Changeset 25ed11d0 in rtems for c/src


Ignore:
Timestamp:
06/17/11 11:58:41 (13 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, 5, master
Children:
18124551
Parents:
1dd95cc
Message:

2011-06-17 Sebastian Huber <sebastian.huber@…>

  • Makefile.am: Added custom memcpy(). Update for network sources.
  • configure.ac: Enable interrupt driven Termios for all BSPs.
  • ide/pcmcia_ide.c: Disable broken DMA support.
  • include/bsp.h: Fixed NEED_LOW_LEVEL_INIT define. Set default console baud to 115200.
  • include/irq.h, irq/irq.c: Fixed interrupt handling to avoid the following problems: 1. multiple invokation of peripheral interrupt handlers, 2. missing synchronization after mask write and enabling of external exceptions, and 3. logic overhead.
  • network_5200/network.c: Added MII interface. Fixed controller restart after FIFO errors. Performance improvements.
  • start/start.S: Fixed ROM startup. Initialize XLB arbiter for all BSPs.
  • startup/bspstart.c: Special intialization for MPC5200B (B variant). Install standard alignment handler.
  • startup/cpuinit.c, startup/linkcmds.brs5l, startup/linkcmds.dp2, startup/linkcmds.icecube, startup/linkcmds.pm520_cr825, startup/linkcmds.pm520_ze30: Avoid accesses outside the RAM area.
Location:
c/src/lib/libbsp/powerpc/gen5200
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/powerpc/gen5200/ChangeLog

    r1dd95cc r25ed11d0  
     12011-06-17      Sebastian Huber <sebastian.huber@embedded-brains.de>
     2
     3        * Makefile.am: Added custom memcpy().  Update for network sources.
     4        * configure.ac: Enable interrupt driven Termios for all BSPs.
     5        * ide/pcmcia_ide.c: Disable broken DMA support.
     6        * include/bsp.h: Fixed NEED_LOW_LEVEL_INIT define.  Set default
     7        console baud to 115200.
     8        * include/irq.h, irq/irq.c: Fixed interrupt handling to avoid the
     9        following problems: 1. multiple invokation of peripheral interrupt
     10        handlers, 2. missing synchronization after mask write and enabling of
     11        external exceptions, and 3. logic overhead.
     12        * network_5200/network.c: Added MII interface.  Fixed controller
     13        restart after FIFO errors.  Performance improvements.
     14        * start/start.S: Fixed ROM startup.  Initialize XLB arbiter for all
     15        BSPs.
     16        * startup/bspstart.c: Special intialization for MPC5200B (B variant).
     17        Install standard alignment handler.
     18        * startup/cpuinit.c, startup/linkcmds.brs5l, startup/linkcmds.dp2,
     19        startup/linkcmds.icecube, startup/linkcmds.pm520_cr825,
     20        startup/linkcmds.pm520_ze30: Avoid accesses outside the RAM area.
     21
    1222011-06-07      Sebastian Huber <sebastian.huber@embedded-brains.de>
    223
  • c/src/lib/libbsp/powerpc/gen5200/Makefile.am

    r1dd95cc r25ed11d0  
    143143        ../../shared/bspgetworkarea.c \
    144144        ../shared/startup/bspidle.c \
     145        ../shared/src/memcpy.c \
    145146        startup/bspstart.c \
    146147        startup/cpuinit.c  \
     
    148149
    149150if HAS_NETWORKING
    150 network_CPPFLAGS = -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
    151 network_CPPFLAGS += -D__BSD_VISIBLE
    152 noinst_PROGRAMS += network.rel
    153 network_rel_SOURCES = network_5200/network.c
    154 network_rel_CPPFLAGS = $(AM_CPPFLAGS) $(network_CPPFLAGS)
    155 network_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
     151libbsp_a_SOURCES += network_5200/network.c
    156152endif
    157153
     
    164160        ../../../libcpu/@RTEMS_CPU@/mpc6xx/timer.rel
    165161
    166 if HAS_NETWORKING
    167 libbsp_a_LIBADD += network.rel
    168 endif
    169 
    170162include $(srcdir)/preinstall.am
    171163include $(top_srcdir)/../../../../automake/local.am
  • c/src/lib/libbsp/powerpc/gen5200/configure.ac

    r1dd95cc r25ed11d0  
    8383RTEMS_BSPOPTS_HELP([MPC5200_PSC_INDEX_FOR_GPS_MODULE],[PSC index for GPS module, if defined results in '/dev/gps'])
    8484
    85 RTEMS_BSPOPTS_SET([SINGLE_CHAR_MODE],[dp2],[])
    86 RTEMS_BSPOPTS_SET([SINGLE_CHAR_MODE],[*],[1])
     85RTEMS_BSPOPTS_SET([SINGLE_CHAR_MODE],[*],[])
    8786RTEMS_BSPOPTS_HELP([SINGLE_CHAR_MODE],[enable single character mode for the PSC console driver])
    8887
    89 RTEMS_BSPOPTS_SET([UARTS_USE_TERMIOS_INT],[dp2],[1])
     88RTEMS_BSPOPTS_SET([UARTS_USE_TERMIOS_INT],[*],[1])
    9089RTEMS_BSPOPTS_HELP([UARTS_USE_TERMIOS_INT],[enable interrupt support for the PSC console driver])
    9190
  • c/src/lib/libbsp/powerpc/gen5200/ide/pcmcia_ide.c

    r1dd95cc r25ed11d0  
    9393#define IDE_DMA_TEST            FALSE
    9494
    95 #ifdef BRS5L
    96 #define IDE_USE_INT             TRUE
    97 #define IDE_READ_USE_DMA        TRUE
    98 #define IDE_USE_READ_PIO_OPT    FALSE
    99 #define IDE_WRITE_USE_DMA       TRUE
    100 #define IDE_USE_WRITE_PIO_OPT   TRUE
    101 /* #define IDE_USE_DMA (IDE_READ_USE_DMA||IDE_WRITE_USE_DMA) */
    102 #define IDE_USE_DMA             TRUE
    103 #else
     95/* DMA supported PIO mode is broken */
    10496#define IDE_USE_INT             TRUE
    10597#define IDE_READ_USE_DMA        FALSE
     
    10799#define IDE_WRITE_USE_DMA       FALSE
    108100#define IDE_USE_WRITE_PIO_OPT   FALSE
    109 /* #define IDE_USE_DMA (IDE_READ_USE_DMA||IDE_WRITE_USE_DMA) */
    110 #define IDE_USE_DMA             FALSE
    111 #endif
     101#define IDE_USE_DMA (IDE_READ_USE_DMA || IDE_WRITE_USE_DMA)
    112102
    113103#define IDE_USE_STATISTICS      TRUE
     
    465455        (*pos) += bufs[bufs_from_dma].length;
    466456        bufs_from_dma++;
     457        bds_free++;
    467458          }
    468459    } while ((nxt_bd_idx != TASK_ERR_BD_RING_EMPTY) &&
  • c/src/lib/libbsp/powerpc/gen5200/include/bsp.h

    r1dd95cc r25ed11d0  
    8080#endif
    8181
     82#if !defined(HAS_UBOOT)
     83  /* we need the low level initialization in start.S*/
     84  #define NEED_LOW_LEVEL_INIT
     85#endif
     86
    8287#if defined(BRS5L)
    8388/*
     
    118123#include <bsp/vectors.h>
    119124#include <bsp/u-boot.h>
    120 
    121 #if !defined(HAS_UBOOT)
    122   /* we need the low level initialization in start.S*/
    123   #define NEED_LOW_LEVEL_INIT
    124 #endif
    125125
    126126/*
     
    180180#define GEN5200_CONSOLE_BAUD (bsp_uboot_board_info.bi_baudrate)
    181181#else
    182 #define GEN5200_CONSOLE_BAUD 9600
     182#define GEN5200_CONSOLE_BAUD 115200
    183183#endif
    184184
  • c/src/lib/libbsp/powerpc/gen5200/include/irq.h

    r1dd95cc r25ed11d0  
    8888#define LIBBSP_POWERPC_GEN5200_IRQ_H
    8989
    90 #define CHK_CE_SHADOW(_pmce)    ((_pmce) & 0x00000001)
    91 #define CHK_CSE_STICKY(_pmce)   (((_pmce) >> 10) & 0x00000001)
    92 #define CHK_MSE_STICKY(_pmce)   (((_pmce) >> 21) & 0x00000001)
    93 #define CHK_PSE_STICKY(_pmce)   (((_pmce) >> 29) & 0x00000001)
    94 #define CLR_CSE_STICKY(_pmce)   ((_pmce) |= (1 << 29 ))
    95 #define CLR_MSE_STICKY(_pmce)   ((_pmce) |= (1 << 21 ))
    96 #define CLR_PSE_STICKY(_pmce)   ((_pmce) |= (1 << 10 ))
    97 #define CSE_SOURCE(_source)     (((_source) >> 8) & 0x00000003)
    98 #define MSE_SOURCE(_source)     (((_source) >> 16) & 0x0000001F)
    99 #define PSE_SOURCE(_source)     (((_source) >> 24) & 0x0000001F)
     90#define PMCE_CE_SHADOW (1U << (31 - 31))
     91#define PMCE_CSE_STICKY (1U << (31 - 21))
     92#define PMCE_MSE_STICKY (1U << (31 - 10))
     93#define PMCE_PSE_STICKY (1U << (31 - 2))
     94#define PMCE_CSE_SOURCE(_pmce) (((_pmce) >> 8) & 0x3U)
     95#define PMCE_MSE_SOURCE(_pmce) (((_pmce) >> 16) & 0x1fU)
     96#define PMCE_PSE_SOURCE(_pmce) (((_pmce) >> 24) & 0x1fU)
    10097
    10198/*
  • c/src/lib/libbsp/powerpc/gen5200/irq/irq.c

    r1dd95cc r25ed11d0  
    172172    prio_index_offset;
    173173  uint32_t *reg;
    174   volatile uint32_t per_pri_1,
    175     main_pri_1,
    176     crit_pri_main_mask,
    177     per_mask;
    178174
    179175  /* calculate the index offset of priority value bit field */
     
    224220  mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]);
    225221
    226   main_pri_1 = mpc5200.main_pri_1;
    227   crit_pri_main_mask = mpc5200.crit_pri_main_mask;
    228   per_pri_1 = mpc5200.per_pri_1;
    229   per_mask = mpc5200.per_mask;
    230 
     222  /* FIXME: Why? */
     223  mpc5200.main_pri_1;
     224  mpc5200.crit_pri_main_mask;
     225  mpc5200.per_pri_1;
     226  mpc5200.per_mask;
    231227}
    232228
     
    485481  #if (ALLOW_IRQ_NESTING == 1)
    486482    uint32_t msr;
     483    uint32_t mask = *maskreg;
    487484  #endif
    488485
    489   uint32_t mask = *maskreg;
    490 
    491486  irq += offset;
    492487
    493   *maskreg = mask | irqMaskTable [irq];
    494 
    495488  #if (ALLOW_IRQ_NESTING == 1)
     489    *maskreg = mask | irqMaskTable [irq];
     490    /* Make sure that the write operation completed (cache inhibited area) */
     491    *maskreg;
    496492    msr = ppc_external_exceptions_enable();
    497493  #endif
     
    501497  #if (ALLOW_IRQ_NESTING == 1)
    502498    ppc_external_exceptions_disable(msr);
     499    *maskreg = mask;
    503500  #endif
    504 
    505   *maskreg = mask;
    506501}
    507502
     
    527522#endif
    528523
    529   switch (excNum) {
    530       /*
    531        * Handle decrementer interrupt
    532        */
    533     case ASM_DEC_VECTOR:
    534 
    535       /* Dispatch interrupt handlers */
    536       bsp_interrupt_handler_dispatch( BSP_DECREMENTER);
    537 
    538       break;
    539 
    540     case ASM_EXT_VECTOR:
    541     case ASM_60X_SYSMGMT_VECTOR:
    542       /* get the content of main interrupt status register */
    543       pmce = mpc5200.pmce;
    544 
    545       /* critical interrupts may be routed to the core_int
    546        * dependent on premature initialization, see bit 31 (CEbsH)
    547        */
    548       while ((CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce))
    549              || CHK_MSE_STICKY( pmce) || CHK_PSE_STICKY( pmce)) {
    550 
    551         /* first: check for critical interrupt sources (hierarchical order)
    552          * -> HI_int indicates peripheral sources
    553          */
    554         if (CHK_CE_SHADOW( pmce) && CHK_CSE_STICKY( pmce)) {
    555           /* get source of critical interrupt */
    556           irq = CSE_SOURCE( pmce);
    557           switch (irq) {
    558               /* irq0, slice timer 1 or ccs wakeup detected */
    559             case 0:
    560             case 1:
    561             case 3:
    562 
    563               /* add proper offset for critical interrupts in the siu
    564                * handler array */
    565               irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
    566 
    567               /* Dispatch interrupt handlers */
    568               bsp_interrupt_handler_dispatch( irq);
    569 
    570               break;
    571 
    572               /* peripheral HI_int interrupt source detected */
    573             case 2:
    574               /* check for valid peripheral interrupt source */
    575               if (CHK_PSE_STICKY( pmce)) {
    576                 /* get source of peripheral interrupt */
    577                 irq = PSE_SOURCE( pmce);
    578 
    579                 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
    580 
    581                 /* force re-evaluation of peripheral interrupts */
    582                 CLR_PSE_STICKY( mpc5200.pmce);
    583               } else {
    584                 /* this case may not occur: no valid peripheral
    585                  * interrupt source */
    586                 printk( "No valid peripheral HI_int interrupt source\n");
    587               }
    588               break;
    589             default:
    590               /* error: unknown interrupt source */
    591               printk( "Unknown HI_int interrupt source\n");
    592               break;
     524  /* get the content of main interrupt status register */
     525  pmce = mpc5200.pmce;
     526
     527  /* critical interrupts are routed to the core_int, see premature
     528   * initialization
     529   */
     530  while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) {
     531    /* first: check for critical interrupt sources (hierarchical order)
     532     * -> HI_int indicates peripheral sources
     533     */
     534    if ((pmce & PMCE_CSE_STICKY) != 0) {
     535      /* get source of critical interrupt */
     536      irq = PMCE_CSE_SOURCE(pmce);
     537
     538      switch (irq) {
     539          /* peripheral HI_int interrupt source detected */
     540        case 2:
     541          /* check for valid peripheral interrupt source */
     542          if ((pmce & PMCE_PSE_STICKY) != 0) {
     543            /* get source of peripheral interrupt */
     544            irq = PMCE_PSE_SOURCE(pmce);
     545
     546            dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
     547          } else {
     548            /* this case may not occur: no valid peripheral
     549             * interrupt source */
     550            printk( "No valid peripheral HI_int interrupt source\n");
    593551          }
    594           /* force re-evaluation of critical interrupts */
    595           CLR_CSE_STICKY( mpc5200.pmce);
    596         }
    597 
    598         /* second: check for main interrupt sources (hierarchical order)
    599          * -> LO_int indicates peripheral sources */
    600         if (CHK_MSE_STICKY( pmce)) {
    601           /* get source of main interrupt */
    602           irq = MSE_SOURCE( pmce);
    603 
    604           switch (irq) {
    605 
    606               /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
    607                * 2 is always routed to SMI) */
    608             case 0:
    609             case 1:
    610             case 2:
    611             case 3:
    612             case 5:
    613             case 6:
    614             case 7:
    615             case 8:
    616             case 9:
    617             case 10:
    618             case 11:
    619             case 12:
    620             case 13:
    621             case 14:
    622             case 15:
    623             case 16:
    624               dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
    625               break;
    626 
    627               /* peripheral LO_int interrupt source detected */
    628             case 4:
    629               /* check for valid peripheral interrupt source */
    630               if (CHK_PSE_STICKY( pmce)) {
    631                 /* get source of peripheral interrupt */
    632                 irq = PSE_SOURCE( pmce);
    633 
    634                 dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
    635 
    636                 /* force re-evaluation of peripheral interrupts */
    637                 CLR_PSE_STICKY( mpc5200.pmce);
    638               } else {
    639                 /* this case may not occur: no valid peripheral
    640                  * interrupt source */
    641                 printk( "No valid peripheral LO_int interrupt source\n");
    642               }
    643               break;
    644 
    645               /* error: unknown interrupt source */
    646             default:
    647               printk( "Unknown peripheral LO_int interrupt source\n");
    648               break;
     552          break;
     553
     554          /* irq0, slice timer 1 or ccs wakeup detected */
     555        case 0:
     556        case 1:
     557        case 3:
     558
     559          /* add proper offset for critical interrupts in the siu
     560           * handler array */
     561          irq += BSP_CRIT_IRQ_LOWEST_OFFSET;
     562
     563          /* Dispatch interrupt handlers */
     564          bsp_interrupt_handler_dispatch( irq);
     565
     566          break;
     567
     568        default:
     569          /* error: unknown interrupt source */
     570          printk( "Unknown HI_int interrupt source\n");
     571          break;
     572      }
     573    }
     574
     575    /* second: check for main interrupt sources (hierarchical order)
     576     * -> LO_int indicates peripheral sources */
     577    if ((pmce & PMCE_MSE_STICKY) != 0) {
     578      /* get source of main interrupt */
     579      irq = PMCE_MSE_SOURCE(pmce);
     580
     581      if (irq == 4) {
     582          /* peripheral LO_int interrupt source detected */
     583          /* check for valid peripheral interrupt source */
     584          if ((pmce & PMCE_PSE_STICKY) != 0) {
     585            /* get source of peripheral interrupt */
     586            irq = PMCE_PSE_SOURCE(pmce);
     587
     588            dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
     589          } else {
     590            /* this case may not occur: no valid peripheral
     591             * interrupt source */
     592            printk( "No valid peripheral LO_int interrupt source\n");
    649593          }
    650           /* force re-evaluation of main interrupts */
    651           CLR_MSE_STICKY( mpc5200.pmce);
    652         }
    653 
    654         if (CHK_PSE_STICKY( pmce)) {
    655           /* get source of peripheral interrupt */
    656           irq = PSE_SOURCE( pmce);
    657 
    658           dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask);
    659 
    660           /* force re-evaluation of peripheral interrupts */
    661           CLR_PSE_STICKY( mpc5200.pmce);
    662         }
    663 
    664         /* get the content of main interrupt status register */
    665         pmce = mpc5200.pmce;
     594      } else if (irq <= 16) {
     595          /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer
     596           * 2 is always routed to SMI) */
     597          dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask);
     598      } else {
     599          /* error: unknown interrupt source */
     600          printk( "Unknown peripheral LO_int interrupt source\n");
    666601      }
    667       break;
    668 
    669     default:
    670       printk( "Unknown processor exception\n");
    671       break;
    672 
    673   }                             /* end of switch( excNum) */
     602    }
     603
     604    /* force re-evaluation of interrupts */
     605    mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY;
     606
     607    /* get the content of main interrupt status register */
     608    pmce = mpc5200.pmce;
     609  }
    674610
    675611#if (BENCHMARK_IRQ_PROCESSING == 1)
     
    772708    return RTEMS_IO_ERROR;
    773709  }
    774   if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) {
    775     return RTEMS_IO_ERROR;
    776   }
    777710  if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) {
    778711    return RTEMS_IO_ERROR;
  • c/src/lib/libbsp/powerpc/gen5200/network_5200/network.c

    r1dd95cc r25ed11d0  
    5454 *
    5555 */
     56
     57#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ 1
     58#define __BSD_VISIBLE 1
     59
    5660#include <rtems.h>
    5761#include <rtems/error.h>
    5862#include <rtems/rtems_bsdnet.h>
     63#include <rtems/rtems_mii_ioctl.h>
    5964#include <stdio.h>
     65#include <inttypes.h>
    6066#include <sys/param.h>
    6167#include <sys/mbuf.h>
     
    6773#include <bsp.h>
    6874#include <bsp/irq.h>
    69 #include "../include/mpc5200.h"
     75#include <bsp/mpc5200.h>
    7076#include <net/if_var.h>
    7177#include <errno.h>
    7278
    73 /* motorola-capi-specifics... */
    74 #include "../bestcomm/include/ppctypes.h"       /* uint32, et. al.                      */
    75 #include "../bestcomm/dma_image.h"
    76 #include "../bestcomm/bestcomm_glue.h"
    77 
    78 
    79 #define SDMA_BD_TFD     0x08000000      /*< Transmit Frame Done         */
    80 #define SDMA_BD_INT     0x04000000      /*< Interrupt on frame done     */
    81 #define SDMA_BD_RX_NUM  64 /* Number of receive buffer descriptors      */
    82 #define SDMA_BD_TX_NUM  64 /* Number of transmit buffer descriptors     */
    83 
    84 #define SET_BD_STATUS(bd, stat) {               \
    85         (bd)->Status &= 0x0000ffff;                     \
    86         (bd)->Status |= 0xffff0000 & stat;      \
    87 }
    88 #define SET_BD_LENGTH(bd, len) {                \
    89         (bd)->Status &= 0xffff0000;                     \
    90         (bd)->Status |= 0x0000ffff & len;       \
    91 }
    92 #define GET_BD_STATUS(bd)               ((bd)->Status & 0xffff0000)
    93 #define GET_BD_LENGTH(bd)               ((bd)->Status & 0x0000ffff)
    94 #define GET_SDMA_PENDINGBIT(Bit)   \
    95    (mpc5200.sdma.IntPend & (uint32)(1<<Bit))
    96 
    97 #include "../bestcomm/bestcomm_api.h"
    98 #include "../bestcomm/task_api/bestcomm_cntrl.h"
    99 #include "../bestcomm/task_api/tasksetup_bdtable.h"
    100 
    101 static TaskId rxTaskId; /* SDMA RX task ID */
    102 static TaskId txTaskId; /* SDMA TX task ID */
     79#include <bsp/bestcomm/include/ppctypes.h>
     80#include <bsp/bestcomm/dma_image.h>
     81#include <bsp/bestcomm/bestcomm_glue.h>
     82#include <bsp/bestcomm/bestcomm_api.h>
     83#include <bsp/bestcomm/task_api/bestcomm_cntrl.h>
     84#include <bsp/bestcomm/task_api/tasksetup_bdtable.h>
    10385
    10486/* #define ETH_DEBUG */
     87
     88#define FEC_BD_LAST TASK_BD_TFD
     89#define FEC_BD_INT TASK_BD_INT
     90#define FEC_BD_READY SDMA_BD_MASK_READY
    10591
    10692/*
     
    114100 * since a single frame often uses four or more buffer descriptors.
    115101 */
    116 #define RX_BUF_COUNT     SDMA_BD_RX_NUM
    117 #define TX_BUF_COUNT     SDMA_BD_TX_NUM
    118 #define TX_BD_PER_BUF    1
     102#define RX_BUF_COUNT     64
     103#define TX_BUF_COUNT     64
    119104
    120105#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255")
    121106
    122 
    123 /*
    124  * RTEMS event used by interrupt handler to signal daemons.
    125  * This must *not* be the same event used by the TCP/IP task synchronization.
    126  */
    127 #define INTERRUPT_EVENT RTEMS_EVENT_1
    128 #define FATAL_INT_EVENT RTEMS_EVENT_3
    129 
    130 /*
    131  * RTEMS event used to start transmit daemon.
    132  * This must not be the same as INTERRUPT_EVENT.
    133  */
    134 #define START_TRANSMIT_EVENT RTEMS_EVENT_2
     107#define FEC_EVENT RTEMS_EVENT_0
    135108
    136109/* Task number assignment */
     
    187160#define MPC5200_FEC_MII_DATA_PA_SHIFT 0x17      /* MII PHY address bits */
    188161
    189 
    190 /* Receive & Transmit Buffer Descriptor definitions */
    191 typedef struct mpc5200_buffer_desc_
    192   {
    193   volatile uint16_t status;
    194   volatile uint16_t length;
    195   volatile void             *buffer;
    196   } mpc5200_buffer_desc_t;
    197 
    198 
    199162#define FEC_INTR_MASK_USED \
    200163(FEC_INTR_LCEN  |FEC_INTR_CRLEN |\
    201164 FEC_INTR_XFUNEN|FEC_INTR_XFERREN|FEC_INTR_RFERREN)
    202165
     166typedef enum {
     167  FEC_STATE_RESTART_0,
     168  FEC_STATE_RESTART_1,
     169  FEC_STATE_NORMAL,
     170} mpc5200_fec_state;
     171
    203172/*
    204173 * Device data
    205174 */
    206 struct mpc5200_enet_struct {
    207 #if 0
    208   struct ifnet            ac_if;
    209 #else
     175typedef struct {
    210176  struct arpcom           arpcom;
    211 #endif
    212177  struct mbuf             **rxMbuf;
    213178  struct mbuf             **txMbuf;
     179  mpc5200_fec_state       state;
    214180  int                     acceptBroadcast;
    215181  int                     rxBdCount;
     
    227193  unsigned long           rxNonOctet;
    228194  unsigned long           rxBadCRC;
    229   unsigned long           rxOverrun;
     195  unsigned long           rxFIFOError;
    230196  unsigned long           rxCollision;
    231197
     
    234200  unsigned long           txLateCollision;
    235201  unsigned long           txUnderrun;
     202  unsigned long           txFIFOError;
    236203  unsigned long           txMisaligned;
    237204  unsigned long           rxNotFirst;
    238205  unsigned long           txRetryLimit;
    239   };
    240 
    241 static struct mpc5200_enet_struct enet_driver[NIFACES];
    242 
    243 extern int taskTable;
    244 static void mpc5200_fec_restart(struct mpc5200_enet_struct *sc);
    245 
    246 
    247 
    248 /*
    249  * Function:    mpc5200_fec_rx_bd_init
    250  *
    251  * Description: Initialize the receive buffer descriptor ring.
    252  *
    253  * Returns:             void
    254  *
    255  * Notes:       Space for the buffers of rx BDs is allocated by the rx deamon
    256  *
    257  */
    258 static void mpc5200_fec_rx_bd_init(struct mpc5200_enet_struct *sc) {
    259   int rxBdIndex;
    260   struct mbuf *m;
    261   struct ifnet *ifp = &sc->arpcom.ac_if;
    262   BDIdx bdi;
    263 
    264   /*
    265    * Fill RX buffer descriptor ring.
    266    */
    267   for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) {
    268     MGETHDR (m, M_WAIT, MT_DATA);
    269     MCLGET (m, M_WAIT);
    270 
    271     m->m_pkthdr.rcvif = ifp;
    272     sc->rxMbuf[rxBdIndex] = m;
    273     bdi = TaskBDAssign( rxTaskId,
    274                         mtod(m, void *),
    275                         NULL,
    276                         ETHER_MAX_LEN,
    277                         0 );
    278     if (bdi != rxBdIndex) {
    279       rtems_panic("network rx buffer indices out of sync");
    280     }
    281   }
    282 }
    283 
    284 /*
    285  * Function:    mpc5200_fec_rx_bd_cleanup
    286  *
    287  * Description: put all mbufs pending in rx BDs back to buffer pool
    288  *
    289  * Returns:             void
    290  *
    291  */
    292 static void mpc5200_fec_rx_bd_cleanup(struct mpc5200_enet_struct *sc) {
    293   int rxBdIndex;
    294   struct mbuf *m,*n;
    295 
    296   /*
    297    * Drain RX buffer descriptor ring.
    298    */
    299   for( rxBdIndex = 0; rxBdIndex < sc->rxBdCount; rxBdIndex++ ) {
    300     n = sc->rxMbuf[rxBdIndex];
    301     while (n != NULL) {
    302       m = n;
    303       MFREE(m,n);
    304     }
    305   }
     206
     207  struct rtems_mdio_info  mdio;
     208  int                     phyAddr;
     209  bool                    phyInitialized;
     210} mpc5200_fec_context;
     211
     212static mpc5200_fec_context enet_driver[NIFACES];
     213
     214static void mpc5200_fec_send_event(rtems_id task)
     215{
     216  rtems_event_send(task, FEC_EVENT);
     217}
     218
     219static void mpc5200_fec_wait_for_event(void)
     220{
     221  rtems_event_set out;
     222  rtems_bsdnet_event_receive(
     223    FEC_EVENT,
     224    RTEMS_EVENT_ANY | RTEMS_WAIT,
     225    RTEMS_NO_TIMEOUT,
     226    &out
     227  );
     228}
     229
     230static void mpc5200_fec_stop_dma(void)
     231{
     232  TaskStop(FEC_RECV_TASK_NO);
     233  TaskStop(FEC_XMIT_TASK_NO);
     234}
     235
     236static void mpc5200_fec_request_restart(mpc5200_fec_context *self)
     237{
     238  self->state = FEC_STATE_RESTART_0;
     239  mpc5200_fec_send_event(self->txDaemonTid);
     240  mpc5200_fec_send_event(self->rxDaemonTid);
     241}
     242
     243static void mpc5200_fec_start_dma_and_controller(void)
     244{
     245  TaskStart(FEC_RECV_TASK_NO, 1, FEC_RECV_TASK_NO, 1);
     246  TaskStart(FEC_XMIT_TASK_NO, 1, FEC_XMIT_TASK_NO, 1);
     247
     248  mpc5200.ecntrl |= FEC_ECNTRL_OE | FEC_ECNTRL_EN;
    306249}
    307250
     
    317260 *
    318261 */
    319 static void mpc5200_eth_addr_filter_set(struct mpc5200_enet_struct *sc)  {
     262static void mpc5200_eth_addr_filter_set(mpc5200_fec_context *self)  {
    320263  unsigned char *mac;
    321264  unsigned char currByte;                               /* byte for which to compute the CRC */
     
    327270  * Get the mac address of ethernet controller
    328271  */
    329   mac = (unsigned char *)(&sc->arpcom.ac_enaddr);
     272  mac = (unsigned char *)(&self->arpcom.ac_enaddr);
    330273
    331274 /*
     
    400343   }
    401344
     345static int mpc5200_eth_mii_transfer(
     346  int phyAddr,
     347  unsigned regAddr,
     348  uint32_t data
     349)
     350{
     351  int timeout = 0xffff;
     352
     353  mpc5200.ievent = FEC_INTR_MII;
     354
     355  mpc5200.mii_data = MPC5200_FEC_MII_DATA_ST
     356    | MPC5200_FEC_MII_DATA_TA
     357    | (phyAddr << MPC5200_FEC_MII_DATA_PA_SHIFT)
     358    | (regAddr << MPC5200_FEC_MII_DATA_RA_SHIFT)
     359    | data;
     360
     361  while (timeout > 0 && (mpc5200.ievent & FEC_INTR_MII) == 0) {
     362    --timeout;
     363  }
     364
     365  return timeout > 0 ? 0 : -1;
     366}
     367
     368/* FIXME: Make this static, this needs a fix in an application */
     369int mpc5200_eth_mii_read(
     370  int phyAddr,
     371  void *arg,
     372  unsigned regAddr,
     373  uint32_t *retVal
     374)
     375{
     376  int rv = mpc5200_eth_mii_transfer(
     377    phyAddr,
     378    regAddr,
     379    MPC5200_FEC_MII_DATA_OP_RD
     380  );
     381
     382  *retVal = mpc5200.mii_data & 0xffff;
     383
     384  return rv;
     385}
     386
     387static int mpc5200_eth_mii_write(
     388  int phyAddr,
     389  void *arg,
     390  unsigned regAddr,
     391  uint32_t data
     392)
     393{
     394  return mpc5200_eth_mii_transfer(
     395    phyAddr,
     396    regAddr,
     397    MPC5200_FEC_MII_DATA_OP_WR | data
     398  );
     399}
     400
    402401
    403402/*
    404  * Function:    mpc5200_eth_mii_read
    405  *
    406  * Description: Read a media independent interface (MII) register on an
    407  *                              18-wire ethernet tranceiver (PHY). Please see your PHY
    408  *                              documentation for the register map.
    409  *
    410  * Returns:             32-bit register value
    411  *
    412  * Notes:
    413  *
     403 * Reset a running ethernet driver including the hardware FIFOs and the FEC.
    414404 */
    415 int mpc5200_eth_mii_read(struct mpc5200_enet_struct *sc, unsigned char phyAddr, unsigned char regAddr, unsigned short * retVal)
    416   {
    417   unsigned long reg;            /* convenient holder for the PHY register */
    418   unsigned long phy;            /* convenient holder for the PHY */
    419   int timeout = 0xffff;
    420 
    421  /*
    422   * reading from any PHY's register is done by properly
    423   * programming the FEC's MII data register.
    424   */
    425   reg = regAddr << MPC5200_FEC_MII_DATA_RA_SHIFT;
    426   phy = phyAddr << MPC5200_FEC_MII_DATA_PA_SHIFT;
    427 
    428   mpc5200.mii_data = (MPC5200_FEC_MII_DATA_ST | MPC5200_FEC_MII_DATA_OP_RD | MPC5200_FEC_MII_DATA_TA | phy | reg);
    429 
    430  /*
    431   * wait for the related interrupt
    432   */
    433   while ((timeout--) && (!(mpc5200.ievent & 0x00800000)));
    434 
    435   if(timeout == 0)
    436     {
    437 
    438 #ifdef ETH_DEBUG
    439     printf ("Read MDIO failed..." "\r\n");
    440 #endif
    441 
    442         return false;
    443 
    444         }
    445 
    446  /*
    447   * clear mii interrupt bit
    448   */
    449   mpc5200.ievent = 0x00800000;
    450 
    451  /*
    452   * it's now safe to read the PHY's register
    453   */
    454   *retVal = (unsigned short)mpc5200.mii_data;
    455 
    456   return true;
    457 
    458   }
    459 
    460 /*
    461  * Function:    mpc5200_eth_mii_write
    462  *
    463  * Description: Write a media independent interface (MII) register on an
    464  *                              18-wire ethernet tranceiver (PHY). Please see your PHY
    465  *                              documentation for the register map.
    466  *
    467  * Returns:             Success (boolean)
    468  *
    469  * Notes:
    470  *
    471  */
    472 static int mpc5200_eth_mii_write(struct mpc5200_enet_struct *sc, unsigned char phyAddr, unsigned char regAddr, unsigned short data)
    473   {
    474   unsigned long reg;                                    /* convenient holder for the PHY register */
    475   unsigned long phy;                                    /* convenient holder for the PHY */
    476   int timeout = 0xffff;
    477 
    478   reg = regAddr << MPC5200_FEC_MII_DATA_RA_SHIFT;
    479   phy = phyAddr << MPC5200_FEC_MII_DATA_PA_SHIFT;
    480 
    481   mpc5200.mii_data = (MPC5200_FEC_MII_DATA_ST | MPC5200_FEC_MII_DATA_OP_WR | MPC5200_FEC_MII_DATA_TA | phy | reg | data);
    482 
    483  /*
    484   * wait for the MII interrupt
    485   */
    486   while ((timeout--) && (!(mpc5200.ievent & 0x00800000)));
    487 
    488   if(timeout == 0)
    489     {
    490 
    491 #ifdef ETH_DEBUG
    492     printf ("Write MDIO failed..." "\r\n");
    493 #endif
    494 
    495     return false;
    496 
    497     }
    498 
    499  /*
    500   * clear MII interrupt bit
    501   */
    502   mpc5200.ievent = 0x00800000;
    503 
    504   return true;
    505 
    506   }
    507 
    508 
    509 /*
    510  * Function:    mpc5200_fec_reset
    511  *
    512  * Description: Reset a running ethernet driver including the hardware
    513  *                              FIFOs and the FEC.
    514  *
    515  * Returns:             Success (boolean)
    516  *
    517  * Notes:
    518  *
    519  */
    520 static int mpc5200_fec_reset(struct mpc5200_enet_struct *sc) {
     405static void mpc5200_fec_reset(mpc5200_fec_context *self)
     406{
    521407  volatile int delay;
    522408  /*
     
    544430   */
    545431  for (delay = 0;delay < 16*4;delay++) {};
    546 
    547   return true;
    548432}
    549433
     
    560444 *
    561445 */
    562 void mpc5200_fec_off(struct mpc5200_enet_struct *sc)
     446void mpc5200_fec_off(mpc5200_fec_context *self)
    563447  {
    564448  int            counter = 0xffff;
     
    566450
    567451#if defined(ETH_DEBUG)
    568   unsigned short phyStatus, i;
    569   unsigned char  phyAddr = 0;
     452  uint32_t phyStatus;
     453  int i;
    570454
    571455  for(i = 0; i < 9; i++)
    572456    {
    573457
    574     mpc5200_eth_mii_read(sc, phyAddr, i, &phyStatus);
    575     printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
     458    mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus);
     459    printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus);
    576460
    577461    }
     
    580464    {
    581465
    582     mpc5200_eth_mii_read(sc, phyAddr, i, &phyStatus);
    583     printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
     466    mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus);
     467    printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus);
    584468
    585469    }
     
    602486  while((counter--) && (!(mpc5200.ievent & FEC_INTR_GRA)));
    603487
    604   /*
    605    * Disable the SmartDMA transmit and receive tasks.
    606    */
    607   TaskStop( rxTaskId );
    608   TaskStop( txTaskId );
     488  mpc5200_fec_stop_dma();
     489
    609490 /*
    610491  * Disable transmit / receive interrupts
     
    617498  */
    618499  mpc5200.ecntrl &= ~(FEC_ECNTRL_OE | FEC_ECNTRL_EN);
    619 
    620   /*
    621    * cleanup all buffers
    622    */
    623   mpc5200_fec_rx_bd_cleanup(sc);
    624 
    625   }
     500}
    626501
    627502/*
     
    630505void mpc5200_fec_irq_handler(rtems_irq_hdl_param handle)
    631506{
    632   struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *) handle;
     507  mpc5200_fec_context *self = (mpc5200_fec_context *) handle;
    633508  volatile uint32_t ievent;
    634509
     
    640515   */
    641516  if (ievent & FEC_INTR_LATE_COL) {
    642     sc->txLateCollision++;
     517    self->txLateCollision++;
    643518  }
    644519  if (ievent & FEC_INTR_COL_RETRY) {
    645     sc->txRetryLimit++;
     520    self->txRetryLimit++;
    646521  }
    647522  if (ievent & FEC_INTR_XFIFO_UN) {
    648     sc->txUnderrun++;
     523    self->txUnderrun++;
    649524  }
    650525  if (ievent & FEC_INTR_XFIFO_ERR) {
    651     sc->txUnderrun++;
     526    self->txFIFOError++;
    652527  }
    653528  if (ievent & FEC_INTR_RFIFO_ERR) {
    654     sc->rxOverrun++;
     529    self->rxFIFOError++;
    655530  }
    656531  /*
     
    659534  if (ievent & (FEC_INTR_XFIFO_ERR | FEC_INTR_RFIFO_ERR)) {
    660535    mpc5200.imask &= ~(FEC_INTR_XFERREN | FEC_INTR_RFERREN);
    661     rtems_event_send(enet_driver[0].rxDaemonTid, FATAL_INT_EVENT);
    662   }
    663 }
    664 
    665 /*
    666  * MPC5200 SmartComm ethernet interrupt handler
    667  */
    668 void mpc5200_smartcomm_rx_irq_handler(rtems_irq_hdl_param unused)
    669   {
    670  /* Frame received? */
    671   if(GET_SDMA_PENDINGBIT(FEC_RECV_TASK_NO))
    672     {
    673 
    674       SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_RECV_TASK_NO);
    675 
    676       bestcomm_glue_irq_disable(FEC_RECV_TASK_NO);/*Disable receive ints*/
    677 
    678       enet_driver[0].rxInterrupts++;            /* Rx int has occurred */
    679 
    680       rtems_event_send(enet_driver[0].rxDaemonTid, INTERRUPT_EVENT);
    681 
    682     }
    683   }
    684 
    685 /*
    686  * MPC5200 SmartComm ethernet interrupt handler
    687  */
    688 void mpc5200_smartcomm_tx_irq_handler(rtems_irq_hdl_param unused)
    689   {
    690  /* Buffer transmitted or transmitter error? */
    691   if(GET_SDMA_PENDINGBIT(FEC_XMIT_TASK_NO))
    692     {
    693 
    694       SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_XMIT_TASK_NO);
    695 
    696       bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO);/*Disable tx ints*/
    697 
    698       enet_driver[0].txInterrupts++; /* Tx int has occurred */
    699 
    700       rtems_event_send(enet_driver[0].txDaemonTid, INTERRUPT_EVENT);
    701 
    702     }
    703 
    704   }
    705 
    706 
    707 
    708 
    709 
    710  /*
    711   * Function:       mpc5200_fec_retire_tbd
    712   *
    713   * Description:        Soak up buffer descriptors that have been sent.
    714   *
    715   * Returns:            void
    716   *
    717   * Notes:
    718   *
    719   */
    720 static void mpc5200_fec_retire_tbd(struct mpc5200_enet_struct *sc,
    721                                    bool force)
    722 {
    723   struct mbuf *n;
    724   TaskBD1_t   *bdRing = (TaskBD1_t *)TaskGetBDRing( txTaskId );;
    725   /*
    726    * Clear already transmitted BDs first. Will not work calling same
    727    * from fecExceptionHandler(TFINT).
    728    */
    729 
    730   while ((sc->txBdActiveCount > 0) &&
    731          (force || (bdRing[sc->txBdTail].Status == 0x0))) {
    732     if (sc->txMbuf[sc->txBdTail] != NULL) {
    733       /*
    734        * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs
    735        */
    736       MFREE (sc->txMbuf[sc->txBdTail],n);
    737       sc->txMbuf[sc->txBdTail] = NULL;
    738     }
    739     sc->txBdActiveCount--;
    740     if(++sc->txBdTail >= sc->txBdCount) {
    741       sc->txBdTail = 0;
    742     }
    743   }
    744 }
    745 
    746 #if 0
    747  /*
    748   * Function:        mpc5200_fec_tx_bd_requeue
    749   *
    750   * Description:        put buffers back to interface output queue
    751   *
    752   * Returns:            void
    753   *
    754   * Notes:
    755   *
    756   */
    757 static void mpc5200_fec_tx_bd_requeue(struct mpc5200_enet_struct *sc)
    758 {
    759   /*
    760    * Clear already transmitted BDs first. Will not work calling same
    761    * from fecExceptionHandler(TFINT).
    762    */
    763 
    764   while (sc->txBdActiveCount > 0) {
    765     if (sc->txMbuf[sc->txBdHead] != NULL) {
    766       /*
    767        * NOTE: txMbuf can be NULL, if mbuf has been split into different BDs
    768        */
    769       IF_PREPEND(&(sc->arpcom.ac_if.if_snd),sc->txMbuf[sc->txBdHead]);
    770       sc->txMbuf[sc->txBdHead] = NULL;
    771     }
    772     sc->txBdActiveCount--;
    773     if(--sc->txBdHead < 0) {
    774       sc->txBdHead = sc->txBdCount-1;
    775     }
    776   }
    777 }
    778 #endif
    779 
    780 static void mpc5200_fec_sendpacket(struct ifnet *ifp,struct mbuf *m) {
    781   struct mpc5200_enet_struct *sc = ifp->if_softc;
    782   struct mbuf *l = NULL;
    783   int nAdded;
    784   uint32_t status;
    785   rtems_event_set events;
    786   TaskBD1_t *bdRing = (TaskBD1_t *)TaskGetBDRing( txTaskId );
    787   TaskBD1_t *thisBd;
    788   TaskBD1_t *firstBd = NULL;
    789   void *data_ptr;
    790   size_t data_len;
    791 
    792  /*
    793   * Free up buffer descriptors
    794   */
    795   mpc5200_fec_retire_tbd(sc,false);
    796 
    797  /*
    798   * Set up the transmit buffer descriptors.
    799   * No need to pad out short packets since the
    800   * hardware takes care of that automatically.
    801   * No need to copy the packet to a contiguous buffer
    802   * since the hardware is capable of scatter/gather DMA.
    803   */
    804   nAdded = 0;
    805 
    806   for(;;) {
    807 
    808    /*
    809     * Wait for buffer descriptor to become available.
    810     */
    811     if((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
    812 
    813       /*
    814        * Clear old events
    815        */
    816       SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_XMIT_TASK_NO);
    817 
    818       /*
    819        * Wait for buffer descriptor to become available.
    820        * Note that the buffer descriptors are checked
    821        * *before* * entering the wait loop -- this catches
    822        * the possibility that a buffer descriptor became
    823        * available between the `if' above, and the clearing
    824        * of the event register.
    825        * This is to catch the case where the transmitter
    826        * stops in the middle of a frame -- and only the
    827        * last buffer descriptor in a frame can generate
    828        * an interrupt.
    829        */
    830       mpc5200_fec_retire_tbd(sc,false);
    831 
    832       while((sc->txBdActiveCount + nAdded) == sc->txBdCount) {
    833         bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO);
    834         rtems_bsdnet_event_receive(INTERRUPT_EVENT,
    835                                    RTEMS_WAIT | RTEMS_EVENT_ANY,
    836                                    RTEMS_NO_TIMEOUT, &events);
    837         mpc5200_fec_retire_tbd(sc,false);
    838       }
    839     }
    840 
    841     if(m->m_len == 0) {
    842       /*
    843        * Just toss empty mbufs
    844        */
    845       struct mbuf *n;
    846       MFREE(m, n);
    847       m = n;
    848       if(l != NULL) {
    849         l->m_next = m;
    850       }
    851     }
    852     else {
    853       /*
    854        * Flush the buffer for this descriptor
    855        */
    856       /*rtems_cache_flush_multiple_data_lines((const void *)mtod(m, void *), m->m_len);*/
    857       /*
    858        * Fill in the buffer descriptor,
    859        * set "end of frame" bit in status,
    860        * if last mbuf in chain
    861        */
    862       thisBd             = bdRing + sc->txBdHead;
    863       /*
    864        * FIXME: do not send interrupt after every frame
    865        * doing this every quarter of BDs is much more efficent
    866        */
    867       status             = ((m->m_next == NULL)
    868                             ? TASK_BD_TFD | TASK_BD_INT
    869                             : 0);
    870       /*
    871        * Don't set the READY flag till the
    872        * whole packet has been readied.
    873        */
    874       if (firstBd != NULL) {
    875         status |= (uint32)SDMA_BD_MASK_READY;
    876       }
    877       else {
    878         firstBd = thisBd;
    879       }
    880 
    881       data_ptr = mtod(m, void *);
    882       data_len = (uint32)m->m_len;
    883       sc->txMbuf[sc->txBdHead] = m;
    884       /* go to next part in chain */
    885       l = m;
    886       m = m->m_next;
    887 
    888       thisBd->DataPtr[0] = (uint32)data_ptr;
    889       thisBd->Status     = (status
    890                             |((uint32)SDMA_DRD_MASK_LENGTH & data_len));
    891 
    892       nAdded++;
    893       if(++(sc->txBdHead) == sc->txBdCount) {
    894         sc->txBdHead = 0;
    895       }
    896     }
    897     /*
    898      * Set the transmit buffer status.
    899      * Break out of the loop if this mbuf is the last in the frame.
    900      */
    901     if(m == NULL) {
    902       if(nAdded) {
    903         firstBd->Status     |= SDMA_BD_MASK_READY;
    904         SDMA_TASK_ENABLE(SDMA_TCR, txTaskId);
    905         sc->txBdActiveCount += nAdded;
    906       }
    907       break;
    908     }
    909   } /* end of for(;;) */
    910 }
    911 
    912 
    913 /*
    914  * Driver transmit daemon
    915  */
    916 void mpc5200_fec_txDaemon(void *arg)
    917   {
    918   struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *)arg;
    919   struct ifnet *ifp = &sc->arpcom.ac_if;
    920   struct mbuf *m;
    921   rtems_event_set events;
    922 
    923   for(;;) {
    924    /*
    925     * Wait for packet
    926     */
    927     bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO);
    928     rtems_bsdnet_event_receive(START_TRANSMIT_EVENT|INTERRUPT_EVENT,
    929                                RTEMS_EVENT_ANY | RTEMS_WAIT,
    930                                RTEMS_NO_TIMEOUT,
    931                                &events);
    932 
    933     /*
    934      * Send packets till queue is empty
    935      */
    936     for(;;)
    937       {
    938 
    939       /*
    940        * Get the next mbuf chain to transmit.
    941        */
    942       IF_DEQUEUE(&ifp->if_snd, m);
    943 
    944       if (!m)
    945         break;
    946 
    947       mpc5200_fec_sendpacket(ifp, m);
    948 
    949       }
    950 
    951     ifp->if_flags &= ~IFF_OACTIVE;
    952 
    953     }
    954 
    955   }
    956 
    957 
    958 /*
    959  * reader task
    960  */
    961 static void mpc5200_fec_rxDaemon(void *arg){
    962   struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *)arg;
    963   struct ifnet *ifp = &sc->arpcom.ac_if;
    964   struct mbuf *m;
    965   struct ether_header *eh;
    966   int rxBdIndex;
    967   uint32_t status;
    968   size_t size;
    969   rtems_event_set events;
    970   uint16    len = 1;
    971   TaskBD1_t *bd;
    972   void      *dptr;
    973   TaskBD1_t   *bdRing = (TaskBD1_t *)TaskGetBDRing( rxTaskId );;
    974 
    975   /*
    976    * Input packet handling loop
    977    */
    978   rxBdIndex = 0;
    979 
    980   for (;;) {
    981     /*
    982      * Clear old events
    983      */
    984     SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend,FEC_RECV_TASK_NO);
    985     /*
    986      * Get the first BD pointer and its length.
    987      */
    988     bd     = bdRing + rxBdIndex;
    989     status = bd->Status;
    990     len    = (uint16)GET_BD_LENGTH( bd );
    991 
    992     /*
    993      * Loop through BDs until we find an empty one. This indicates that
    994      * the SmartDMA is still using it.
    995      */
    996     while( !(status & SDMA_BD_MASK_READY) ) {
    997 
    998       /*
    999        * Remember the data pointer from this transfer.
    1000        */
    1001       dptr = (void *)bd->DataPtr[0];
    1002       m    = sc->rxMbuf[rxBdIndex];
    1003       m->m_len = m->m_pkthdr.len = (len
    1004                                     - sizeof(uint32_t)
    1005                                     - sizeof(struct ether_header));
    1006       eh = mtod(m, struct ether_header *);
    1007       m->m_data += sizeof(struct ether_header);
    1008       ether_input(ifp, eh, m);
    1009 
    1010       /*
    1011        * Done w/ the BD. Clean it.
    1012        */
    1013       sc->rxMbuf[rxBdIndex] = NULL;
    1014 
    1015       /*
    1016        * Add a new buffer to the ring.
    1017        */
    1018       MGETHDR (m, M_WAIT, MT_DATA);
    1019       MCLGET (m, M_WAIT);
    1020       m->m_pkthdr.rcvif = ifp;
    1021       size = ETHER_MAX_LEN;
    1022 
    1023       sc->rxMbuf[rxBdIndex] = m;
    1024       bd->DataPtr[0] = (uint32)mtod(m, void *);
    1025       bd->Status = ( (  (uint32)SDMA_DRD_MASK_LENGTH & (uint32)size)
    1026                      | ((uint32)SDMA_BD_MASK_READY));
    1027 
    1028       /*
    1029        * advance to next BD
    1030        */
    1031       if (++rxBdIndex >= sc->rxBdCount) {
    1032         rxBdIndex = 0;
    1033       }
    1034       /*
    1035        * Get next BD pointer and its length.
    1036        */
    1037       bd     = bdRing + rxBdIndex;
    1038       status = bd->Status;
    1039       len    = (uint16)GET_BD_LENGTH( bd );
    1040     }
    1041     /*
    1042      * Unmask RXF (Full frame received) event
    1043      */
    1044     bestcomm_glue_irq_enable(FEC_RECV_TASK_NO);
    1045 
    1046     rtems_bsdnet_event_receive (INTERRUPT_EVENT | FATAL_INT_EVENT,
    1047                                 RTEMS_WAIT | RTEMS_EVENT_ANY,
    1048                                 RTEMS_NO_TIMEOUT, &events);
    1049     if (events & FATAL_INT_EVENT) {
    1050       /*
    1051        * fatal interrupt ocurred, so reinit fec and restart bestcomm tasks
    1052        */
    1053       mpc5200_fec_restart(sc);
    1054       rxBdIndex = 0;
    1055     }
    1056   }
    1057 }
    1058 
     536    mpc5200_fec_request_restart(self);
     537  }
     538}
     539
     540void mpc5200_smartcomm_rx_irq_handler(void *arg)
     541{
     542  mpc5200_fec_context *self = arg;
     543
     544  ++self->rxInterrupts;
     545  mpc5200_fec_send_event(self->rxDaemonTid);
     546  SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_RECV_TASK_NO);
     547  bestcomm_glue_irq_disable(FEC_RECV_TASK_NO);
     548}
     549
     550void mpc5200_smartcomm_tx_irq_handler(void *arg)
     551{
     552  mpc5200_fec_context *self = arg;
     553
     554  ++self->txInterrupts;
     555  mpc5200_fec_send_event(self->txDaemonTid);
     556  SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_XMIT_TASK_NO);
     557  bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO);
     558}
     559
     560static void mpc5200_fec_init_mib(mpc5200_fec_context *self)
     561{
     562  memset(&mpc5200.RES [0], 0, 0x2e4);
     563  mpc5200.mib_control = 0x40000000;
     564}
    1059565
    1060566/*
     
    1069575 *
    1070576 */
    1071 static void mpc5200_fec_initialize_hardware(struct mpc5200_enet_struct *sc)
    1072   {
     577static void mpc5200_fec_initialize_hardware(mpc5200_fec_context *self)
     578{
     579  /* We want at most 2.5MHz */
     580  uint32_t div = 2 * 2500000;
     581  uint32_t mii_speed = (IPB_CLOCK + div - 1) / div;
    1073582
    1074583 /*
    1075584  * Reset mpc5200 FEC
    1076585  */
    1077   mpc5200_fec_reset(sc);
     586  mpc5200_fec_reset(self);
     587  mpc5200_fec_init_mib(self);
    1078588
    1079589 /*
     
    1103613
    1104614 /*
    1105   * Set MII_SPEED = (1/(mii_speed * 2)) * System Clock(33Mhz)
     615  * Set MII_SPEED = IPB clock / (2 * mii_speed))
    1106616  * and do not drop the Preamble.
    1107617  */
    1108   mpc5200.mii_speed = (7 << 1); /* ipb_clk = 33 MHz */
     618  mpc5200.mii_speed = mii_speed << 1;
    1109619
    1110620 /*
     
    1136646  * and set physical address registers.
    1137647  */
    1138   mpc5200_eth_addr_filter_set(sc);
     648  mpc5200_eth_addr_filter_set(self);
    1139649
    1140650 /*
     
    1148658  */
    1149659  mpc5200.xmit_fsm = FEC_FSM_CRC | FEC_FSM_ENFSM;
    1150   }
     660}
    1151661
    1152662 /*
     
    1175685  *
    1176686  */
    1177 static void mpc5200_fec_initialize_phy(struct mpc5200_enet_struct *sc)
    1178   {
    1179   int            timeout;
    1180   unsigned short phyAddr = 0;
    1181 
     687static void mpc5200_fec_initialize_phy(mpc5200_fec_context *self)
     688{
     689  if (self->phyInitialized) {
     690    return;
     691  } else {
     692    self->phyInitialized = true;
     693  }
    1182694
    1183695 /*
    1184696  * Reset PHY, then delay 300ns
    1185697  */
    1186   mpc5200_eth_mii_write(sc, phyAddr, 0x0, 0x8000);
     698  mpc5200_eth_mii_write(self->phyAddr, self, 0x0, 0x8000);
    1187699
    1188700  rtems_task_wake_after(2);
     
    1193705  * Set the auto-negotiation advertisement register bits
    1194706  */
    1195   mpc5200_eth_mii_write(sc, phyAddr, 0x4, 0x01e1);
     707  mpc5200_eth_mii_write(self->phyAddr, self, 0x4, 0x01e1);
    1196708
    1197709 /*
    1198710  * Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
    1199711  */
    1200   mpc5200_eth_mii_write(sc, phyAddr, 0x0, 0x1200);
     712  mpc5200_eth_mii_write(self->phyAddr, self, 0x0, 0x1200);
    1201713
    1202714 /*
    1203715  * Wait for AN completion
    1204716  */
    1205   timeout = 0x100;
    1206717#if 0
     718  int timeout = 0x100;
     719  uint32_t phyStatus;
    1207720  do
    1208721    {
     
    1219732      }
    1220733
    1221     if(mpc5200_eth_mii_read(sc, phyAddr, 0x1, &phyStatus) != true)
     734    if(mpc5200_eth_mii_read(self->phyAddr, self, 0x1, &phyStatus) != true)
    1222735      {
    1223736
    1224737#if defined(ETH_DEBUG)
    1225       printf ("MPC5200FEC PHY auto neg failed: 0x%04x." "\r\n", phyStatus);
     738      printf ("MPC5200FEC PHY auto neg failed: 0x%04" PRIx32 ".\r\n", phyStatus);
    1226739#endif
    1227740
     
    1243756#if defined(ETH_DEBUG)
    1244757  int i;
    1245   unsigned short phyStatus;
     758  uint32_t phyStatus;
    1246759 /*
    1247760  * Print PHY registers after initialization.
     
    1250763    {
    1251764
    1252         mpc5200_eth_mii_read(sc, phyAddr, i, &phyStatus);
    1253         printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
     765        mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus);
     766        printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus);
    1254767
    1255768        }
     
    1258771    {
    1259772
    1260     mpc5200_eth_mii_read(sc, phyAddr, i, &phyStatus);
    1261     printf ("Mii reg %d: 0x%04x" "\r\n", i, phyStatus);
     773    mpc5200_eth_mii_read(self->phyAddr, self, i, &phyStatus);
     774    printf ("Mii reg %d: 0x%04" PRIx32 "\r\n", i, phyStatus);
    1262775
    1263776    }
     
    1266779  }
    1267780
     781static void mpc5200_fec_restart(mpc5200_fec_context *self, rtems_id otherDaemon)
     782{
     783  if (self->state == FEC_STATE_RESTART_1) {
     784    mpc5200_fec_initialize_hardware(self);
     785    mpc5200_fec_initialize_phy(self);
     786    mpc5200_fec_start_dma_and_controller();
     787    self->state = FEC_STATE_NORMAL;
     788  } else {
     789    self->state = FEC_STATE_RESTART_1;
     790  }
     791
     792  mpc5200_fec_send_event(otherDaemon);
     793  while (self->state != FEC_STATE_NORMAL) {
     794    mpc5200_fec_wait_for_event();
     795  }
     796}
    1268797
    1269798/*
     
    1273802  {
    1274803
    1275   struct mpc5200_enet_struct *sc = ifp->if_softc;
     804  mpc5200_fec_context *self = ifp->if_softc;
    1276805
    1277806  ifp->if_flags |= IFF_OACTIVE;
    1278807
    1279   rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT);
    1280 
    1281   }
    1282 
    1283 
    1284 /*
    1285  * set up sdma tasks for ethernet
    1286  */
    1287 static void mpc5200_sdma_task_setup(struct mpc5200_enet_struct *sc) {
    1288   TaskSetupParamSet_t   rxParam;        /* RX task setup parameters     */
    1289   TaskSetupParamSet_t   txParam;        /* TX task setup parameters     */
    1290 
    1291   /*
    1292    * Setup the SDMA RX task.
    1293    */
    1294   rxParam.NumBD        = sc->rxBdCount;
    1295   rxParam.Size.MaxBuf  = ETHER_MAX_LEN;
    1296   rxParam.Initiator    = 0;
    1297   rxParam.StartAddrSrc = (uint32)&(mpc5200.rfifo_data);
    1298   rxParam.IncrSrc      = 0;
    1299   rxParam.SzSrc        = sizeof(uint32_t);
    1300   rxParam.StartAddrDst = (uint32)NULL;
    1301   rxParam.IncrDst      = sizeof(uint32_t);
    1302   rxParam.SzDst        = sizeof(uint32_t);
    1303   rxTaskId             = TaskSetup(TASK_FEC_RX,&rxParam );
    1304 
    1305   /*
    1306    * Setup the TX task.
    1307    */
    1308   txParam.NumBD        = sc->txBdCount;
    1309   txParam.Size.MaxBuf  = ETHER_MAX_LEN;
    1310   txParam.Initiator    = 0;
    1311   txParam.StartAddrSrc = (uint32)NULL;
    1312   txParam.IncrSrc      = sizeof(uint32_t);
    1313   txParam.SzSrc        = sizeof(uint32_t);
    1314   txParam.StartAddrDst = (uint32)&(mpc5200.tfifo_data);
    1315   txParam.IncrDst      = 0;
    1316   txParam.SzDst        = sizeof(uint32_t);
    1317 
    1318   txTaskId             = TaskSetup( TASK_FEC_TX, &txParam );
    1319 
    1320 }
    1321 
    1322 void mpc5200_fec_irq_on(const rtems_irq_connect_data* ptr)
    1323 {
    1324   mpc5200.imask = FEC_INTR_MASK_USED;
    1325 }
    1326 
    1327 
    1328 int mpc5200_fec_irq_isOn(const rtems_irq_connect_data* ptr)
    1329 {
    1330   return mpc5200.imask != 0;
    1331 }
    1332 
    1333 
    1334 void mpc5200_fec_irq_off(const rtems_irq_connect_data* ptr)
    1335 {
    1336   mpc5200.imask = 0;
    1337 }
    1338 
     808  mpc5200_fec_send_event(self->txDaemonTid);
     809
     810  }
     811
     812static TaskBD1_t *mpc5200_fec_init_tx_dma(int bdCount, struct mbuf **mbufs)
     813{
     814  TaskSetupParamSet_t param = {
     815    .NumBD = bdCount,
     816    .Size = {
     817      .MaxBuf = ETHER_MAX_LEN
     818    },
     819    .Initiator = 0,
     820    .StartAddrSrc = 0,
     821    .IncrSrc = sizeof(uint32_t),
     822    .SzSrc = sizeof(uint32_t),
     823    .StartAddrDst = (uint32) &mpc5200.tfifo_data,
     824    .IncrDst = 0,
     825    .SzDst = sizeof(uint32_t)
     826  };
     827  int bdIndex = 0;
     828
     829  TaskSetup(FEC_XMIT_TASK_NO, &param);
     830
     831  for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) {
     832    mbufs [bdIndex] = NULL;
     833  }
     834
     835  return (TaskBD1_t *) TaskGetBDRing(FEC_XMIT_TASK_NO);
     836}
     837
     838#if 0
     839static void mpc5200_fec_requeue_and_discard_tx_frames(
     840  int bdIndex,
     841  int bdCount,
     842  TaskBD1_t *bdRing,
     843  struct mbuf **mbufs
     844)
     845{
     846  int bdStop = bdIndex;
     847  struct mbuf *previous = NULL;
     848
     849  do {
     850    struct mbuf *current = NULL;
     851    uint32 status = 0;
     852    TaskBD1_t *bd = NULL;
     853
     854    if (bdIndex > 1) {
     855      --bdIndex;
     856    } else {
     857      bdIndex = bdCount - 1;
     858    }
     859
     860    current = mbufs [bdIndex];
     861    mbufs [bdIndex] = NULL;
     862
     863    status = bdRing [bdIndex].Status;
     864    bdRing [bdIndex].Status = 0;
     865
     866    if (current != NULL) {
     867      if ((status & FEC_BD_LAST) != 0) {
     868        if (previous != NULL) {
     869          IF_PREPEND(&ifp->if_snd, previous);
     870        }
     871      }
     872    } else {
     873      break;
     874    }
     875
     876    previous = current;
     877  } while (bdIndex != bdStop);
     878}
     879#endif
     880
     881static void mpc5200_fec_discard_tx_frames(
     882  int bdCount,
     883  struct mbuf **mbufs
     884)
     885{
     886  int bdIndex = 0;
     887
     888  for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) {
     889    struct mbuf *m = mbufs [bdIndex];
     890
     891    if (m != NULL) {
     892      mbufs [bdIndex] = NULL;
     893      m_free(m);
     894    }
     895  }
     896}
     897
     898static void mpc5200_fec_reset_tx_dma(
     899  int bdCount,
     900  TaskBD1_t *bdRing,
     901  struct mbuf **mbufs,
     902  struct mbuf *m
     903)
     904{
     905  TaskStop(FEC_XMIT_TASK_NO);
     906  TaskBDReset(FEC_XMIT_TASK_NO);
     907  mpc5200_fec_discard_tx_frames(bdCount, mbufs);
     908  while (m != NULL) {
     909    m = m_free(m);
     910  }
     911}
     912
     913static struct mbuf *mpc5200_fec_next_fragment(
     914  struct ifnet *ifp,
     915  struct mbuf *m,
     916  bool *isFirst
     917)
     918{
     919  struct mbuf *n = NULL;
     920
     921  *isFirst = false;
     922
     923  while (true) {
     924    if (m == NULL) {
     925      IF_DEQUEUE(&ifp->if_snd, m);
     926
     927      if (m != NULL) {
     928        *isFirst = true;
     929      } else {
     930        ifp->if_flags &= ~IFF_OACTIVE;
     931
     932        return NULL;
     933      }
     934    }
     935
     936    if (m->m_len > 0) {
     937      break;
     938    } else {
     939      m = m_free(m);
     940    }
     941  }
     942
     943  n = m->m_next;
     944  while (n != NULL && n->m_len <= 0) {
     945    n = m_free(n);
     946  }
     947  m->m_next = n;
     948
     949  return m;
     950}
     951
     952static bool mpc5200_fec_transmit(
     953  struct ifnet *ifp,
     954  int bdCount,
     955  TaskBD1_t *bdRing,
     956  struct mbuf **mbufs,
     957  int *bdIndexPtr,
     958  struct mbuf **mPtr,
     959  TaskBD1_t **firstPtr
     960)
     961{
     962  bool bdShortage = false;
     963  int bdIndex = *bdIndexPtr;
     964  struct mbuf *m = *mPtr;
     965  TaskBD1_t *first = *firstPtr;
     966
     967  while (true) {
     968    TaskBD1_t *bd = &bdRing [bdIndex];
     969
     970    if (bd->Status == 0) {
     971      struct mbuf *done = mbufs [bdIndex];
     972      bool isFirst = false;
     973
     974      if (done != NULL) {
     975        m_free(done);
     976        mbufs [bdIndex] = NULL;
     977      }
     978
     979      m = mpc5200_fec_next_fragment(ifp, m, &isFirst);
     980      if (m != NULL) {
     981        uint32 status = (uint32) m->m_len;
     982
     983        mbufs [bdIndex] = m;
     984
     985        rtems_cache_flush_multiple_data_lines(mtod(m, void *), m->m_len);
     986
     987        if (isFirst) {
     988          first = bd;
     989        } else {
     990          status |= FEC_BD_READY;
     991        }
     992
     993        bd->DataPtr [0] = mtod(m, uint32);
     994
     995        if (m->m_next != NULL) {
     996          bd->Status = status;
     997        } else {
     998          bd->Status = status | FEC_BD_INT | FEC_BD_LAST;
     999          first->Status |= FEC_BD_READY;
     1000          SDMA_TASK_ENABLE(SDMA_TCR, FEC_XMIT_TASK_NO);
     1001        }
     1002
     1003        m = m->m_next;
     1004      } else {
     1005        break;
     1006      }
     1007    } else {
     1008      bdShortage = true;
     1009      break;
     1010    }
     1011
     1012    if (bdIndex < bdCount - 1) {
     1013      ++bdIndex;
     1014    } else {
     1015      bdIndex = 0;
     1016    }
     1017  }
     1018
     1019  *bdIndexPtr = bdIndex;
     1020  *mPtr = m;
     1021  *firstPtr = first;
     1022
     1023  return bdShortage;
     1024}
     1025
     1026static void mpc5200_fec_tx_daemon(void *arg)
     1027{
     1028  mpc5200_fec_context *self = arg;
     1029  struct ifnet *ifp = &self->arpcom.ac_if;
     1030  int bdIndex = 0;
     1031  int bdCount = self->txBdCount;
     1032  struct mbuf **mbufs = &self->txMbuf [0];
     1033  struct mbuf *m = NULL;
     1034  TaskBD1_t *bdRing = mpc5200_fec_init_tx_dma(bdCount, mbufs);
     1035  TaskBD1_t *first = NULL;
     1036  bool bdShortage = false;
     1037
     1038  while (true) {
     1039    if (bdShortage) {
     1040      bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO);
     1041    }
     1042    mpc5200_fec_wait_for_event();
     1043
     1044    if (self->state != FEC_STATE_NORMAL) {
     1045      mpc5200_fec_reset_tx_dma(bdCount, bdRing, mbufs, m);
     1046      mpc5200_fec_restart(self, self->rxDaemonTid);
     1047      bdIndex = 0;
     1048      m = NULL;
     1049      first = NULL;
     1050    }
     1051
     1052    bdShortage = mpc5200_fec_transmit(
     1053      ifp,
     1054      bdCount,
     1055      bdRing,
     1056      mbufs,
     1057      &bdIndex,
     1058      &m,
     1059      &first
     1060    );
     1061  }
     1062}
     1063
     1064static struct mbuf *mpc5200_fec_add_mbuf(struct ifnet *ifp, TaskBD1_t *bd)
     1065{
     1066  struct mbuf *m = NULL;
     1067
     1068  MGETHDR (m, M_WAIT, MT_DATA);
     1069  MCLGET (m, M_WAIT);
     1070  m->m_pkthdr.rcvif = ifp;
     1071
     1072  /* XXX: The dcbi operation does not work properly */
     1073  rtems_cache_flush_multiple_data_lines(mtod(m, void *), ETHER_MAX_LEN);
     1074
     1075  bd->DataPtr [0] = mtod(m, uint32);
     1076  bd->Status = ETHER_MAX_LEN | FEC_BD_READY;
     1077
     1078  return m;
     1079}
     1080
     1081static TaskBD1_t *mpc5200_fec_init_rx_dma(
     1082  struct ifnet *ifp,
     1083  int bdCount,
     1084  struct mbuf **mbufs
     1085)
     1086{
     1087  TaskSetupParamSet_t param = {
     1088    .NumBD = bdCount,
     1089    .Size = {
     1090      .MaxBuf = ETHER_MAX_LEN
     1091    },
     1092    .Initiator = 0,
     1093    .StartAddrSrc = (uint32) &mpc5200.rfifo_data,
     1094    .IncrSrc = 0,
     1095    .SzSrc = sizeof(uint32_t),
     1096    .StartAddrDst = 0,
     1097    .IncrDst = sizeof(uint32_t),
     1098    .SzDst = sizeof(uint32_t)
     1099  };
     1100  TaskBD1_t *bdRing = NULL;
     1101  int bdIndex = 0;
     1102
     1103  TaskSetup(FEC_RECV_TASK_NO, &param);
     1104  bdRing = (TaskBD1_t *) TaskGetBDRing(FEC_RECV_TASK_NO);
     1105
     1106  for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) {
     1107    mbufs [bdIndex] = mpc5200_fec_add_mbuf(ifp, &bdRing [bdIndex]);
     1108  }
     1109
     1110  return bdRing;
     1111}
     1112
     1113static void mpc5200_fec_reset_rx_dma(int bdCount, TaskBD1_t *bdRing)
     1114{
     1115  int bdIndex = 0;
     1116
     1117  TaskStop(FEC_RECV_TASK_NO);
     1118  TaskBDReset(FEC_RECV_TASK_NO);
     1119
     1120  for (bdIndex = 0; bdIndex < bdCount; ++bdIndex) {
     1121    bdRing [bdIndex].Status = ETHER_MAX_LEN | FEC_BD_READY;
     1122  }
     1123}
     1124
     1125static int mpc5200_fec_ether_input(
     1126  struct ifnet *ifp,
     1127  int bdIndex,
     1128  int bdCount,
     1129  TaskBD1_t *bdRing,
     1130  struct mbuf **mbufs
     1131)
     1132{
     1133  while (true) {
     1134    TaskBD1_t *bd = &bdRing [bdIndex];
     1135    struct mbuf *m = mbufs [bdIndex];
     1136    uint32 status = 0;
     1137    int len = 0;
     1138    struct ether_header *eh = NULL;
     1139
     1140    SDMA_CLEAR_IEVENT(&mpc5200.sdma.IntPend, FEC_RECV_TASK_NO);
     1141    status = bd->Status;
     1142
     1143    if ((status & FEC_BD_READY) != 0) {
     1144      break;
     1145    }
     1146
     1147    eh = mtod(m, struct ether_header *);
     1148
     1149    len = (status & 0xffff) - ETHER_HDR_LEN - ETHER_CRC_LEN;
     1150    m->m_len = len;
     1151    m->m_pkthdr.len = len;
     1152    m->m_data = mtod(m, char *) + ETHER_HDR_LEN;
     1153
     1154    ether_input(ifp, eh, m);
     1155
     1156    mbufs [bdIndex] = mpc5200_fec_add_mbuf(ifp, bd);
     1157
     1158    if (bdIndex < bdCount - 1) {
     1159      ++bdIndex;
     1160    } else {
     1161      bdIndex = 0;
     1162    }
     1163  }
     1164
     1165  return bdIndex;
     1166}
     1167
     1168static void mpc5200_fec_rx_daemon(void *arg)
     1169{
     1170  mpc5200_fec_context *self = arg;
     1171  struct ifnet *ifp = &self->arpcom.ac_if;
     1172  int bdIndex = 0;
     1173  int bdCount = self->rxBdCount;
     1174  struct mbuf **mbufs = &self->rxMbuf [0];
     1175  TaskBD1_t *bdRing = mpc5200_fec_init_rx_dma(ifp, bdCount, mbufs);
     1176
     1177  while (true) {
     1178    bestcomm_glue_irq_enable(FEC_RECV_TASK_NO);
     1179    mpc5200_fec_wait_for_event();
     1180
     1181    bdIndex = mpc5200_fec_ether_input(ifp, bdIndex, bdCount, bdRing, mbufs);
     1182
     1183    if (self->state != FEC_STATE_NORMAL) {
     1184      mpc5200_fec_reset_rx_dma(bdCount, bdRing);
     1185      mpc5200_fec_restart(self, self->txDaemonTid);
     1186      bdIndex = 0;
     1187    }
     1188  }
     1189}
    13391190
    13401191/*
     
    13431194static void mpc5200_fec_init(void *arg)
    13441195{
    1345   struct mpc5200_enet_struct *sc = (struct mpc5200_enet_struct *)arg;
    1346   struct ifnet *ifp = &sc->arpcom.ac_if;
    1347   rtems_irq_connect_data fec_irq_data = {
    1348     BSP_SIU_IRQ_ETH,
    1349     mpc5200_fec_irq_handler, /* rtems_irq_hdl           */
    1350     (rtems_irq_hdl_param)sc, /* (rtems_irq_hdl_param)   */
    1351     mpc5200_fec_irq_on,      /* (rtems_irq_enable)      */
    1352     mpc5200_fec_irq_off,     /* (rtems_irq_disable)     */
    1353     mpc5200_fec_irq_isOn     /* (rtems_irq_is_enabled)  */
    1354   };
    1355 
    1356 
    1357   if(sc->txDaemonTid == 0)
     1196  rtems_status_code sc = RTEMS_SUCCESSFUL;
     1197  mpc5200_fec_context *self = (mpc5200_fec_context *)arg;
     1198  struct ifnet *ifp = &self->arpcom.ac_if;
     1199
     1200  if(self->txDaemonTid == 0)
    13581201    {
     1202      size_t rxMbufTableSize = self->rxBdCount * sizeof(*self->rxMbuf);
     1203      size_t txMbufTableSize = self->txBdCount * sizeof(*self->txMbuf);
     1204
    13591205      /*
    13601206       * Allocate a set of mbuf pointers
    13611207       */
    1362       sc->rxMbuf =
    1363         malloc(sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT);
    1364       sc->txMbuf =
    1365         malloc(sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT);
    1366 
    1367       if(!sc->rxMbuf || !sc->txMbuf)
     1208      self->rxMbuf = malloc(rxMbufTableSize, M_MBUF, M_NOWAIT);
     1209      self->txMbuf = malloc(txMbufTableSize, M_MBUF, M_NOWAIT);
     1210
     1211      if(!self->rxMbuf || !self->txMbuf)
    13681212        rtems_panic ("No memory for mbuf pointers");
    13691213
     1214      /*
     1215       * DMA setup
     1216       */
    13701217      bestcomm_glue_init();
    1371 
    1372       mpc5200_sdma_task_setup(sc);
     1218      mpc5200.sdma.ipr [0] = 4; /* always initiator     */
     1219      mpc5200.sdma.ipr [3] = 6; /* eth rx initiator     */
     1220      mpc5200.sdma.ipr [4] = 5; /* eth tx initiator     */
    13731221
    13741222      /*
     
    13771225      bestcomm_glue_irq_install(FEC_RECV_TASK_NO,
    13781226                                mpc5200_smartcomm_rx_irq_handler,
    1379                                 NULL);
     1227                                self);
    13801228      bestcomm_glue_irq_install(FEC_XMIT_TASK_NO,
    13811229                                mpc5200_smartcomm_tx_irq_handler,
    1382                                 NULL);
    1383       if(!BSP_install_rtems_irq_handler (&fec_irq_data)) {
     1230                                self);
     1231      sc = rtems_interrupt_handler_install(
     1232        BSP_SIU_IRQ_ETH,
     1233        "FEC",
     1234        RTEMS_INTERRUPT_UNIQUE,
     1235        mpc5200_fec_irq_handler,
     1236        self
     1237      );
     1238      if(sc != RTEMS_SUCCESSFUL) {
    13841239        rtems_panic ("Can't attach MPC5x00 FEX interrupt handler\n");
    13851240      }
    1386 
    1387       /* mpc5200_fec_tx_bd_init(sc); */
    1388       mpc5200_fec_rx_bd_init(sc);
    1389 
    1390       /*
    1391        * reset and Set up mpc5200 FEC hardware
    1392        */
    1393       mpc5200_fec_initialize_hardware(sc);
    1394       /*
    1395        * Set up the phy
    1396        */
    1397       mpc5200_fec_initialize_phy(sc);
    1398       /*
    1399        * Set priority of different initiators
    1400        */
    1401       mpc5200.sdma.ipr [0] = 7; /* always initiator     */
    1402       mpc5200.sdma.ipr [3] = 6; /* eth rx initiator     */
    1403       mpc5200.sdma.ipr [4] = 5; /* eth tx initiator     */
    14041241
    14051242      /*
    14061243       * Start driver tasks
    14071244       */
    1408       sc->txDaemonTid = rtems_bsdnet_newproc("FEtx", 4096, mpc5200_fec_txDaemon, sc);
    1409       sc->rxDaemonTid = rtems_bsdnet_newproc("FErx", 4096, mpc5200_fec_rxDaemon, sc);
    1410       /*
    1411        * Clear SmartDMA task interrupt pending bits.
    1412        */
    1413       TaskIntClear( rxTaskId );
    1414 
    1415       /*
    1416        * Enable the SmartDMA receive task.
    1417        */
    1418       TaskStart( rxTaskId, 1, rxTaskId, 1 );
    1419       TaskStart( txTaskId, 1, txTaskId, 1 );
    1420       /*
    1421        * Enable FEC-Lite controller
    1422        */
    1423       mpc5200.ecntrl |= (FEC_ECNTRL_OE | FEC_ECNTRL_EN);
    1424 
    1425 
    1426     }
     1245      self->txDaemonTid = rtems_bsdnet_newproc("FEtx", 4096, mpc5200_fec_tx_daemon, self);
     1246      self->rxDaemonTid = rtems_bsdnet_newproc("FErx", 4096, mpc5200_fec_rx_daemon, self);
     1247    }
     1248
     1249  mpc5200_fec_request_restart(self);
    14271250
    14281251  /*
     
    14401263}
    14411264
    1442 
    1443 static void enet_stats (struct mpc5200_enet_struct *sc)
    1444 {
    1445   printf ("      Rx Interrupts:%-8lu", sc->rxInterrupts);
    1446   printf ("       Not First:%-8lu", sc->rxNotFirst);
    1447   printf ("        Not Last:%-8lu\n", sc->rxNotLast);
    1448   printf ("              Giant:%-8lu", sc->rxGiant);
    1449   printf ("       Non-octet:%-8lu\n", sc->rxNonOctet);
    1450   printf ("            Bad CRC:%-8lu", sc->rxBadCRC);
    1451   printf ("         Overrun:%-8lu", sc->rxOverrun);
    1452   printf ("       Collision:%-8lu\n", sc->rxCollision);
    1453 
    1454   printf ("      Tx Interrupts:%-8lu", sc->txInterrupts);
    1455   printf ("        Deferred:%-8lu", sc->txDeferred);
    1456   printf ("  Late Collision:%-8lu\n", sc->txLateCollision);
    1457   printf ("   Retransmit Limit:%-8lu", sc->txRetryLimit);
    1458   printf ("        Underrun:%-8lu", sc->txUnderrun);
    1459   printf ("      Misaligned:%-8lu\n", sc->txMisaligned);
    1460 
    1461 }
    1462 
    1463 /*
    1464  * restart the driver, reinit the fec
    1465  * this function is responsible to reinitialize the FEC in case a fatal
    1466  * error has ocurred. This is needed, wen a RxFIFO Overrun or a TxFIFO underrun
    1467  * has ocurred. In these cases, the FEC is automatically disabled, and
    1468  * both FIFOs must be reset and the BestComm tasks must be restarted
    1469  *
    1470  * Note: the daemon tasks will continue to run
    1471  * (in fact this function will be called in the context of the rx daemon task)
    1472  */
    1473 #define NEW_SDMA_SETUP
    1474 
    1475 static void mpc5200_fec_restart(struct mpc5200_enet_struct *sc)
    1476 {
    1477   /*
    1478    * FIXME: bring Tx Daemon into idle state
    1479    */
    1480 #ifdef NEW_SDMA_SETUP
    1481   /*
    1482    * cleanup remaining receive mbufs
    1483    */
    1484   mpc5200_fec_rx_bd_cleanup(sc);
    1485 #endif
    1486   /*
    1487    * Stop SDMA tasks
    1488    */
    1489   TaskStop( rxTaskId);
    1490   TaskStop( txTaskId);
    1491   /*
    1492    * FIXME: wait, until Tx Daemon is in idle state
    1493    */
    1494 
    1495   /*
    1496    * Disable transmit / receive interrupts
    1497    */
    1498   bestcomm_glue_irq_disable(FEC_XMIT_TASK_NO);
    1499   bestcomm_glue_irq_disable(FEC_RECV_TASK_NO);
    1500 #ifdef NEW_SDMA_SETUP
    1501   /*
    1502    * recycle pending tx buffers
    1503    * FIXME: try to extract pending Tx buffers
    1504    */
    1505 #if 0
    1506   mpc5200_fec_tx_bd_requeue(sc);
    1507 #else
    1508   mpc5200_fec_retire_tbd(sc,true);
    1509 #endif
    1510 #endif
    1511   /*
    1512    * re-initialize the FEC hardware
    1513    */
    1514   mpc5200_fec_initialize_hardware(sc);
    1515 
    1516 #ifdef NEW_SDMA_SETUP
    1517   /*
    1518    * completely reinitialize Bestcomm tasks
    1519    */
    1520   mpc5200_sdma_task_setup(sc);
    1521 
    1522   /*
    1523    * reinit receive mbufs
    1524    */
    1525   mpc5200_fec_rx_bd_init(sc);
    1526 #endif
    1527   /*
    1528    * Clear SmartDMA task interrupt pending bits.
    1529    */
    1530   TaskIntClear( rxTaskId );
    1531 
    1532   /*
    1533    * Enable the SmartDMA receive/transmit task.
    1534    */
    1535   TaskStart( rxTaskId, 1, rxTaskId, 1 );
    1536   TaskStart( txTaskId, 1, txTaskId, 1 );
    1537   /*
    1538    * reenable rx/tx interrupts
    1539    */
    1540   bestcomm_glue_irq_enable(FEC_XMIT_TASK_NO);
    1541   bestcomm_glue_irq_enable(FEC_RECV_TASK_NO);
    1542   /*
    1543    * (re-)init fec hardware
    1544    */
    1545   mpc5200_fec_initialize_hardware(sc);
    1546   /*
    1547    * reenable fec FIFO error interrupts
    1548    */
    1549   mpc5200.imask = FEC_INTR_MASK_USED;
    1550   /*
    1551    * Enable FEC-Lite controller
    1552    */
    1553   mpc5200.ecntrl |= (FEC_ECNTRL_OE | FEC_ECNTRL_EN);
     1265static void enet_stats (mpc5200_fec_context *self)
     1266{
     1267  if (self->phyAddr >= 0) {
     1268    struct ifnet *ifp = &self->arpcom.ac_if;
     1269    int media = IFM_MAKEWORD(0, 0, 0, self->phyAddr);
     1270    int rv = (*ifp->if_ioctl)(ifp, SIOCGIFMEDIA, (caddr_t) &media);
     1271
     1272    if (rv == 0) {
     1273      rtems_ifmedia2str(media, NULL, 0);
     1274      printf ("\n");
     1275    } else {
     1276      printf ("PHY communication error\n");
     1277    }
     1278  }
     1279  printf ("       Rx Interrupts:%-8lu", self->rxInterrupts);
     1280  printf ("        Rx Not First:%-8lu", self->rxNotFirst);
     1281  printf ("         Rx Not Last:%-8lu\n", self->rxNotLast);
     1282  printf ("            Rx Giant:%-8lu", self->rxGiant);
     1283  printf ("        Rx Non-octet:%-8lu", self->rxNonOctet);
     1284  printf ("          Rx Bad CRC:%-8lu\n", self->rxBadCRC);
     1285  printf ("       Rx FIFO Error:%-8lu", self->rxFIFOError);
     1286  printf ("        Rx Collision:%-8lu", self->rxCollision);
     1287
     1288  printf ("       Tx Interrupts:%-8lu\n", self->txInterrupts);
     1289  printf ("         Tx Deferred:%-8lu", self->txDeferred);
     1290  printf ("   Tx Late Collision:%-8lu", self->txLateCollision);
     1291  printf (" Tx Retransmit Limit:%-8lu\n", self->txRetryLimit);
     1292  printf ("         Tx Underrun:%-8lu", self->txUnderrun);
     1293  printf ("       Tx FIFO Error:%-8lu", self->txFIFOError);
     1294  printf ("       Tx Misaligned:%-8lu\n", self->txMisaligned);
    15541295}
    15551296
    15561297int32_t mpc5200_fec_setMultiFilter(struct ifnet *ifp)
    15571298{
    1558   /*struct mpc5200_enet_struct *sc = ifp->if_softc; */
     1299  /*mpc5200_fec_context *self = ifp->if_softc; */
    15591300  /* XXX anything to do? */
    15601301  return 0;
     
    15671308static int mpc5200_fec_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data)
    15681309  {
    1569   struct mpc5200_enet_struct *sc = ifp->if_softc;
     1310  mpc5200_fec_context *self = ifp->if_softc;
    15701311  int error = 0;
    15711312
     
    15841325      struct ifreq* ifr = (struct ifreq*) data;
    15851326      error = (command == SIOCADDMULTI)
    1586                   ? ether_addmulti(ifr, &sc->arpcom)
    1587                   : ether_delmulti(ifr, &sc->arpcom);
     1327                  ? ether_addmulti(ifr, &self->arpcom)
     1328                  : ether_delmulti(ifr, &self->arpcom);
    15881329
    15891330       if (error == ENETRESET) {
     
    16031344        case IFF_RUNNING:
    16041345
    1605           mpc5200_fec_off(sc);
     1346          mpc5200_fec_off(self);
    16061347
    16071348          break;
     
    16091350        case IFF_UP:
    16101351
    1611           mpc5200_fec_init(sc);
     1352          mpc5200_fec_init(self);
    16121353
    16131354          break;
     
    16151356        case IFF_UP | IFF_RUNNING:
    16161357
    1617           mpc5200_fec_off(sc);
    1618           mpc5200_fec_init(sc);
     1358          mpc5200_fec_off(self);
     1359          mpc5200_fec_init(self);
    16191360
    16201361          break;
     
    16271368      break;
    16281369
     1370    case SIOCGIFMEDIA:
     1371    case SIOCSIFMEDIA:
     1372      error = rtems_mii_ioctl(&self->mdio, self, command, (int *) data);
     1373      break;
     1374
    16291375    case SIO_RTEMS_SHOW_STATS:
    16301376
    1631       enet_stats(sc);
     1377      enet_stats(self);
    16321378
    16331379      break;
     
    16541400int rtems_mpc5200_fec_driver_attach(struct rtems_bsdnet_ifconfig *config)
    16551401  {
    1656   struct mpc5200_enet_struct *sc;
     1402  mpc5200_fec_context *self;
    16571403  struct ifnet *ifp;
    16581404  int    mtu;
     
    16771423    }
    16781424
    1679   sc = &enet_driver[unitNumber - 1];
    1680   ifp = &sc->arpcom.ac_if;
     1425  self = &enet_driver[unitNumber - 1];
     1426  ifp = &self->arpcom.ac_if;
    16811427
    16821428  if(ifp->if_softc != NULL)
     
    16871433
    16881434    }
     1435
     1436  self->mdio.mdio_r = mpc5200_eth_mii_read;
     1437  self->mdio.mdio_w = mpc5200_eth_mii_write;
    16891438
    16901439  /*
     
    17271476
    17281477    /* Anything in the first three bytes indicates a non-zero entry, copy value */
    1729         memcpy((void *)sc->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN);
     1478        memcpy((void *)self->arpcom.ac_enaddr, &nvram->enaddr, ETHER_ADDR_LEN);
    17301479
    17311480    }
     
    17351484
    17361485      /* There is no entry in NVRAM, but there is in the ifconfig struct, so use it. */
    1737       memcpy((void *)sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
     1486      memcpy((void *)self->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
    17381487      }
    17391488    else
     
    17501499    {
    17511500
    1752     memcpy(sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
     1501    memcpy(self->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
    17531502
    17541503    }
     
    17651514#endif /* NVRAM_CONFIGURE != 1 */
    17661515#ifdef HAS_UBOOT
    1767   if ((sc->arpcom.ac_enaddr[0] == 0) &&
    1768       (sc->arpcom.ac_enaddr[1] == 0) &&
    1769       (sc->arpcom.ac_enaddr[2] == 0)) {
     1516  if ((self->arpcom.ac_enaddr[0] == 0) &&
     1517      (self->arpcom.ac_enaddr[1] == 0) &&
     1518      (self->arpcom.ac_enaddr[2] == 0)) {
    17701519      memcpy(
    1771         (void *)sc->arpcom.ac_enaddr,
     1520        (void *)self->arpcom.ac_enaddr,
    17721521        bsp_uboot_board_info.bi_enetaddr,
    17731522        ETHER_ADDR_LEN
     
    17811530
    17821531  if(config->rbuf_count)
    1783     sc->rxBdCount = config->rbuf_count;
     1532    self->rxBdCount = config->rbuf_count;
    17841533  else
    1785     sc->rxBdCount = RX_BUF_COUNT;
     1534    self->rxBdCount = RX_BUF_COUNT;
    17861535
    17871536  if(config->xbuf_count)
    1788     sc->txBdCount = config->xbuf_count;
     1537    self->txBdCount = config->xbuf_count;
    17891538  else
    1790     sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF;
    1791 
    1792   sc->acceptBroadcast = !config->ignore_broadcast;
     1539    self->txBdCount = TX_BUF_COUNT;
     1540
     1541  self->acceptBroadcast = !config->ignore_broadcast;
    17931542
    17941543 /*
    17951544  * Set up network interface values
    17961545  */
    1797   ifp->if_softc   = sc;
     1546  ifp->if_softc   = self;
    17981547  ifp->if_unit    = unitNumber;
    17991548  ifp->if_name    = unitName;
  • c/src/lib/libbsp/powerpc/gen5200/start/start.S

    r1dd95cc r25ed11d0  
    157157.extern boot_card
    158158
     159.section ".vectors", "ax"
     160        bl      start
     161        .rep 63
     162        .long 0x04000400
     163        .endr
     164__vec2: b       __vec2
     165        .rep 63
     166        .long 0x04000400
     167        .endr
     168__vec3: b       __vec3
     169        .rep 63
     170        .long 0x04000400
     171        .endr
     172__vec4: b       __vec4
     173        .rep 63
     174        .long 0x04000400
     175        .endr
     176__vec5: b       __vec5
     177        .rep 63
     178        .long 0x04000400
     179        .endr
     180__vec6: b       __vec6
     181        .rep 63
     182        .long 0x04000400
     183        .endr
     184__vec7: b       __vec7
     185        .rep 63
     186        .long 0x04000400
     187        .endr
     188__vec8: b       __vec8
     189        .rep 63
     190        .long 0x04000400
     191        .endr
     192__vec9: b       __vec9
     193        .rep 63
     194        .long 0x04000400
     195        .endr
     196__veca: b       __veca
     197        .rep 63
     198        .long 0x04000400
     199        .endr
     200__vecb: b       __vecb
     201        .rep 63
     202        .long 0x04000400
     203        .endr
     204__vecc: b       __vecc
     205        .rep 63
     206        .long 0x04000400
     207        .endr
     208__vecd: b       __vecd
     209        .rep 63
     210        .long 0x04000400
     211        .endr
     212__vece: b       __vece
     213        .rep 63
     214        .long 0x04000400
     215        .endr
     216__vecf: b       __vecf
     217        .rep 63+1024
     218        .long 0x04000400
     219        .endr
     220
    159221.section ".entry"
    160222PUBLIC_VAR (start)
     
    244306        stw     r30, CS0STR(r31)                /* Set CS0STR */
    245307
    246         LWI     r30, bsp_rom_end
     308        LWI     r30, bsp_rom_end - 1
    247309
    248310        rlwinm  r30, r30,17,15,31
     
    280342        bl      SDRAM_init                      /* Initialize SDRAM controller */
    281343
    282 /* init arbiter and stuff... */
    283         LWI     r30, 0x8000a06e
    284         stw     r30, ARBCFG(r31)                /* Set ARBCFG */
    285 
    286         LWI     r30, 0x000000ff
    287         stw     r30, ARBMPREN(r31)              /* Set ARBMPREN */
    288 
    289         LWI     r30, 0x00001234
    290         stw     r30, ARBMPRIO(r31)              /* Set ARBPRIO */
    291 
    292         LWI     r30, 0x0000001e
    293         stw     r30, ARBSNOOP(r31)              /* Set ARBSNOOP */
     344        bl      XLB_init
    294345/* copy .text section from ROM to RAM location (unique for ROM startup) */
    295346        LA      r30, bsp_section_text_start     /* get start address of text section in RAM */
     
    396447        bl      clr_mem                         /* Clear onchip SRAM */
    397448
     449#else /* defined(NEED_LOW_LEVEL_INIT) */
     450        bl      XLB_init
    398451#endif /* defined(NEED_LOW_LEVEL_INIT) */
    399452/* clear .bss section (unique for ROM startup) */
     
    844897        blr                                     /* return */
    845898
    846 
    847 
     899XLB_init:
     900/* init arbiter and stuff... */
     901        LWI     r30, 0x8000a06e
     902        stw     r30, ARBCFG(r31)                /* Set ARBCFG */
     903
     904        LWI     r30, 0x000000ff
     905        stw     r30, ARBMPREN(r31)              /* Set ARBMPREN */
     906
     907        LWI     r30, 0x00001234
     908        stw     r30, ARBMPRIO(r31)              /* Set ARBPRIO */
     909
     910        LWI     r30, 0x0000001e
     911        stw     r30, ARBSNOOP(r31)              /* Set ARBSNOOP */
     912
     913        blr
  • c/src/lib/libbsp/powerpc/gen5200/startup/bspstart.c

    r1dd95cc r25ed11d0  
    104104#include <bsp/irq.h>
    105105#include <bsp/irq-generic.h>
     106#include <bsp/mpc5200.h>
    106107
    107108/*
     
    144145
    145146  cpu_init();
     147
     148  if(get_ppc_cpu_revision() >= 0x2014) {
     149    /* Special settings for MPC5200B (B variant) */
     150    uint32_t xlb_cfg = mpc5200.config;
     151
     152    /* XXX: The Freescale documentation for BSDIS seems to be wrong */
     153    xlb_cfg |= XLB_CFG_BSDIS;
     154
     155    xlb_cfg &= ~XLB_CFG_PLDIS;
     156
     157    mpc5200.config = xlb_cfg;
     158  }
    146159
    147160  bsp_clicks_per_usec    = (XLB_CLOCK/4000000);
     
    167180    BSP_panic("cannot initialize exceptions");
    168181  }
     182  ppc_exc_set_handler(ASM_ALIGN_VECTOR, ppc_exc_alignment_handler);
    169183
    170184  /* Initalize interrupt support */
  • c/src/lib/libbsp/powerpc/gen5200/startup/cpuinit.c

    r1dd95cc r25ed11d0  
    170170
    171171  /*
     172   * Accesses (also speculative accesses) outside of the RAM area are a
     173   * disaster especially in combination with the BestComm.  For safety reasons
     174   * we make the available RAM a little bit smaller to have an unused area at
     175   * the end.
     176   */
     177  bsp_uboot_board_info.bi_memsize -= 4 * 1024;
     178
     179  /*
    172180   * Program BAT0 for RAM
    173181   */
  • c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.brs5l

    r1dd95cc r25ed11d0  
    66
    77MEMORY {
    8         RAM : ORIGIN = 0x0, LENGTH = 128M
     8        /* For the 4k adjustment see cpuinit.c */
     9        RAM : ORIGIN = 0x0, LENGTH = 128M - 4k
    910        ROM : ORIGIN = 0xffe00000, LENGTH = 2M
    1011        DPRAM : ORIGIN = 0xff000000, LENGTH = 1k
  • c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.dp2

    r1dd95cc r25ed11d0  
    66
    77MEMORY {
    8         RAM : ORIGIN = 0x0, LENGTH = 64M
     8        /* For the 4k adjustment see cpuinit.c */
     9        RAM : ORIGIN = 0x0, LENGTH = 64M - 4k
    910        ROM : ORIGIN = 0xffe00000, LENGTH = 2M
    10         DPRAM : ORIGIN = 0xff000000, LENGTH = 1k
    1111        REGS : ORIGIN = 0xf0000000, LENGTH = 64k
     12        DPRAM : ORIGIN = 0x0, LENGTH = 0
    1213        NIRVANA : ORIGIN = 0x0, LENGTH = 0
    1314}
  • c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.icecube

    r1dd95cc r25ed11d0  
    66
    77MEMORY {
    8         RAM : ORIGIN = 0x0, LENGTH = 128M
     8        /* For the 4k adjustment see cpuinit.c */
     9        RAM : ORIGIN = 0x0, LENGTH = 128M - 4k
    910        ROM : ORIGIN = 0xffe00000, LENGTH = 2M
    1011        REGS : ORIGIN = 0xf0000000, LENGTH = 64k
     12        DPRAM : ORIGIN = 0x0, LENGTH = 0
    1113        NIRVANA : ORIGIN = 0x0, LENGTH = 0
    12         DPRAM : ORIGIN = 0x0, LENGTH = 0
    1314}
    1415
  • c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.pm520_cr825

    r1dd95cc r25ed11d0  
    66
    77MEMORY {
    8         RAM : ORIGIN = 0x0, LENGTH = 64M
     8        /* For the 4k adjustment see cpuinit.c */
     9        RAM : ORIGIN = 0x0, LENGTH = 64M - 4k
    910        ROM : ORIGIN = 0xffe00000, LENGTH = 2M
     11        REGS : ORIGIN = 0xf0000000, LENGTH = 64k
    1012        DPRAM : ORIGIN = 0xff000000, LENGTH = 1k
    11         REGS : ORIGIN = 0xf0000000, LENGTH = 64k
    1213        NIRVANA : ORIGIN = 0x0, LENGTH = 0
    1314}
  • c/src/lib/libbsp/powerpc/gen5200/startup/linkcmds.pm520_ze30

    r1dd95cc r25ed11d0  
    66
    77MEMORY {
    8         RAM : ORIGIN = 0x0, LENGTH = 64M
     8        /* For the 4k adjustment see cpuinit.c */
     9        RAM : ORIGIN = 0x0, LENGTH = 64M - 4k
    910        ROM : ORIGIN = 0xffe00000, LENGTH = 2M
     11        REGS : ORIGIN = 0xf0000000, LENGTH = 64k
    1012        DPRAM : ORIGIN = 0xff000000, LENGTH = 1k
    11         REGS : ORIGIN = 0xf0000000, LENGTH = 64k
    1213        NIRVANA : ORIGIN = 0x0, LENGTH = 0
    1314}
Note: See TracChangeset for help on using the changeset viewer.