~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to cpu/mpc8260/ether_fcc.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * MPC8260 FCC Fast Ethernet
 
3
 *
 
4
 * Copyright (c) 2000 MontaVista Software, Inc.   Dan Malek (dmalek@jlc.net)
 
5
 *
 
6
 * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
 
7
 * Marius Groeger <mgroeger@sysgo.de>
 
8
 *
 
9
 * See file CREDITS for list of people who contributed to this
 
10
 * project.
 
11
 *
 
12
 * This program is free software; you can redistribute it and/or
 
13
 * modify it under the terms of the GNU General Public License as
 
14
 * published by the Free Software Foundation; either version 2 of
 
15
 * the License, or (at your option) any later version.
 
16
 *
 
17
 * This program is distributed in the hope that it will be useful,
 
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
20
 * GNU General Public License for more details.
 
21
 *
 
22
 * You should have received a copy of the GNU General Public License
 
23
 * along with this program; if not, write to the Free Software
 
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 
25
 * MA 02111-1307 USA
 
26
 */
 
27
 
 
28
/*
 
29
 * MPC8260 FCC Fast Ethernet
 
30
 * Basic ET HW initialization and packet RX/TX routines
 
31
 *
 
32
 * This code will not perform the IO port configuration. This should be
 
33
 * done in the iop_conf_t structure specific for the board.
 
34
 *
 
35
 * TODO:
 
36
 * add a PHY driver to do the negotiation
 
37
 * reflect negotiation results in FPSMR
 
38
 * look for ways to configure the board specific stuff elsewhere, eg.
 
39
 *    config_xxx.h or the board directory
 
40
 */
 
41
 
 
42
#include <common.h>
 
43
#include <malloc.h>
 
44
#include <asm/cpm_8260.h>
 
45
#include <mpc8260.h>
 
46
#include <command.h>
 
47
#include <config.h>
 
48
#include <net.h>
 
49
 
 
50
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
 
51
#include <miiphy.h>
 
52
#endif
 
53
 
 
54
DECLARE_GLOBAL_DATA_PTR;
 
55
 
 
56
#if defined(CONFIG_ETHER_ON_FCC) && defined(CONFIG_CMD_NET) && \
 
57
        defined(CONFIG_NET_MULTI)
 
58
 
 
59
static struct ether_fcc_info_s
 
60
{
 
61
        int ether_index;
 
62
        int proff_enet;
 
63
        ulong cpm_cr_enet_sblock;
 
64
        ulong cpm_cr_enet_page;
 
65
        ulong cmxfcr_mask;
 
66
        ulong cmxfcr_value;
 
67
}
 
68
        ether_fcc_info[] =
 
69
{
 
70
#ifdef CONFIG_ETHER_ON_FCC1
 
71
{
 
72
        0,
 
73
        PROFF_FCC1,
 
74
        CPM_CR_FCC1_SBLOCK,
 
75
        CPM_CR_FCC1_PAGE,
 
76
        CONFIG_SYS_CMXFCR_MASK1,
 
77
        CONFIG_SYS_CMXFCR_VALUE1
 
78
},
 
79
#endif
 
80
 
 
81
#ifdef CONFIG_ETHER_ON_FCC2
 
82
{
 
83
        1,
 
84
        PROFF_FCC2,
 
85
        CPM_CR_FCC2_SBLOCK,
 
86
        CPM_CR_FCC2_PAGE,
 
87
        CONFIG_SYS_CMXFCR_MASK2,
 
88
        CONFIG_SYS_CMXFCR_VALUE2
 
89
},
 
90
#endif
 
91
 
 
92
#ifdef CONFIG_ETHER_ON_FCC3
 
93
{
 
94
        2,
 
95
        PROFF_FCC3,
 
96
        CPM_CR_FCC3_SBLOCK,
 
97
        CPM_CR_FCC3_PAGE,
 
98
        CONFIG_SYS_CMXFCR_MASK3,
 
99
        CONFIG_SYS_CMXFCR_VALUE3
 
100
},
 
101
#endif
 
102
};
 
103
 
 
104
/*---------------------------------------------------------------------*/
 
105
 
 
106
/* Maximum input DMA size.  Must be a should(?) be a multiple of 4. */
 
107
#define PKT_MAXDMA_SIZE         1520
 
108
 
 
109
/* The FCC stores dest/src/type, data, and checksum for receive packets. */
 
110
#define PKT_MAXBUF_SIZE         1518
 
111
#define PKT_MINBUF_SIZE         64
 
112
 
 
113
/* Maximum input buffer size.  Must be a multiple of 32. */
 
114
#define PKT_MAXBLR_SIZE         1536
 
115
 
 
116
#define TOUT_LOOP 1000000
 
117
 
 
118
#define TX_BUF_CNT 2
 
119
#ifdef __GNUC__
 
120
static char txbuf[TX_BUF_CNT][PKT_MAXBLR_SIZE] __attribute__ ((aligned(8)));
 
121
#else
 
122
#error "txbuf must be 64-bit aligned"
 
123
#endif
 
124
 
 
125
static uint rxIdx;      /* index of the current RX buffer */
 
126
static uint txIdx;      /* index of the current TX buffer */
 
127
 
 
128
/*
 
129
 * FCC Ethernet Tx and Rx buffer descriptors.
 
130
 * Provide for Double Buffering
 
131
 * Note: PKTBUFSRX is defined in net.h
 
132
 */
 
133
 
 
134
typedef volatile struct rtxbd {
 
135
    cbd_t rxbd[PKTBUFSRX];
 
136
    cbd_t txbd[TX_BUF_CNT];
 
137
} RTXBD;
 
138
 
 
139
/*  Good news: the FCC supports external BDs! */
 
140
#ifdef __GNUC__
 
141
static RTXBD rtx __attribute__ ((aligned(8)));
 
142
#else
 
143
#error "rtx must be 64-bit aligned"
 
144
#endif
 
145
 
 
146
static int fec_send(struct eth_device* dev, volatile void *packet, int length)
 
147
{
 
148
    int i;
 
149
    int result = 0;
 
150
 
 
151
    if (length <= 0) {
 
152
        printf("fec: bad packet size: %d\n", length);
 
153
        goto out;
 
154
    }
 
155
 
 
156
    for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
 
157
        if (i >= TOUT_LOOP) {
 
158
            puts ("fec: tx buffer not ready\n");
 
159
            goto out;
 
160
        }
 
161
    }
 
162
 
 
163
    rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
 
164
    rtx.txbd[txIdx].cbd_datlen = length;
 
165
    rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |
 
166
                               BD_ENET_TX_WRAP);
 
167
 
 
168
    for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
 
169
        if (i >= TOUT_LOOP) {
 
170
            puts ("fec: tx error\n");
 
171
            goto out;
 
172
        }
 
173
    }
 
174
 
 
175
#ifdef ET_DEBUG
 
176
    printf("cycles: %d status: %04x\n", i, rtx.txbd[txIdx].cbd_sc);
 
177
#endif
 
178
 
 
179
    /* return only status bits */
 
180
    result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
 
181
 
 
182
out:
 
183
    return result;
 
184
}
 
185
 
 
186
static int fec_recv(struct eth_device* dev)
 
187
{
 
188
    int length;
 
189
 
 
190
    for (;;)
 
191
    {
 
192
        if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
 
193
            length = -1;
 
194
            break;     /* nothing received - leave for() loop */
 
195
        }
 
196
        length = rtx.rxbd[rxIdx].cbd_datlen;
 
197
 
 
198
        if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
 
199
            printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
 
200
        }
 
201
        else {
 
202
            /* Pass the packet up to the protocol layers. */
 
203
            NetReceive(NetRxPackets[rxIdx], length - 4);
 
204
        }
 
205
 
 
206
 
 
207
        /* Give the buffer back to the FCC. */
 
208
        rtx.rxbd[rxIdx].cbd_datlen = 0;
 
209
 
 
210
        /* wrap around buffer index when necessary */
 
211
        if ((rxIdx + 1) >= PKTBUFSRX) {
 
212
            rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
 
213
            rxIdx = 0;
 
214
        }
 
215
        else {
 
216
            rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
 
217
            rxIdx++;
 
218
        }
 
219
    }
 
220
    return length;
 
221
}
 
222
 
 
223
 
 
224
static int fec_init(struct eth_device* dev, bd_t *bis)
 
225
{
 
226
    struct ether_fcc_info_s * info = dev->priv;
 
227
    int i;
 
228
    volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 
229
    volatile cpm8260_t *cp = &(immr->im_cpm);
 
230
    fcc_enet_t *pram_ptr;
 
231
    unsigned long mem_addr;
 
232
 
 
233
#if 0
 
234
    mii_discover_phy();
 
235
#endif
 
236
 
 
237
    /* 28.9 - (1-2): ioports have been set up already */
 
238
 
 
239
    /* 28.9 - (3): connect FCC's tx and rx clocks */
 
240
    immr->im_cpmux.cmx_uar = 0;
 
241
    immr->im_cpmux.cmx_fcr = (immr->im_cpmux.cmx_fcr & ~info->cmxfcr_mask) |
 
242
                                                        info->cmxfcr_value;
 
243
 
 
244
    /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
 
245
    immr->im_fcc[info->ether_index].fcc_gfmr =
 
246
      FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
 
247
 
 
248
    /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet */
 
249
    immr->im_fcc[info->ether_index].fcc_fpsmr = CONFIG_SYS_FCC_PSMR | FCC_PSMR_ENCRC;
 
250
 
 
251
    /* 28.9 - (6): FDSR: Ethernet Syn */
 
252
    immr->im_fcc[info->ether_index].fcc_fdsr = 0xD555;
 
253
 
 
254
    /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
 
255
    rxIdx = 0;
 
256
    txIdx = 0;
 
257
 
 
258
    /* Setup Receiver Buffer Descriptors */
 
259
    for (i = 0; i < PKTBUFSRX; i++)
 
260
    {
 
261
      rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
 
262
      rtx.rxbd[i].cbd_datlen = 0;
 
263
      rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
 
264
    }
 
265
    rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
 
266
 
 
267
    /* Setup Ethernet Transmitter Buffer Descriptors */
 
268
    for (i = 0; i < TX_BUF_CNT; i++)
 
269
    {
 
270
      rtx.txbd[i].cbd_sc = (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
 
271
      rtx.txbd[i].cbd_datlen = 0;
 
272
      rtx.txbd[i].cbd_bufaddr = (uint)&txbuf[i][0];
 
273
    }
 
274
    rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
 
275
 
 
276
    /* 28.9 - (7): initialise parameter ram */
 
277
    pram_ptr = (fcc_enet_t *)&(immr->im_dprambase[info->proff_enet]);
 
278
 
 
279
    /* clear whole structure to make sure all reserved fields are zero */
 
280
    memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
 
281
 
 
282
    /*
 
283
     * common Parameter RAM area
 
284
     *
 
285
     * Allocate space in the reserved FCC area of DPRAM for the
 
286
     * internal buffers.  No one uses this space (yet), so we
 
287
     * can do this.  Later, we will add resource management for
 
288
     * this area.
 
289
     */
 
290
    mem_addr = CPM_FCC_SPECIAL_BASE + ((info->ether_index) * 64);
 
291
    pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
 
292
    pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
 
293
    /*
 
294
     * Set maximum bytes per receive buffer.
 
295
     * It must be a multiple of 32.
 
296
     */
 
297
    pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
 
298
    pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
 
299
                                       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
 
300
    pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
 
301
    pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
 
302
                                       CONFIG_SYS_CPMFCR_RAMTYPE) << 24;
 
303
    pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
 
304
 
 
305
    /* protocol-specific area */
 
306
    pram_ptr->fen_cmask = 0xdebb20e3;   /* CRC mask */
 
307
    pram_ptr->fen_cpres = 0xffffffff;   /* CRC preset */
 
308
    pram_ptr->fen_retlim = 15;          /* Retry limit threshold */
 
309
    pram_ptr->fen_mflr = PKT_MAXBUF_SIZE;   /* maximum frame length register */
 
310
    /*
 
311
     * Set Ethernet station address.
 
312
     *
 
313
     * This is supplied in the board information structure, so we
 
314
     * copy that into the controller.
 
315
     * So, far we have only been given one Ethernet address. We make
 
316
     * it unique by setting a few bits in the upper byte of the
 
317
     * non-static part of the address.
 
318
     */
 
319
#define ea eth_get_dev()->enetaddr
 
320
    pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
 
321
    pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
 
322
    pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
 
323
#undef ea
 
324
    pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
 
325
    /* pad pointer. use tiptr since we don't need a specific padding char */
 
326
    pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
 
327
    pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE;      /* maximum DMA1 length */
 
328
    pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE;      /* maximum DMA2 length */
 
329
    pram_ptr->fen_rfthr = 1;
 
330
    pram_ptr->fen_rfcnt = 1;
 
331
#if 0
 
332
    printf("pram_ptr->fen_genfcc.fcc_rbase %08lx\n",
 
333
        pram_ptr->fen_genfcc.fcc_rbase);
 
334
    printf("pram_ptr->fen_genfcc.fcc_tbase %08lx\n",
 
335
        pram_ptr->fen_genfcc.fcc_tbase);
 
336
#endif
 
337
 
 
338
    /* 28.9 - (8): clear out events in FCCE */
 
339
    immr->im_fcc[info->ether_index].fcc_fcce = ~0x0;
 
340
 
 
341
    /* 28.9 - (9): FCCM: mask all events */
 
342
    immr->im_fcc[info->ether_index].fcc_fccm = 0;
 
343
 
 
344
    /* 28.9 - (10-12): we don't use ethernet interrupts */
 
345
 
 
346
    /* 28.9 - (13)
 
347
     *
 
348
     * Let's re-initialize the channel now.  We have to do it later
 
349
     * than the manual describes because we have just now finished
 
350
     * the BD initialization.
 
351
     */
 
352
    cp->cp_cpcr = mk_cr_cmd(info->cpm_cr_enet_page,
 
353
                            info->cpm_cr_enet_sblock,
 
354
                            0x0c,
 
355
                            CPM_CR_INIT_TRX) | CPM_CR_FLG;
 
356
    do {
 
357
        __asm__ __volatile__ ("eieio");
 
358
    } while (cp->cp_cpcr & CPM_CR_FLG);
 
359
 
 
360
    /* 28.9 - (14): enable tx/rx in gfmr */
 
361
    immr->im_fcc[info->ether_index].fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
 
362
 
 
363
    return 1;
 
364
}
 
365
 
 
366
static void fec_halt(struct eth_device* dev)
 
367
{
 
368
    struct ether_fcc_info_s * info = dev->priv;
 
369
    volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 
370
 
 
371
    /* write GFMR: disable tx/rx */
 
372
    immr->im_fcc[info->ether_index].fcc_gfmr &=
 
373
                                                ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
 
374
}
 
375
 
 
376
int fec_initialize(bd_t *bis)
 
377
{
 
378
        struct eth_device* dev;
 
379
        int i;
 
380
 
 
381
        for (i = 0; i < sizeof(ether_fcc_info) / sizeof(ether_fcc_info[0]); i++)
 
382
        {
 
383
                dev = (struct eth_device*) malloc(sizeof *dev);
 
384
                memset(dev, 0, sizeof *dev);
 
385
 
 
386
                sprintf(dev->name, "FCC%d ETHERNET",
 
387
                        ether_fcc_info[i].ether_index + 1);
 
388
                dev->priv   = &ether_fcc_info[i];
 
389
                dev->init   = fec_init;
 
390
                dev->halt   = fec_halt;
 
391
                dev->send   = fec_send;
 
392
                dev->recv   = fec_recv;
 
393
 
 
394
                eth_register(dev);
 
395
 
 
396
#if (defined(CONFIG_MII) || defined(CONFIG_CMD_MII)) \
 
397
                && defined(CONFIG_BITBANGMII)
 
398
                miiphy_register(dev->name,
 
399
                                bb_miiphy_read, bb_miiphy_write);
 
400
#endif
 
401
        }
 
402
 
 
403
        return 1;
 
404
}
 
405
 
 
406
#ifdef CONFIG_ETHER_LOOPBACK_TEST
 
407
 
 
408
#define ELBT_BUFSZ      1024    /* must be multiple of 32 */
 
409
 
 
410
#define ELBT_CRCSZ      4
 
411
 
 
412
#define ELBT_NRXBD      4       /* must be at least 2 */
 
413
#define ELBT_NTXBD      4
 
414
 
 
415
#define ELBT_MAXRXERR   32
 
416
#define ELBT_MAXTXERR   32
 
417
 
 
418
#define ELBT_CLSWAIT    1000    /* msec to wait for further input frames */
 
419
 
 
420
typedef
 
421
        struct {
 
422
                uint off;
 
423
                char *lab;
 
424
        }
 
425
elbt_prdesc;
 
426
 
 
427
typedef
 
428
        struct {
 
429
                uint _l, _f, m, bc, mc, lg, no, sh, cr, ov, cl;
 
430
                uint badsrc, badtyp, badlen, badbit;
 
431
        }
 
432
elbt_rxeacc;
 
433
 
 
434
static elbt_prdesc rxeacc_descs[] = {
 
435
        { offsetof(elbt_rxeacc, _l),            "Not Last in Frame"     },
 
436
        { offsetof(elbt_rxeacc, _f),            "Not First in Frame"    },
 
437
        { offsetof(elbt_rxeacc, m),             "Address Miss"          },
 
438
        { offsetof(elbt_rxeacc, bc),            "Broadcast Address"     },
 
439
        { offsetof(elbt_rxeacc, mc),            "Multicast Address"     },
 
440
        { offsetof(elbt_rxeacc, lg),            "Frame Length Violation"},
 
441
        { offsetof(elbt_rxeacc, no),            "Non-Octet Alignment"   },
 
442
        { offsetof(elbt_rxeacc, sh),            "Short Frame"           },
 
443
        { offsetof(elbt_rxeacc, cr),            "CRC Error"             },
 
444
        { offsetof(elbt_rxeacc, ov),            "Overrun"               },
 
445
        { offsetof(elbt_rxeacc, cl),            "Collision"             },
 
446
        { offsetof(elbt_rxeacc, badsrc),        "Bad Src Address"       },
 
447
        { offsetof(elbt_rxeacc, badtyp),        "Bad Frame Type"        },
 
448
        { offsetof(elbt_rxeacc, badlen),        "Bad Frame Length"      },
 
449
        { offsetof(elbt_rxeacc, badbit),        "Data Compare Errors"   },
 
450
};
 
451
static int rxeacc_ndesc = sizeof (rxeacc_descs) / sizeof (rxeacc_descs[0]);
 
452
 
 
453
typedef
 
454
        struct {
 
455
                uint def, hb, lc, rl, rc, un, csl;
 
456
        }
 
457
elbt_txeacc;
 
458
 
 
459
static elbt_prdesc txeacc_descs[] = {
 
460
        { offsetof(elbt_txeacc, def),           "Defer Indication"      },
 
461
        { offsetof(elbt_txeacc, hb),            "Heartbeat"             },
 
462
        { offsetof(elbt_txeacc, lc),            "Late Collision"        },
 
463
        { offsetof(elbt_txeacc, rl),            "Retransmission Limit"  },
 
464
        { offsetof(elbt_txeacc, rc),            "Retry Count"           },
 
465
        { offsetof(elbt_txeacc, un),            "Underrun"              },
 
466
        { offsetof(elbt_txeacc, csl),           "Carrier Sense Lost"    },
 
467
};
 
468
static int txeacc_ndesc = sizeof (txeacc_descs) / sizeof (txeacc_descs[0]);
 
469
 
 
470
typedef
 
471
        struct {
 
472
                uchar rxbufs[ELBT_NRXBD][ELBT_BUFSZ];
 
473
                uchar txbufs[ELBT_NTXBD][ELBT_BUFSZ];
 
474
                cbd_t rxbd[ELBT_NRXBD];
 
475
                cbd_t txbd[ELBT_NTXBD];
 
476
                enum { Idle, Running, Closing, Closed } state;
 
477
                int proff, page, sblock;
 
478
                uint clstime, nsent, ntxerr, nrcvd, nrxerr;
 
479
                ushort rxerrs[ELBT_MAXRXERR], txerrs[ELBT_MAXTXERR];
 
480
                elbt_rxeacc rxeacc;
 
481
                elbt_txeacc txeacc;
 
482
        } __attribute__ ((aligned(8)))
 
483
elbt_chan;
 
484
 
 
485
static uchar patbytes[ELBT_NTXBD] = {
 
486
        0xff, 0xaa, 0x55, 0x00
 
487
};
 
488
static uint patwords[ELBT_NTXBD] = {
 
489
        0xffffffff, 0xaaaaaaaa, 0x55555555, 0x00000000
 
490
};
 
491
 
 
492
#ifdef __GNUC__
 
493
static elbt_chan elbt_chans[3] __attribute__ ((aligned(8)));
 
494
#else
 
495
#error "elbt_chans must be 64-bit aligned"
 
496
#endif
 
497
 
 
498
#define CPM_CR_GRACEFUL_STOP_TX ((ushort)0x0005)
 
499
 
 
500
static elbt_prdesc epram_descs[] = {
 
501
        { offsetof(fcc_enet_t, fen_crcec),      "CRC Errors"            },
 
502
        { offsetof(fcc_enet_t, fen_alec),       "Alignment Errors"      },
 
503
        { offsetof(fcc_enet_t, fen_disfc),      "Discarded Frames"      },
 
504
        { offsetof(fcc_enet_t, fen_octc),       "Octets"                },
 
505
        { offsetof(fcc_enet_t, fen_colc),       "Collisions"            },
 
506
        { offsetof(fcc_enet_t, fen_broc),       "Broadcast Frames"      },
 
507
        { offsetof(fcc_enet_t, fen_mulc),       "Multicast Frames"      },
 
508
        { offsetof(fcc_enet_t, fen_uspc),       "Undersize Frames"      },
 
509
        { offsetof(fcc_enet_t, fen_frgc),       "Fragments"             },
 
510
        { offsetof(fcc_enet_t, fen_ospc),       "Oversize Frames"       },
 
511
        { offsetof(fcc_enet_t, fen_jbrc),       "Jabbers"               },
 
512
        { offsetof(fcc_enet_t, fen_p64c),       "64 Octet Frames"       },
 
513
        { offsetof(fcc_enet_t, fen_p65c),       "65-127 Octet Frames"   },
 
514
        { offsetof(fcc_enet_t, fen_p128c),      "128-255 Octet Frames"  },
 
515
        { offsetof(fcc_enet_t, fen_p256c),      "256-511 Octet Frames"  },
 
516
        { offsetof(fcc_enet_t, fen_p512c),      "512-1023 Octet Frames" },
 
517
        { offsetof(fcc_enet_t, fen_p1024c),     "1024-1518 Octet Frames"},
 
518
};
 
519
static int epram_ndesc = sizeof (epram_descs) / sizeof (epram_descs[0]);
 
520
 
 
521
/*
 
522
 * given an elbt_prdesc array and an array of base addresses, print
 
523
 * each prdesc down the screen with the values fetched from each
 
524
 * base address across the screen
 
525
 */
 
526
static void
 
527
print_desc (elbt_prdesc descs[], int ndesc, uchar *bases[], int nbase)
 
528
{
 
529
        elbt_prdesc *dp = descs, *edp = dp + ndesc;
 
530
        int i;
 
531
 
 
532
        printf ("%32s", "");
 
533
 
 
534
        for (i = 0; i < nbase; i++)
 
535
                printf ("  Channel %d", i);
 
536
 
 
537
        putc ('\n');
 
538
 
 
539
        while (dp < edp) {
 
540
 
 
541
                printf ("%-32s", dp->lab);
 
542
 
 
543
                for (i = 0; i < nbase; i++) {
 
544
                        uint val = *(uint *)(bases[i] + dp->off);
 
545
 
 
546
                        printf (" %10u", val);
 
547
                }
 
548
 
 
549
                putc ('\n');
 
550
 
 
551
                dp++;
 
552
        }
 
553
}
 
554
 
 
555
/*
 
556
 * return number of bits that are set in a value; value contains
 
557
 * nbits (right-justified) bits.
 
558
 */
 
559
static uint __inline__
 
560
nbs (uint value, uint nbits)
 
561
{
 
562
        uint cnt = 0;
 
563
#if 1
 
564
        uint pos = sizeof (uint) * 8;
 
565
 
 
566
        __asm__ __volatile__ ("\
 
567
        mtctr   %2\n\
 
568
1:      rlwnm.  %2,%1,%4,31,31\n\
 
569
        beq     2f\n\
 
570
        addi    %0,%0,1\n\
 
571
2:      subi    %4,%4,1\n\
 
572
        bdnz    1b"
 
573
        : "=r"(cnt)
 
574
        : "r"(value), "r"(nbits), "r"(cnt), "r"(pos)
 
575
        : "ctr", "cc" );
 
576
#else
 
577
        uint mask = 1;
 
578
 
 
579
        do {
 
580
                if (value & mask)
 
581
                        cnt++;
 
582
                mask <<= 1;
 
583
        } while (--nbits);
 
584
#endif
 
585
 
 
586
        return (cnt);
 
587
}
 
588
 
 
589
static ulong
 
590
badbits (uchar *bp, int n, ulong pat)
 
591
{
 
592
        ulong *lp, cnt = 0;
 
593
        int nl;
 
594
 
 
595
        while (n > 0 && ((ulong)bp & (sizeof (ulong) - 1)) != 0) {
 
596
                uchar diff;
 
597
 
 
598
                diff = *bp++ ^ (uchar)pat;
 
599
 
 
600
                if (diff)
 
601
                        cnt += nbs ((ulong)diff, 8);
 
602
 
 
603
                n--;
 
604
        }
 
605
 
 
606
        lp = (ulong *)bp;
 
607
        nl = n / sizeof (ulong);
 
608
        n -= nl * sizeof (ulong);
 
609
 
 
610
        while (nl > 0) {
 
611
                ulong diff;
 
612
 
 
613
                diff = *lp++ ^ pat;
 
614
 
 
615
                if (diff)
 
616
                        cnt += nbs (diff, 32);
 
617
 
 
618
                nl--;
 
619
        }
 
620
 
 
621
        bp = (uchar *)lp;
 
622
 
 
623
        while (n > 0) {
 
624
                uchar diff;
 
625
 
 
626
                diff = *bp++ ^ (uchar)pat;
 
627
 
 
628
                if (diff)
 
629
                        cnt += nbs ((ulong)diff, 8);
 
630
 
 
631
                n--;
 
632
        }
 
633
 
 
634
        return (cnt);
 
635
}
 
636
 
 
637
static inline unsigned short
 
638
swap16 (unsigned short x)
 
639
{
 
640
        return (((x & 0xff) << 8) | ((x & 0xff00) >> 8));
 
641
}
 
642
 
 
643
/* broadcast is not an error - we send them like that */
 
644
#define BD_ENET_RX_ERRS (BD_ENET_RX_STATS & ~BD_ENET_RX_BC)
 
645
 
 
646
void
 
647
eth_loopback_test (void)
 
648
{
 
649
        volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 
650
        volatile cpm8260_t *cp = &(immr->im_cpm);
 
651
        int c, nclosed;
 
652
        ulong runtime, nmsec;
 
653
        uchar *bases[3];
 
654
 
 
655
        puts ("FCC Ethernet External loopback test\n");
 
656
 
 
657
        eth_getenv_enetaddr("ethaddr", NetOurEther);
 
658
 
 
659
        /*
 
660
         * global initialisations for all FCC channels
 
661
         */
 
662
 
 
663
        /* 28.9 - (1-2): ioports have been set up already */
 
664
 
 
665
#if defined(CONFIG_HYMOD)
 
666
        /*
 
667
         * Attention: this is board-specific
 
668
         * 0, FCC1
 
669
         * 1, FCC2
 
670
         * 2, FCC3
 
671
         */
 
672
#       define FCC_START_LOOP 0
 
673
#       define FCC_END_LOOP   2
 
674
 
 
675
        /*
 
676
         * Attention: this is board-specific
 
677
         * - FCC1 Rx-CLK is CLK10
 
678
         * - FCC1 Tx-CLK is CLK11
 
679
         * - FCC2 Rx-CLK is CLK13
 
680
         * - FCC2 Tx-CLK is CLK14
 
681
         * - FCC3 Rx-CLK is CLK15
 
682
         * - FCC3 Tx-CLK is CLK16
 
683
         */
 
684
 
 
685
        /* 28.9 - (3): connect FCC's tx and rx clocks */
 
686
        immr->im_cpmux.cmx_uar = 0;
 
687
        immr->im_cpmux.cmx_fcr = CMXFCR_RF1CS_CLK10|CMXFCR_TF1CS_CLK11|\
 
688
            CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14|\
 
689
            CMXFCR_RF3CS_CLK15|CMXFCR_TF3CS_CLK16;
 
690
#elif defined(CONFIG_SBC8260) || defined(CONFIG_SACSng)
 
691
        /*
 
692
         * Attention: this is board-specific
 
693
         * 1, FCC2
 
694
         */
 
695
#       define FCC_START_LOOP 1
 
696
#       define FCC_END_LOOP   1
 
697
 
 
698
        /*
 
699
         * Attention: this is board-specific
 
700
         * - FCC2 Rx-CLK is CLK13
 
701
         * - FCC2 Tx-CLK is CLK14
 
702
         */
 
703
 
 
704
        /* 28.9 - (3): connect FCC's tx and rx clocks */
 
705
        immr->im_cpmux.cmx_uar = 0;
 
706
        immr->im_cpmux.cmx_fcr = CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14;
 
707
#else
 
708
#error "eth_loopback_test not supported on your board"
 
709
#endif
 
710
 
 
711
        puts ("Initialise FCC channels:");
 
712
 
 
713
        for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
 
714
                elbt_chan *ecp = &elbt_chans[c];
 
715
                volatile fcc_t *fcp = &immr->im_fcc[c];
 
716
                volatile fcc_enet_t *fpp;
 
717
                int i;
 
718
                ulong addr;
 
719
 
 
720
                /*
 
721
                 * initialise channel data
 
722
                 */
 
723
 
 
724
                printf (" %d", c);
 
725
 
 
726
                memset ((void *)ecp, 0, sizeof (*ecp));
 
727
 
 
728
                ecp->state = Idle;
 
729
 
 
730
                switch (c) {
 
731
 
 
732
                case 0: /* FCC1 */
 
733
                        ecp->proff = PROFF_FCC1;
 
734
                        ecp->page = CPM_CR_FCC1_PAGE;
 
735
                        ecp->sblock = CPM_CR_FCC1_SBLOCK;
 
736
                        break;
 
737
 
 
738
                case 1: /* FCC2 */
 
739
                        ecp->proff = PROFF_FCC2;
 
740
                        ecp->page = CPM_CR_FCC2_PAGE;
 
741
                        ecp->sblock = CPM_CR_FCC2_SBLOCK;
 
742
                        break;
 
743
 
 
744
                case 2: /* FCC3 */
 
745
                        ecp->proff = PROFF_FCC3;
 
746
                        ecp->page = CPM_CR_FCC3_PAGE;
 
747
                        ecp->sblock = CPM_CR_FCC3_SBLOCK;
 
748
                        break;
 
749
                }
 
750
 
 
751
                /*
 
752
                 * set up tx buffers and bds
 
753
                 */
 
754
 
 
755
                for (i = 0; i < ELBT_NTXBD; i++) {
 
756
                        cbd_t *bdp = &ecp->txbd[i];
 
757
                        uchar *bp = &ecp->txbufs[i][0];
 
758
 
 
759
                        bdp->cbd_bufaddr = (uint)bp;
 
760
                        /* room for crc */
 
761
                        bdp->cbd_datlen = ELBT_BUFSZ - ELBT_CRCSZ;
 
762
                        bdp->cbd_sc = BD_ENET_TX_READY | BD_ENET_TX_PAD | \
 
763
                                BD_ENET_TX_LAST | BD_ENET_TX_TC;
 
764
 
 
765
                        memset ((void *)bp, patbytes[i], ELBT_BUFSZ);
 
766
                        NetSetEther (bp, NetBcastAddr, 0x8000);
 
767
                }
 
768
                ecp->txbd[ELBT_NTXBD - 1].cbd_sc |= BD_ENET_TX_WRAP;
 
769
 
 
770
                /*
 
771
                 * set up rx buffers and bds
 
772
                 */
 
773
 
 
774
                for (i = 0; i < ELBT_NRXBD; i++) {
 
775
                    cbd_t *bdp = &ecp->rxbd[i];
 
776
                    uchar *bp = &ecp->rxbufs[i][0];
 
777
 
 
778
                    bdp->cbd_bufaddr = (uint)bp;
 
779
                    bdp->cbd_datlen = 0;
 
780
                    bdp->cbd_sc = BD_ENET_RX_EMPTY;
 
781
 
 
782
                    memset ((void *)bp, 0, ELBT_BUFSZ);
 
783
                }
 
784
                ecp->rxbd[ELBT_NRXBD - 1].cbd_sc |= BD_ENET_RX_WRAP;
 
785
 
 
786
                /*
 
787
                 * set up the FCC channel hardware
 
788
                 */
 
789
 
 
790
                /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
 
791
                fcp->fcc_gfmr = FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
 
792
 
 
793
                /* 28.9 - (5): FPSMR: fd, enet CRC, Promis, RMON, Rx SHort */
 
794
                fcp->fcc_fpsmr = FCC_PSMR_FDE | FCC_PSMR_LPB | \
 
795
                        FCC_PSMR_ENCRC | FCC_PSMR_PRO | \
 
796
                        FCC_PSMR_MON | FCC_PSMR_RSH;
 
797
 
 
798
                /* 28.9 - (6): FDSR: Ethernet Syn */
 
799
                fcp->fcc_fdsr = 0xD555;
 
800
 
 
801
                /* 29.9 - (7): initialise parameter ram */
 
802
                fpp = (fcc_enet_t *)&(immr->im_dprambase[ecp->proff]);
 
803
 
 
804
                /* clear whole struct to make sure all resv fields are zero */
 
805
                memset ((void *)fpp, 0, sizeof (fcc_enet_t));
 
806
 
 
807
                /*
 
808
                 * common Parameter RAM area
 
809
                 *
 
810
                 * Allocate space in the reserved FCC area of DPRAM for the
 
811
                 * internal buffers.  No one uses this space (yet), so we
 
812
                 * can do this.  Later, we will add resource management for
 
813
                 * this area.
 
814
                 */
 
815
                addr = CPM_FCC_SPECIAL_BASE + (c * 64);
 
816
                fpp->fen_genfcc.fcc_riptr = addr;
 
817
                fpp->fen_genfcc.fcc_tiptr = addr + 32;
 
818
 
 
819
                /*
 
820
                 * Set maximum bytes per receive buffer.
 
821
                 * It must be a multiple of 32.
 
822
                 * buffers are in 60x bus memory.
 
823
                 */
 
824
                fpp->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
 
825
                fpp->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
 
826
                fpp->fen_genfcc.fcc_rbase = (unsigned int)(&ecp->rxbd[0]);
 
827
                fpp->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB) << 24;
 
828
                fpp->fen_genfcc.fcc_tbase = (unsigned int)(&ecp->txbd[0]);
 
829
 
 
830
                /* protocol-specific area */
 
831
                fpp->fen_cmask = 0xdebb20e3;    /* CRC mask */
 
832
                fpp->fen_cpres = 0xffffffff;    /* CRC preset */
 
833
                fpp->fen_retlim = 15;           /* Retry limit threshold */
 
834
                fpp->fen_mflr = PKT_MAXBUF_SIZE;/* max frame length register */
 
835
 
 
836
                /*
 
837
                 * Set Ethernet station address.
 
838
                 *
 
839
                 * This is supplied in the board information structure, so we
 
840
                 * copy that into the controller.
 
841
                 * So, far we have only been given one Ethernet address. We use
 
842
                 * the same address for all channels
 
843
                 */
 
844
#define ea NetOurEther
 
845
                fpp->fen_paddrh = (ea[5] << 8) + ea[4];
 
846
                fpp->fen_paddrm = (ea[3] << 8) + ea[2];
 
847
                fpp->fen_paddrl = (ea[1] << 8) + ea[0];
 
848
#undef ea
 
849
 
 
850
                fpp->fen_minflr = PKT_MINBUF_SIZE; /* min frame len register */
 
851
                /*
 
852
                 * pad pointer. use tiptr since we don't need
 
853
                 * a specific padding char
 
854
                 */
 
855
                fpp->fen_padptr = fpp->fen_genfcc.fcc_tiptr;
 
856
                fpp->fen_maxd1 = PKT_MAXDMA_SIZE;       /* max DMA1 length */
 
857
                fpp->fen_maxd2 = PKT_MAXDMA_SIZE;       /* max DMA2 length */
 
858
                fpp->fen_rfthr = 1;
 
859
                fpp->fen_rfcnt = 1;
 
860
 
 
861
                /* 28.9 - (8): clear out events in FCCE */
 
862
                fcp->fcc_fcce = ~0x0;
 
863
 
 
864
                /* 28.9 - (9): FCCM: mask all events */
 
865
                fcp->fcc_fccm = 0;
 
866
 
 
867
                /* 28.9 - (10-12): we don't use ethernet interrupts */
 
868
 
 
869
                /* 28.9 - (13)
 
870
                 *
 
871
                 * Let's re-initialize the channel now.  We have to do it later
 
872
                 * than the manual describes because we have just now finished
 
873
                 * the BD initialization.
 
874
                 */
 
875
                cp->cp_cpcr = mk_cr_cmd (ecp->page, ecp->sblock, \
 
876
                        0x0c, CPM_CR_INIT_TRX) | CPM_CR_FLG;
 
877
                do {
 
878
                        __asm__ __volatile__ ("eieio");
 
879
                } while (cp->cp_cpcr & CPM_CR_FLG);
 
880
        }
 
881
 
 
882
        puts (" done\nStarting test... (Ctrl-C to Finish)\n");
 
883
 
 
884
        /*
 
885
         * Note: don't want serial output from here until the end of the
 
886
         * test - the delays would probably stuff things up.
 
887
         */
 
888
 
 
889
        clear_ctrlc ();
 
890
        runtime = get_timer (0);
 
891
 
 
892
        do {
 
893
                nclosed = 0;
 
894
 
 
895
                for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
 
896
                        volatile fcc_t *fcp = &immr->im_fcc[c];
 
897
                        elbt_chan *ecp = &elbt_chans[c];
 
898
                        int i;
 
899
 
 
900
                        switch (ecp->state) {
 
901
 
 
902
                        case Idle:
 
903
                                /*
 
904
                                 * set the channel Running ...
 
905
                                 */
 
906
 
 
907
                                /* 28.9 - (14): enable tx/rx in gfmr */
 
908
                                fcp->fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
 
909
 
 
910
                                ecp->state = Running;
 
911
                                break;
 
912
 
 
913
                        case Running:
 
914
                                /*
 
915
                                 * (while Running only) check for
 
916
                                 * termination of the test
 
917
                                 */
 
918
 
 
919
                                (void)ctrlc ();
 
920
 
 
921
                                if (had_ctrlc ()) {
 
922
                                        /*
 
923
                                         * initiate a "graceful stop transmit"
 
924
                                         * on the channel
 
925
                                         */
 
926
                                        cp->cp_cpcr = mk_cr_cmd (ecp->page, \
 
927
                                                ecp->sblock, 0x0c, \
 
928
                                                CPM_CR_GRACEFUL_STOP_TX) | \
 
929
                                                CPM_CR_FLG;
 
930
                                        do {
 
931
                                                __asm__ __volatile__ ("eieio");
 
932
                                        } while (cp->cp_cpcr & CPM_CR_FLG);
 
933
 
 
934
                                        ecp->clstime = get_timer (0);
 
935
                                        ecp->state = Closing;
 
936
                                }
 
937
                                /* fall through ... */
 
938
 
 
939
                        case Closing:
 
940
                                /*
 
941
                                 * (while Running or Closing) poll the channel:
 
942
                                 * - check for any non-READY tx buffers and
 
943
                                 *   make them ready
 
944
                                 * - check for any non-EMPTY rx buffers and
 
945
                                 *   check that they were received correctly,
 
946
                                 *   adjust counters etc, then make empty
 
947
                                 */
 
948
 
 
949
                                for (i = 0; i < ELBT_NTXBD; i++) {
 
950
                                        cbd_t *bdp = &ecp->txbd[i];
 
951
                                        ushort sc = bdp->cbd_sc;
 
952
 
 
953
                                        if ((sc & BD_ENET_TX_READY) != 0)
 
954
                                                continue;
 
955
 
 
956
                                        /*
 
957
                                         * this frame has finished
 
958
                                         * transmitting
 
959
                                         */
 
960
                                        ecp->nsent++;
 
961
 
 
962
                                        if (sc & BD_ENET_TX_STATS) {
 
963
                                                ulong n;
 
964
 
 
965
                                                /*
 
966
                                                 * we had an error on
 
967
                                                 * the transmission
 
968
                                                 */
 
969
                                                n = ecp->ntxerr++;
 
970
                                                if (n < ELBT_MAXTXERR)
 
971
                                                        ecp->txerrs[n] = sc;
 
972
 
 
973
                                                if (sc & BD_ENET_TX_DEF)
 
974
                                                        ecp->txeacc.def++;
 
975
                                                if (sc & BD_ENET_TX_HB)
 
976
                                                        ecp->txeacc.hb++;
 
977
                                                if (sc & BD_ENET_TX_LC)
 
978
                                                        ecp->txeacc.lc++;
 
979
                                                if (sc & BD_ENET_TX_RL)
 
980
                                                        ecp->txeacc.rl++;
 
981
                                                if (sc & BD_ENET_TX_RCMASK)
 
982
                                                        ecp->txeacc.rc++;
 
983
                                                if (sc & BD_ENET_TX_UN)
 
984
                                                        ecp->txeacc.un++;
 
985
                                                if (sc & BD_ENET_TX_CSL)
 
986
                                                        ecp->txeacc.csl++;
 
987
 
 
988
                                                bdp->cbd_sc &= \
 
989
                                                        ~BD_ENET_TX_STATS;
 
990
                                        }
 
991
 
 
992
                                        if (ecp->state == Closing)
 
993
                                                ecp->clstime = get_timer (0);
 
994
 
 
995
                                        /* make it ready again */
 
996
                                        bdp->cbd_sc |= BD_ENET_TX_READY;
 
997
                                }
 
998
 
 
999
                                for (i = 0; i < ELBT_NRXBD; i++) {
 
1000
                                        cbd_t *bdp = &ecp->rxbd[i];
 
1001
                                        ushort sc = bdp->cbd_sc, mask;
 
1002
 
 
1003
                                        if ((sc & BD_ENET_RX_EMPTY) != 0)
 
1004
                                                continue;
 
1005
 
 
1006
                                        /* we have a new frame in this buffer */
 
1007
                                        ecp->nrcvd++;
 
1008
 
 
1009
                                        mask = BD_ENET_RX_LAST|BD_ENET_RX_FIRST;
 
1010
                                        if ((sc & mask) != mask) {
 
1011
                                                /* somethings wrong here ... */
 
1012
                                                if (!(sc & BD_ENET_RX_LAST))
 
1013
                                                        ecp->rxeacc._l++;
 
1014
                                                if (!(sc & BD_ENET_RX_FIRST))
 
1015
                                                        ecp->rxeacc._f++;
 
1016
                                        }
 
1017
 
 
1018
                                        if (sc & BD_ENET_RX_ERRS) {
 
1019
                                                ulong n;
 
1020
 
 
1021
                                                /*
 
1022
                                                 * we had some sort of error
 
1023
                                                 * on the frame
 
1024
                                                 */
 
1025
                                                n = ecp->nrxerr++;
 
1026
                                                if (n < ELBT_MAXRXERR)
 
1027
                                                        ecp->rxerrs[n] = sc;
 
1028
 
 
1029
                                                if (sc & BD_ENET_RX_MISS)
 
1030
                                                        ecp->rxeacc.m++;
 
1031
                                                if (sc & BD_ENET_RX_BC)
 
1032
                                                        ecp->rxeacc.bc++;
 
1033
                                                if (sc & BD_ENET_RX_MC)
 
1034
                                                        ecp->rxeacc.mc++;
 
1035
                                                if (sc & BD_ENET_RX_LG)
 
1036
                                                        ecp->rxeacc.lg++;
 
1037
                                                if (sc & BD_ENET_RX_NO)
 
1038
                                                        ecp->rxeacc.no++;
 
1039
                                                if (sc & BD_ENET_RX_SH)
 
1040
                                                        ecp->rxeacc.sh++;
 
1041
                                                if (sc & BD_ENET_RX_CR)
 
1042
                                                        ecp->rxeacc.cr++;
 
1043
                                                if (sc & BD_ENET_RX_OV)
 
1044
                                                        ecp->rxeacc.ov++;
 
1045
                                                if (sc & BD_ENET_RX_CL)
 
1046
                                                        ecp->rxeacc.cl++;
 
1047
 
 
1048
                                                bdp->cbd_sc &= \
 
1049
                                                        ~BD_ENET_RX_ERRS;
 
1050
                                        }
 
1051
                                        else {
 
1052
                                                ushort datlen = bdp->cbd_datlen;
 
1053
                                                Ethernet_t *ehp;
 
1054
                                                ushort prot;
 
1055
                                                int ours, tb, n, nbytes;
 
1056
 
 
1057
                                                ehp = (Ethernet_t *) \
 
1058
                                                        &ecp->rxbufs[i][0];
 
1059
 
 
1060
                                                ours = memcmp (ehp->et_src, \
 
1061
                                                        NetOurEther, 6);
 
1062
 
 
1063
                                                prot = swap16 (ehp->et_protlen);
 
1064
                                                tb = prot & 0x8000;
 
1065
                                                n = prot & 0x7fff;
 
1066
 
 
1067
                                                nbytes = ELBT_BUFSZ - \
 
1068
                                                        offsetof (Ethernet_t, \
 
1069
                                                                et_dsap) - \
 
1070
                                                        ELBT_CRCSZ;
 
1071
 
 
1072
                                                /* check the frame is correct */
 
1073
                                                if (datlen != ELBT_BUFSZ)
 
1074
                                                        ecp->rxeacc.badlen++;
 
1075
                                                else if (!ours)
 
1076
                                                        ecp->rxeacc.badsrc++;
 
1077
                                                else if (!tb || n >= ELBT_NTXBD)
 
1078
                                                        ecp->rxeacc.badtyp++;
 
1079
                                                else {
 
1080
                                                        ulong patword = \
 
1081
                                                                patwords[n];
 
1082
                                                        uint nbb;
 
1083
 
 
1084
                                                        nbb = badbits ( \
 
1085
                                                                &ehp->et_dsap, \
 
1086
                                                                nbytes, \
 
1087
                                                                patword);
 
1088
 
 
1089
                                                        ecp->rxeacc.badbit += \
 
1090
                                                                nbb;
 
1091
                                                }
 
1092
                                        }
 
1093
 
 
1094
                                        if (ecp->state == Closing)
 
1095
                                            ecp->clstime = get_timer (0);
 
1096
 
 
1097
                                        /* make it empty again */
 
1098
                                        bdp->cbd_sc |= BD_ENET_RX_EMPTY;
 
1099
                                }
 
1100
 
 
1101
                                if (ecp->state != Closing)
 
1102
                                        break;
 
1103
 
 
1104
                                /*
 
1105
                                 * (while Closing) check to see if
 
1106
                                 * waited long enough
 
1107
                                 */
 
1108
 
 
1109
                                if (get_timer (ecp->clstime) >= ELBT_CLSWAIT) {
 
1110
                                        /* write GFMR: disable tx/rx */
 
1111
                                        fcp->fcc_gfmr &= \
 
1112
                                                ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
 
1113
                                        ecp->state = Closed;
 
1114
                                }
 
1115
 
 
1116
                                break;
 
1117
 
 
1118
                        case Closed:
 
1119
                                nclosed++;
 
1120
                                break;
 
1121
                        }
 
1122
                }
 
1123
 
 
1124
        } while (nclosed < (FCC_END_LOOP - FCC_START_LOOP + 1));
 
1125
 
 
1126
        runtime = get_timer (runtime);
 
1127
        if (runtime <= ELBT_CLSWAIT) {
 
1128
                printf ("Whoops! somehow elapsed time (%ld) is wrong (<= %d)\n",
 
1129
                        runtime, ELBT_CLSWAIT);
 
1130
                return;
 
1131
        }
 
1132
        nmsec = runtime - ELBT_CLSWAIT;
 
1133
 
 
1134
        printf ("Test Finished in %ldms (plus %dms close wait period)!\n\n",
 
1135
                nmsec, ELBT_CLSWAIT);
 
1136
 
 
1137
        /*
 
1138
         * now print stats
 
1139
         */
 
1140
 
 
1141
        for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++) {
 
1142
                elbt_chan *ecp = &elbt_chans[c];
 
1143
                uint rxpps, txpps, nerr;
 
1144
 
 
1145
                rxpps = (ecp->nrcvd * 1000) / nmsec;
 
1146
                txpps = (ecp->nsent * 1000) / nmsec;
 
1147
 
 
1148
                printf ("Channel %d: %d rcvd (%d pps, %d rxerrs), "
 
1149
                        "%d sent (%d pps, %d txerrs)\n\n", c,
 
1150
                        ecp->nrcvd, rxpps, ecp->nrxerr,
 
1151
                        ecp->nsent, txpps, ecp->ntxerr);
 
1152
 
 
1153
                if ((nerr = ecp->nrxerr) > 0) {
 
1154
                        ulong i;
 
1155
 
 
1156
                        printf ("\tFirst %d rx errs:", nerr);
 
1157
                        for (i = 0; i < nerr; i++)
 
1158
                                printf (" %04x", ecp->rxerrs[i]);
 
1159
                        putc ('\n');
 
1160
                }
 
1161
 
 
1162
                if ((nerr = ecp->ntxerr) > 0) {
 
1163
                        ulong i;
 
1164
 
 
1165
                        printf ("\tFirst %d tx errs:", nerr);
 
1166
                        for (i = 0; i < nerr; i++)
 
1167
                                printf (" %04x", ecp->txerrs[i]);
 
1168
                        putc ('\n');
 
1169
                }
 
1170
        }
 
1171
 
 
1172
        puts ("Receive Error Counts:\n");
 
1173
        for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
 
1174
                bases[c] = (uchar *)&elbt_chans[c].rxeacc;
 
1175
        print_desc (rxeacc_descs, rxeacc_ndesc, bases, 3);
 
1176
 
 
1177
        puts ("\nTransmit Error Counts:\n");
 
1178
        for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
 
1179
                bases[c] = (uchar *)&elbt_chans[c].txeacc;
 
1180
        print_desc (txeacc_descs, txeacc_ndesc, bases, 3);
 
1181
 
 
1182
        puts ("\nRMON(-like) Counters:\n");
 
1183
        for (c = FCC_START_LOOP; c <= FCC_END_LOOP; c++)
 
1184
                bases[c] = (uchar *)&immr->im_dprambase[elbt_chans[c].proff];
 
1185
        print_desc (epram_descs, epram_ndesc, bases, 3);
 
1186
}
 
1187
 
 
1188
#endif /* CONFIG_ETHER_LOOPBACK_TEST */
 
1189
 
 
1190
#endif