]>
git.ipfire.org Git - people/ms/u-boot.git/blob - cpu/mpc8260/ether_fcc.c
2 * MPC8260 FCC Fast Ethernet
4 * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
6 * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
7 * Marius Groeger <mgroeger@sysgo.de>
9 * See file CREDITS for list of people who contributed to this
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.
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.
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,
29 * MPC8260 FCC Fast Ethernet
30 * Basic ET HW initialization and packet RX/TX routines
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.
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
44 #include <asm/cpm_8260.h>
50 #if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET) && \
51 defined(CONFIG_NET_MULTI)
53 static struct ether_fcc_info_s
57 ulong cpm_cr_enet_sblock
;
58 ulong cpm_cr_enet_page
;
64 #ifdef CONFIG_ETHER_ON_FCC1
75 #ifdef CONFIG_ETHER_ON_FCC2
86 #ifdef CONFIG_ETHER_ON_FCC3
98 /*---------------------------------------------------------------------*/
100 /* Maximum input DMA size. Must be a should(?) be a multiple of 4. */
101 #define PKT_MAXDMA_SIZE 1520
103 /* The FCC stores dest/src/type, data, and checksum for receive packets. */
104 #define PKT_MAXBUF_SIZE 1518
105 #define PKT_MINBUF_SIZE 64
107 /* Maximum input buffer size. Must be a multiple of 32. */
108 #define PKT_MAXBLR_SIZE 1536
110 #define TOUT_LOOP 1000000
114 static char txbuf
[TX_BUF_CNT
][PKT_MAXBLR_SIZE
] __attribute__ ((aligned(8)));
116 #error "txbuf must be 64-bit aligned"
119 static uint rxIdx
; /* index of the current RX buffer */
120 static uint txIdx
; /* index of the current TX buffer */
123 * FCC Ethernet Tx and Rx buffer descriptors.
124 * Provide for Double Buffering
125 * Note: PKTBUFSRX is defined in net.h
128 typedef volatile struct rtxbd
{
129 cbd_t rxbd
[PKTBUFSRX
];
130 cbd_t txbd
[TX_BUF_CNT
];
133 /* Good news: the FCC supports external BDs! */
135 static RTXBD rtx
__attribute__ ((aligned(8)));
137 #error "rtx must be 64-bit aligned"
140 static int fec_send(struct eth_device
* dev
, volatile void *packet
, int length
)
146 printf("fec: bad packet size: %d\n", length
);
150 for(i
=0; rtx
.txbd
[txIdx
].cbd_sc
& BD_ENET_TX_READY
; i
++) {
151 if (i
>= TOUT_LOOP
) {
152 printf("fec: tx buffer not ready\n");
157 rtx
.txbd
[txIdx
].cbd_bufaddr
= (uint
)packet
;
158 rtx
.txbd
[txIdx
].cbd_datlen
= length
;
159 rtx
.txbd
[txIdx
].cbd_sc
|= (BD_ENET_TX_READY
| BD_ENET_TX_LAST
|
162 for(i
=0; rtx
.txbd
[txIdx
].cbd_sc
& BD_ENET_TX_READY
; i
++) {
163 if (i
>= TOUT_LOOP
) {
164 printf("fec: tx error\n");
170 printf("cycles: %d status: %04x\n", i
, rtx
.txbd
[txIdx
].cbd_sc
);
173 /* return only status bits */
174 result
= rtx
.txbd
[txIdx
].cbd_sc
& BD_ENET_TX_STATS
;
180 static int fec_recv(struct eth_device
* dev
)
186 if (rtx
.rxbd
[rxIdx
].cbd_sc
& BD_ENET_RX_EMPTY
) {
188 break; /* nothing received - leave for() loop */
190 length
= rtx
.rxbd
[rxIdx
].cbd_datlen
;
192 if (rtx
.rxbd
[rxIdx
].cbd_sc
& 0x003f) {
193 printf("fec: rx error %04x\n", rtx
.rxbd
[rxIdx
].cbd_sc
);
196 /* Pass the packet up to the protocol layers. */
197 NetReceive(NetRxPackets
[rxIdx
], length
- 4);
201 /* Give the buffer back to the FCC. */
202 rtx
.rxbd
[rxIdx
].cbd_datlen
= 0;
204 /* wrap around buffer index when necessary */
205 if ((rxIdx
+ 1) >= PKTBUFSRX
) {
206 rtx
.rxbd
[PKTBUFSRX
- 1].cbd_sc
= (BD_ENET_RX_WRAP
| BD_ENET_RX_EMPTY
);
210 rtx
.rxbd
[rxIdx
].cbd_sc
= BD_ENET_RX_EMPTY
;
218 static int fec_init(struct eth_device
* dev
, bd_t
*bis
)
220 struct ether_fcc_info_s
* info
= dev
->priv
;
222 volatile immap_t
*immr
= (immap_t
*)CFG_IMMR
;
223 volatile cpm8260_t
*cp
= &(immr
->im_cpm
);
224 fcc_enet_t
*pram_ptr
;
225 unsigned long mem_addr
;
231 /* 28.9 - (1-2): ioports have been set up already */
233 /* 28.9 - (3): connect FCC's tx and rx clocks */
234 immr
->im_cpmux
.cmx_uar
= 0;
235 immr
->im_cpmux
.cmx_fcr
= (immr
->im_cpmux
.cmx_fcr
& ~info
->cmxfcr_mask
) |
238 /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
239 immr
->im_fcc
[info
->ether_index
].fcc_gfmr
=
240 FCC_GFMR_MODE_ENET
| FCC_GFMR_TCRC_32
;
242 /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet */
243 immr
->im_fcc
[info
->ether_index
].fcc_fpsmr
= CFG_FCC_PSMR
| FCC_PSMR_ENCRC
;
245 /* 28.9 - (6): FDSR: Ethernet Syn */
246 immr
->im_fcc
[info
->ether_index
].fcc_fdsr
= 0xD555;
248 /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
252 /* Setup Receiver Buffer Descriptors */
253 for (i
= 0; i
< PKTBUFSRX
; i
++)
255 rtx
.rxbd
[i
].cbd_sc
= BD_ENET_RX_EMPTY
;
256 rtx
.rxbd
[i
].cbd_datlen
= 0;
257 rtx
.rxbd
[i
].cbd_bufaddr
= (uint
)NetRxPackets
[i
];
259 rtx
.rxbd
[PKTBUFSRX
- 1].cbd_sc
|= BD_ENET_RX_WRAP
;
261 /* Setup Ethernet Transmitter Buffer Descriptors */
262 for (i
= 0; i
< TX_BUF_CNT
; i
++)
264 rtx
.txbd
[i
].cbd_sc
= (BD_ENET_TX_PAD
| BD_ENET_TX_LAST
| BD_ENET_TX_TC
);
265 rtx
.txbd
[i
].cbd_datlen
= 0;
266 rtx
.txbd
[i
].cbd_bufaddr
= (uint
)&txbuf
[i
][0];
268 rtx
.txbd
[TX_BUF_CNT
- 1].cbd_sc
|= BD_ENET_TX_WRAP
;
270 /* 28.9 - (7): initialise parameter ram */
271 pram_ptr
= (fcc_enet_t
*)&(immr
->im_dprambase
[info
->proff_enet
]);
273 /* clear whole structure to make sure all reserved fields are zero */
274 memset((void*)pram_ptr
, 0, sizeof(fcc_enet_t
));
277 * common Parameter RAM area
279 * Allocate space in the reserved FCC area of DPRAM for the
280 * internal buffers. No one uses this space (yet), so we
281 * can do this. Later, we will add resource management for
284 mem_addr
= CPM_FCC_SPECIAL_BASE
+ ((info
->ether_index
) * 64);
285 pram_ptr
->fen_genfcc
.fcc_riptr
= mem_addr
;
286 pram_ptr
->fen_genfcc
.fcc_tiptr
= mem_addr
+32;
288 * Set maximum bytes per receive buffer.
289 * It must be a multiple of 32.
291 pram_ptr
->fen_genfcc
.fcc_mrblr
= PKT_MAXBLR_SIZE
;
292 pram_ptr
->fen_genfcc
.fcc_rstate
= (CPMFCR_GBL
| CPMFCR_EB
|
293 CFG_CPMFCR_RAMTYPE
) << 24;
294 pram_ptr
->fen_genfcc
.fcc_rbase
= (unsigned int)(&rtx
.rxbd
[rxIdx
]);
295 pram_ptr
->fen_genfcc
.fcc_tstate
= (CPMFCR_GBL
| CPMFCR_EB
|
296 CFG_CPMFCR_RAMTYPE
) << 24;
297 pram_ptr
->fen_genfcc
.fcc_tbase
= (unsigned int)(&rtx
.txbd
[txIdx
]);
299 /* protocol-specific area */
300 pram_ptr
->fen_cmask
= 0xdebb20e3; /* CRC mask */
301 pram_ptr
->fen_cpres
= 0xffffffff; /* CRC preset */
302 pram_ptr
->fen_retlim
= 15; /* Retry limit threshold */
303 pram_ptr
->fen_mflr
= PKT_MAXBUF_SIZE
; /* maximum frame length register */
305 * Set Ethernet station address.
307 * This is supplied in the board information structure, so we
308 * copy that into the controller.
309 * So, far we have only been given one Ethernet address. We make
310 * it unique by setting a few bits in the upper byte of the
311 * non-static part of the address.
313 #define ea eth_get_dev()->enetaddr
314 pram_ptr
->fen_paddrh
= (ea
[5] << 8) + ea
[4];
315 pram_ptr
->fen_paddrm
= (ea
[3] << 8) + ea
[2];
316 pram_ptr
->fen_paddrl
= (ea
[1] << 8) + ea
[0];
318 pram_ptr
->fen_minflr
= PKT_MINBUF_SIZE
; /* minimum frame length register */
319 /* pad pointer. use tiptr since we don't need a specific padding char */
320 pram_ptr
->fen_padptr
= pram_ptr
->fen_genfcc
.fcc_tiptr
;
321 pram_ptr
->fen_maxd1
= PKT_MAXDMA_SIZE
; /* maximum DMA1 length */
322 pram_ptr
->fen_maxd2
= PKT_MAXDMA_SIZE
; /* maximum DMA2 length */
323 pram_ptr
->fen_rfthr
= 1;
324 pram_ptr
->fen_rfcnt
= 1;
326 printf("pram_ptr->fen_genfcc.fcc_rbase %08lx\n",
327 pram_ptr
->fen_genfcc
.fcc_rbase
);
328 printf("pram_ptr->fen_genfcc.fcc_tbase %08lx\n",
329 pram_ptr
->fen_genfcc
.fcc_tbase
);
332 /* 28.9 - (8): clear out events in FCCE */
333 immr
->im_fcc
[info
->ether_index
].fcc_fcce
= ~0x0;
335 /* 28.9 - (9): FCCM: mask all events */
336 immr
->im_fcc
[info
->ether_index
].fcc_fccm
= 0;
338 /* 28.9 - (10-12): we don't use ethernet interrupts */
342 * Let's re-initialize the channel now. We have to do it later
343 * than the manual describes because we have just now finished
344 * the BD initialization.
346 cp
->cp_cpcr
= mk_cr_cmd(info
->cpm_cr_enet_page
,
347 info
->cpm_cr_enet_sblock
,
349 CPM_CR_INIT_TRX
) | CPM_CR_FLG
;
351 __asm__
__volatile__ ("eieio");
352 } while (cp
->cp_cpcr
& CPM_CR_FLG
);
354 /* 28.9 - (14): enable tx/rx in gfmr */
355 immr
->im_fcc
[info
->ether_index
].fcc_gfmr
|= FCC_GFMR_ENT
| FCC_GFMR_ENR
;
360 static void fec_halt(struct eth_device
* dev
)
362 struct ether_fcc_info_s
* info
= dev
->priv
;
363 volatile immap_t
*immr
= (immap_t
*)CFG_IMMR
;
365 /* write GFMR: disable tx/rx */
366 immr
->im_fcc
[info
->ether_index
].fcc_gfmr
&=
367 ~(FCC_GFMR_ENT
| FCC_GFMR_ENR
);
370 int fec_initialize(bd_t
*bis
)
372 struct eth_device
* dev
;
375 for (i
= 0; i
< sizeof(ether_fcc_info
) / sizeof(ether_fcc_info
[0]); i
++)
377 dev
= (struct eth_device
*) malloc(sizeof *dev
);
378 memset(dev
, 0, sizeof *dev
);
380 sprintf(dev
->name
, "FCC%d ETHERNET",
381 ether_fcc_info
[i
].ether_index
+ 1);
382 dev
->priv
= ðer_fcc_info
[i
];
383 dev
->init
= fec_init
;
384 dev
->halt
= fec_halt
;
385 dev
->send
= fec_send
;
386 dev
->recv
= fec_recv
;
394 #ifdef CONFIG_ETHER_LOOPBACK_TEST
396 #define ELBT_BUFSZ 1024 /* must be multiple of 32 */
400 #define ELBT_NRXBD 4 /* must be at least 2 */
403 #define ELBT_MAXRXERR 32
404 #define ELBT_MAXTXERR 32
406 #define ELBT_CLSWAIT 1000 /* msec to wait for further input frames */
417 uint _l
, _f
, m
, bc
, mc
, lg
, no
, sh
, cr
, ov
, cl
;
418 uint badsrc
, badtyp
, badlen
, badbit
;
422 static elbt_prdesc rxeacc_descs
[] = {
423 { offsetof(elbt_rxeacc
, _l
), "Not Last in Frame" },
424 { offsetof(elbt_rxeacc
, _f
), "Not First in Frame" },
425 { offsetof(elbt_rxeacc
, m
), "Address Miss" },
426 { offsetof(elbt_rxeacc
, bc
), "Broadcast Address" },
427 { offsetof(elbt_rxeacc
, mc
), "Multicast Address" },
428 { offsetof(elbt_rxeacc
, lg
), "Frame Length Violation"},
429 { offsetof(elbt_rxeacc
, no
), "Non-Octet Alignment" },
430 { offsetof(elbt_rxeacc
, sh
), "Short Frame" },
431 { offsetof(elbt_rxeacc
, cr
), "CRC Error" },
432 { offsetof(elbt_rxeacc
, ov
), "Overrun" },
433 { offsetof(elbt_rxeacc
, cl
), "Collision" },
434 { offsetof(elbt_rxeacc
, badsrc
), "Bad Src Address" },
435 { offsetof(elbt_rxeacc
, badtyp
), "Bad Frame Type" },
436 { offsetof(elbt_rxeacc
, badlen
), "Bad Frame Length" },
437 { offsetof(elbt_rxeacc
, badbit
), "Data Compare Errors" },
439 static int rxeacc_ndesc
= sizeof (rxeacc_descs
) / sizeof (rxeacc_descs
[0]);
443 uint def
, hb
, lc
, rl
, rc
, un
, csl
;
447 static elbt_prdesc txeacc_descs
[] = {
448 { offsetof(elbt_txeacc
, def
), "Defer Indication" },
449 { offsetof(elbt_txeacc
, hb
), "Heartbeat" },
450 { offsetof(elbt_txeacc
, lc
), "Late Collision" },
451 { offsetof(elbt_txeacc
, rl
), "Retransmission Limit" },
452 { offsetof(elbt_txeacc
, rc
), "Retry Count" },
453 { offsetof(elbt_txeacc
, un
), "Underrun" },
454 { offsetof(elbt_txeacc
, csl
), "Carrier Sense Lost" },
456 static int txeacc_ndesc
= sizeof (txeacc_descs
) / sizeof (txeacc_descs
[0]);
460 uchar rxbufs
[ELBT_NRXBD
][ELBT_BUFSZ
];
461 uchar txbufs
[ELBT_NTXBD
][ELBT_BUFSZ
];
462 cbd_t rxbd
[ELBT_NRXBD
];
463 cbd_t txbd
[ELBT_NTXBD
];
464 enum { Idle
, Running
, Closing
, Closed
} state
;
465 int proff
, page
, sblock
;
466 uint clstime
, nsent
, ntxerr
, nrcvd
, nrxerr
;
467 ushort rxerrs
[ELBT_MAXRXERR
], txerrs
[ELBT_MAXTXERR
];
470 } __attribute__ ((aligned(8)))
473 static uchar patbytes
[ELBT_NTXBD
] = {
474 0xff, 0xaa, 0x55, 0x00
476 static uint patwords
[ELBT_NTXBD
] = {
477 0xffffffff, 0xaaaaaaaa, 0x55555555, 0x00000000
481 static elbt_chan elbt_chans
[3] __attribute__ ((aligned(8)));
483 #error "elbt_chans must be 64-bit aligned"
486 #define CPM_CR_GRACEFUL_STOP_TX ((ushort)0x0005)
488 static elbt_prdesc epram_descs
[] = {
489 { offsetof(fcc_enet_t
, fen_crcec
), "CRC Errors" },
490 { offsetof(fcc_enet_t
, fen_alec
), "Alignment Errors" },
491 { offsetof(fcc_enet_t
, fen_disfc
), "Discarded Frames" },
492 { offsetof(fcc_enet_t
, fen_octc
), "Octets" },
493 { offsetof(fcc_enet_t
, fen_colc
), "Collisions" },
494 { offsetof(fcc_enet_t
, fen_broc
), "Broadcast Frames" },
495 { offsetof(fcc_enet_t
, fen_mulc
), "Multicast Frames" },
496 { offsetof(fcc_enet_t
, fen_uspc
), "Undersize Frames" },
497 { offsetof(fcc_enet_t
, fen_frgc
), "Fragments" },
498 { offsetof(fcc_enet_t
, fen_ospc
), "Oversize Frames" },
499 { offsetof(fcc_enet_t
, fen_jbrc
), "Jabbers" },
500 { offsetof(fcc_enet_t
, fen_p64c
), "64 Octet Frames" },
501 { offsetof(fcc_enet_t
, fen_p65c
), "65-127 Octet Frames" },
502 { offsetof(fcc_enet_t
, fen_p128c
), "128-255 Octet Frames" },
503 { offsetof(fcc_enet_t
, fen_p256c
), "256-511 Octet Frames" },
504 { offsetof(fcc_enet_t
, fen_p512c
), "512-1023 Octet Frames" },
505 { offsetof(fcc_enet_t
, fen_p1024c
), "1024-1518 Octet Frames"},
507 static int epram_ndesc
= sizeof (epram_descs
) / sizeof (epram_descs
[0]);
510 * given an elbt_prdesc array and an array of base addresses, print
511 * each prdesc down the screen with the values fetched from each
512 * base address across the screen
515 print_desc (elbt_prdesc descs
[], int ndesc
, uchar
*bases
[], int nbase
)
517 elbt_prdesc
*dp
= descs
, *edp
= dp
+ ndesc
;
522 for (i
= 0; i
< nbase
; i
++)
523 printf (" Channel %d", i
);
529 printf ("%-32s", dp
->lab
);
531 for (i
= 0; i
< nbase
; i
++) {
532 uint val
= *(uint
*)(bases
[i
] + dp
->off
);
534 printf (" %10u", val
);
544 * return number of bits that are set in a value; value contains
545 * nbits (right-justified) bits.
547 static uint __inline__
548 nbs (uint value
, uint nbits
)
552 uint pos
= sizeof (uint
) * 8;
554 __asm__
__volatile__ ("\
556 1: rlwnm. %2,%1,%4,31,31\n\
562 : "r"(value
), "r"(nbits
), "r"(cnt
), "r"(pos
)
578 badbits (uchar
*bp
, int n
, ulong pat
)
583 while (n
> 0 && ((ulong
)bp
& (sizeof (ulong
) - 1)) != 0) {
586 diff
= *bp
++ ^ (uchar
)pat
;
589 cnt
+= nbs ((ulong
)diff
, 8);
595 nl
= n
/ sizeof (ulong
);
596 n
-= nl
* sizeof (ulong
);
604 cnt
+= nbs (diff
, 32);
614 diff
= *bp
++ ^ (uchar
)pat
;
617 cnt
+= nbs ((ulong
)diff
, 8);
625 static inline unsigned short
626 swap16 (unsigned short x
)
628 return (((x
& 0xff) << 8) | ((x
& 0xff00) >> 8));
632 eth_loopback_test (void)
634 DECLARE_GLOBAL_DATA_PTR
;
636 volatile immap_t
*immr
= (immap_t
*)CFG_IMMR
;
637 volatile cpm8260_t
*cp
= &(immr
->im_cpm
);
639 ulong runtime
, nmsec
;
642 puts ("FCC Ethernet External loopback test\n");
644 memcpy (NetOurEther
, gd
->bd
->bi_enetaddr
, 6);
647 * global initialisations for all FCC channels
650 /* 28.9 - (1-2): ioports have been set up already */
652 #if defined(CONFIG_HYMOD)
654 * Attention: this is board-specific
659 # define FCC_START_LOOP 0
660 # define FCC_END_LOOP 2
663 * Attention: this is board-specific
664 * - FCC1 Rx-CLK is CLK10
665 * - FCC1 Tx-CLK is CLK11
666 * - FCC2 Rx-CLK is CLK13
667 * - FCC2 Tx-CLK is CLK14
668 * - FCC3 Rx-CLK is CLK15
669 * - FCC3 Tx-CLK is CLK16
672 /* 28.9 - (3): connect FCC's tx and rx clocks */
673 immr
->im_cpmux
.cmx_uar
= 0;
674 immr
->im_cpmux
.cmx_fcr
= CMXFCR_RF1CS_CLK10
|CMXFCR_TF1CS_CLK11
|\
675 CMXFCR_RF2CS_CLK13
|CMXFCR_TF2CS_CLK14
|\
676 CMXFCR_RF3CS_CLK15
|CMXFCR_TF3CS_CLK16
;
677 #elif defined(CONFIG_SBC8260) || defined(CONFIG_SACSng)
679 * Attention: this is board-specific
682 # define FCC_START_LOOP 1
683 # define FCC_END_LOOP 1
686 * Attention: this is board-specific
687 * - FCC2 Rx-CLK is CLK13
688 * - FCC2 Tx-CLK is CLK14
691 /* 28.9 - (3): connect FCC's tx and rx clocks */
692 immr
->im_cpmux
.cmx_uar
= 0;
693 immr
->im_cpmux
.cmx_fcr
= CMXFCR_RF2CS_CLK13
|CMXFCR_TF2CS_CLK14
;
695 #error "eth_loopback_test not supported on your board"
698 puts ("Initialise FCC channels:");
700 for (c
= FCC_START_LOOP
; c
<= FCC_END_LOOP
; c
++) {
701 elbt_chan
*ecp
= &elbt_chans
[c
];
702 volatile fcc_t
*fcp
= &immr
->im_fcc
[c
];
703 volatile fcc_enet_t
*fpp
;
708 * initialise channel data
713 memset ((void *)ecp
, 0, sizeof (*ecp
));
720 ecp
->proff
= PROFF_FCC1
;
721 ecp
->page
= CPM_CR_FCC1_PAGE
;
722 ecp
->sblock
= CPM_CR_FCC1_SBLOCK
;
726 ecp
->proff
= PROFF_FCC2
;
727 ecp
->page
= CPM_CR_FCC2_PAGE
;
728 ecp
->sblock
= CPM_CR_FCC2_SBLOCK
;
732 ecp
->proff
= PROFF_FCC3
;
733 ecp
->page
= CPM_CR_FCC3_PAGE
;
734 ecp
->sblock
= CPM_CR_FCC3_SBLOCK
;
739 * set up tx buffers and bds
742 for (i
= 0; i
< ELBT_NTXBD
; i
++) {
743 cbd_t
*bdp
= &ecp
->txbd
[i
];
744 uchar
*bp
= &ecp
->txbufs
[i
][0];
746 bdp
->cbd_bufaddr
= (uint
)bp
;
748 bdp
->cbd_datlen
= ELBT_BUFSZ
- ELBT_CRCSZ
;
749 bdp
->cbd_sc
= BD_ENET_TX_READY
| BD_ENET_TX_PAD
| \
750 BD_ENET_TX_LAST
| BD_ENET_TX_TC
;
752 memset ((void *)bp
, patbytes
[i
], ELBT_BUFSZ
);
753 NetSetEther (bp
, NetBcastAddr
, 0x8000);
755 ecp
->txbd
[ELBT_NTXBD
- 1].cbd_sc
|= BD_ENET_TX_WRAP
;
758 * set up rx buffers and bds
761 for (i
= 0; i
< ELBT_NRXBD
; i
++) {
762 cbd_t
*bdp
= &ecp
->rxbd
[i
];
763 uchar
*bp
= &ecp
->rxbufs
[i
][0];
765 bdp
->cbd_bufaddr
= (uint
)bp
;
767 bdp
->cbd_sc
= BD_ENET_RX_EMPTY
;
769 memset ((void *)bp
, 0, ELBT_BUFSZ
);
771 ecp
->rxbd
[ELBT_NRXBD
- 1].cbd_sc
|= BD_ENET_RX_WRAP
;
774 * set up the FCC channel hardware
777 /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
778 fcp
->fcc_gfmr
= FCC_GFMR_MODE_ENET
| FCC_GFMR_TCRC_32
;
780 /* 28.9 - (5): FPSMR: fd, enet CRC, Promis, RMON, Rx SHort */
781 fcp
->fcc_fpsmr
= FCC_PSMR_FDE
| FCC_PSMR_LPB
| \
782 FCC_PSMR_ENCRC
| FCC_PSMR_PRO
| \
783 FCC_PSMR_MON
| FCC_PSMR_RSH
;
785 /* 28.9 - (6): FDSR: Ethernet Syn */
786 fcp
->fcc_fdsr
= 0xD555;
788 /* 29.9 - (7): initialise parameter ram */
789 fpp
= (fcc_enet_t
*)&(immr
->im_dprambase
[ecp
->proff
]);
791 /* clear whole struct to make sure all resv fields are zero */
792 memset ((void *)fpp
, 0, sizeof (fcc_enet_t
));
795 * common Parameter RAM area
797 * Allocate space in the reserved FCC area of DPRAM for the
798 * internal buffers. No one uses this space (yet), so we
799 * can do this. Later, we will add resource management for
802 addr
= CPM_FCC_SPECIAL_BASE
+ (c
* 64);
803 fpp
->fen_genfcc
.fcc_riptr
= addr
;
804 fpp
->fen_genfcc
.fcc_tiptr
= addr
+ 32;
807 * Set maximum bytes per receive buffer.
808 * It must be a multiple of 32.
809 * buffers are in 60x bus memory.
811 fpp
->fen_genfcc
.fcc_mrblr
= PKT_MAXBLR_SIZE
;
812 fpp
->fen_genfcc
.fcc_rstate
= (CPMFCR_GBL
| CPMFCR_EB
) << 24;
813 fpp
->fen_genfcc
.fcc_rbase
= (unsigned int)(&ecp
->rxbd
[0]);
814 fpp
->fen_genfcc
.fcc_tstate
= (CPMFCR_GBL
| CPMFCR_EB
) << 24;
815 fpp
->fen_genfcc
.fcc_tbase
= (unsigned int)(&ecp
->txbd
[0]);
817 /* protocol-specific area */
818 fpp
->fen_cmask
= 0xdebb20e3; /* CRC mask */
819 fpp
->fen_cpres
= 0xffffffff; /* CRC preset */
820 fpp
->fen_retlim
= 15; /* Retry limit threshold */
821 fpp
->fen_mflr
= PKT_MAXBUF_SIZE
;/* max frame length register */
824 * Set Ethernet station address.
826 * This is supplied in the board information structure, so we
827 * copy that into the controller.
828 * So, far we have only been given one Ethernet address. We use
829 * the same address for all channels
831 #define ea gd->bd->bi_enetaddr
832 fpp
->fen_paddrh
= (ea
[5] << 8) + ea
[4];
833 fpp
->fen_paddrm
= (ea
[3] << 8) + ea
[2];
834 fpp
->fen_paddrl
= (ea
[1] << 8) + ea
[0];
837 fpp
->fen_minflr
= PKT_MINBUF_SIZE
; /* min frame len register */
839 * pad pointer. use tiptr since we don't need
840 * a specific padding char
842 fpp
->fen_padptr
= fpp
->fen_genfcc
.fcc_tiptr
;
843 fpp
->fen_maxd1
= PKT_MAXDMA_SIZE
; /* max DMA1 length */
844 fpp
->fen_maxd2
= PKT_MAXDMA_SIZE
; /* max DMA2 length */
848 /* 28.9 - (8): clear out events in FCCE */
849 fcp
->fcc_fcce
= ~0x0;
851 /* 28.9 - (9): FCCM: mask all events */
854 /* 28.9 - (10-12): we don't use ethernet interrupts */
858 * Let's re-initialize the channel now. We have to do it later
859 * than the manual describes because we have just now finished
860 * the BD initialization.
862 cp
->cp_cpcr
= mk_cr_cmd (ecp
->page
, ecp
->sblock
, \
863 0x0c, CPM_CR_INIT_TRX
) | CPM_CR_FLG
;
865 __asm__
__volatile__ ("eieio");
866 } while (cp
->cp_cpcr
& CPM_CR_FLG
);
869 puts (" done\nStarting test... (Ctrl-C to Finish)\n");
872 * Note: don't want serial output from here until the end of the
873 * test - the delays would probably stuff things up.
877 runtime
= get_timer (0);
882 for (c
= FCC_START_LOOP
; c
<= FCC_END_LOOP
; c
++) {
883 volatile fcc_t
*fcp
= &immr
->im_fcc
[c
];
884 elbt_chan
*ecp
= &elbt_chans
[c
];
887 switch (ecp
->state
) {
891 * set the channel Running ...
894 /* 28.9 - (14): enable tx/rx in gfmr */
895 fcp
->fcc_gfmr
|= FCC_GFMR_ENT
| FCC_GFMR_ENR
;
897 ecp
->state
= Running
;
902 * (while Running only) check for
903 * termination of the test
910 * initiate a "graceful stop transmit"
913 cp
->cp_cpcr
= mk_cr_cmd (ecp
->page
, \
915 CPM_CR_GRACEFUL_STOP_TX
) | \
918 __asm__
__volatile__ ("eieio");
919 } while (cp
->cp_cpcr
& CPM_CR_FLG
);
921 ecp
->clstime
= get_timer (0);
922 ecp
->state
= Closing
;
924 /* fall through ... */
928 * (while Running or Closing) poll the channel:
929 * - check for any non-READY tx buffers and
931 * - check for any non-EMPTY rx buffers and
932 * check that they were received correctly,
933 * adjust counters etc, then make empty
936 for (i
= 0; i
< ELBT_NTXBD
; i
++) {
937 cbd_t
*bdp
= &ecp
->txbd
[i
];
938 ushort sc
= bdp
->cbd_sc
;
940 if ((sc
& BD_ENET_TX_READY
) != 0)
944 * this frame has finished
949 if (sc
& BD_ENET_TX_STATS
) {
957 if (n
< ELBT_MAXTXERR
)
960 if (sc
& BD_ENET_TX_DEF
)
962 if (sc
& BD_ENET_TX_HB
)
964 if (sc
& BD_ENET_TX_LC
)
966 if (sc
& BD_ENET_TX_RL
)
968 if (sc
& BD_ENET_TX_RCMASK
)
970 if (sc
& BD_ENET_TX_UN
)
972 if (sc
& BD_ENET_TX_CSL
)
979 if (ecp
->state
== Closing
)
980 ecp
->clstime
= get_timer (0);
982 /* make it ready again */
983 bdp
->cbd_sc
|= BD_ENET_TX_READY
;
986 for (i
= 0; i
< ELBT_NRXBD
; i
++) {
987 cbd_t
*bdp
= &ecp
->rxbd
[i
];
988 ushort sc
= bdp
->cbd_sc
, mask
;
990 if ((sc
& BD_ENET_RX_EMPTY
) != 0)
993 /* we have a new frame in this buffer */
996 mask
= BD_ENET_RX_LAST
|BD_ENET_RX_FIRST
;
997 if ((sc
& mask
) != mask
) {
998 /* somethings wrong here ... */
999 if (!(sc
& BD_ENET_RX_LAST
))
1001 if (!(sc
& BD_ENET_RX_FIRST
))
1005 if (sc
& BD_ENET_RX_STATS
) {
1009 * we had some sort of error
1013 if (n
< ELBT_MAXRXERR
)
1014 ecp
->rxerrs
[n
] = sc
;
1016 if (sc
& BD_ENET_RX_MISS
)
1018 if (sc
& BD_ENET_RX_BC
)
1020 if (sc
& BD_ENET_RX_MC
)
1022 if (sc
& BD_ENET_RX_LG
)
1024 if (sc
& BD_ENET_RX_NO
)
1026 if (sc
& BD_ENET_RX_SH
)
1028 if (sc
& BD_ENET_RX_CR
)
1030 if (sc
& BD_ENET_RX_OV
)
1032 if (sc
& BD_ENET_RX_CL
)
1039 ushort datlen
= bdp
->cbd_datlen
;
1042 int ours
, tb
, n
, nbytes
;
1044 ehp
= (Ethernet_t
*) \
1047 ours
= memcmp (ehp
->et_src
, \
1050 prot
= swap16 (ehp
->et_protlen
);
1054 nbytes
= ELBT_BUFSZ
- \
1055 offsetof (Ethernet_t
, \
1059 /* check the frame is correct */
1060 if (datlen
!= ELBT_BUFSZ
)
1061 ecp
->rxeacc
.badlen
++;
1063 ecp
->rxeacc
.badsrc
++;
1064 else if (!tb
|| n
>= ELBT_NTXBD
)
1065 ecp
->rxeacc
.badtyp
++;
1076 ecp
->rxeacc
.badbit
+= \
1081 if (ecp
->state
== Closing
)
1082 ecp
->clstime
= get_timer (0);
1084 /* make it empty again */
1085 bdp
->cbd_sc
|= BD_ENET_RX_EMPTY
;
1088 if (ecp
->state
!= Closing
)
1092 * (while Closing) check to see if
1093 * waited long enough
1096 if (get_timer (ecp
->clstime
) >= ELBT_CLSWAIT
) {
1097 /* write GFMR: disable tx/rx */
1099 ~(FCC_GFMR_ENT
| FCC_GFMR_ENR
);
1100 ecp
->state
= Closed
;
1111 } while (nclosed
< (FCC_END_LOOP
- FCC_START_LOOP
+ 1));
1113 runtime
= get_timer (runtime
);
1114 if (runtime
<= ELBT_CLSWAIT
) {
1115 printf ("Whoops! somehow elapsed time (%ld) is wrong (<= %d)\n",
1116 runtime
, ELBT_CLSWAIT
);
1119 nmsec
= runtime
- ELBT_CLSWAIT
;
1121 printf ("Test Finished in %ldms (plus %dms close wait period)!\n\n",
1122 nmsec
, ELBT_CLSWAIT
);
1128 for (c
= FCC_START_LOOP
; c
<= FCC_END_LOOP
; c
++) {
1129 elbt_chan
*ecp
= &elbt_chans
[c
];
1130 uint rxpps
, txpps
, nerr
;
1132 rxpps
= (ecp
->nrcvd
* 1000) / nmsec
;
1133 txpps
= (ecp
->nsent
* 1000) / nmsec
;
1135 printf ("Channel %d: %d rcvd (%d pps, %d rxerrs), "
1136 "%d sent (%d pps, %d txerrs)\n\n", c
,
1137 ecp
->nrcvd
, rxpps
, ecp
->nrxerr
,
1138 ecp
->nsent
, txpps
, ecp
->ntxerr
);
1140 if ((nerr
= ecp
->nrxerr
) > 0) {
1143 printf ("\tFirst %d rx errs:", nerr
);
1144 for (i
= 0; i
< nerr
; i
++)
1145 printf (" %04x", ecp
->rxerrs
[i
]);
1149 if ((nerr
= ecp
->ntxerr
) > 0) {
1152 printf ("\tFirst %d tx errs:", nerr
);
1153 for (i
= 0; i
< nerr
; i
++)
1154 printf (" %04x", ecp
->txerrs
[i
]);
1159 puts ("Receive Error Counts:\n");
1160 for (c
= FCC_START_LOOP
; c
<= FCC_END_LOOP
; c
++)
1161 bases
[c
] = (uchar
*)&elbt_chans
[c
].rxeacc
;
1162 print_desc (rxeacc_descs
, rxeacc_ndesc
, bases
, 3);
1164 puts ("\nTransmit Error Counts:\n");
1165 for (c
= FCC_START_LOOP
; c
<= FCC_END_LOOP
; c
++)
1166 bases
[c
] = (uchar
*)&elbt_chans
[c
].txeacc
;
1167 print_desc (txeacc_descs
, txeacc_ndesc
, bases
, 3);
1169 puts ("\nRMON(-like) Counters:\n");
1170 for (c
= FCC_START_LOOP
; c
<= FCC_END_LOOP
; c
++)
1171 bases
[c
] = (uchar
*)&immr
->im_dprambase
[elbt_chans
[c
].proff
];
1172 print_desc (epram_descs
, epram_ndesc
, bases
, 3);
1175 #endif /* CONFIG_ETHER_LOOPBACK_TEST */
1177 #endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET && CONFIG_NET_MULTI */