GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / arch / mips / cpu / sb1250 / src / dev_sb1250_ethernet.c
blobf9c40320f060d3c11654ccbbdf56f35f7b1d18d0
1 /* *********************************************************************
2 * SB1250_ETHERNET
4 * CFE Ethernet Driver File: DEV_SB1250_ETHERNET.C
5 *
6 * Author: Mitch Lichtenberg (mpl@broadcom.com)
7 *
8 * This is the console monitor Ethernet driver for the SB1250
9 *
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
47 #include "sbmips.h"
49 #include "lib_types.h"
50 #include "lib_malloc.h"
51 #include "lib_string.h"
52 #include "lib_printf.h"
54 #include "cfe_iocb.h"
55 #include "cfe_device.h"
56 #include "cfe_ioctl.h"
57 #include "cfe_console.h"
58 #include "cfe_timer.h"
59 #include "cfe_error.h"
61 #include "env_subr.h"
63 #include "sb1250_defs.h"
64 #include "sb1250_regs.h"
65 #include "sb1250_mac.h"
66 #include "sb1250_dma.h"
67 #include "mii.h"
69 /* *********************************************************************
70 * Simple types
71 ********************************************************************* */
73 #ifdef __long64
74 typedef volatile uint64_t sbeth_port_t;
75 typedef uint64_t sbeth_physaddr_t;
76 #define SBETH_PORT(x) PHYS_TO_K1(x)
77 #else
78 typedef volatile uint32_t sbeth_port_t;
79 typedef uint32_t sbeth_physaddr_t;
80 #define SBETH_PORT(x) PHYS_TO_K1(x)
81 #endif
83 #define SBETH_READCSR(t) (*((volatile uint64_t *) (t)))
84 #define SBETH_WRITECSR(t,v) *((volatile uint64_t *) (t)) = (v)
86 #define SBETH_MAX_TXDESCR 8
87 #define SBETH_MAX_RXDESCR 8
88 #define SBETH_MIN_RCV_RING 4
89 #define SBETH_PKTPOOL_SIZE 16
90 #define SBETH_DMA_CHANNELS 1
91 #define SBETH_PKT_SIZE 1518
92 #define SBETH_PKTBUF_SIZE 2048
94 #define SBETH_ADDR_LEN 6
97 typedef enum { sbeth_speed_10, sbeth_speed_100,
98 sbeth_speed_1000 } sbeth_speed_t;
100 typedef enum { sbeth_duplex_half,
101 sbeth_duplex_full } sbeth_duplex_t;
103 typedef enum { sbeth_fc_disabled, sbeth_fc_frame,
104 sbeth_fc_collision, sbeth_fc_carrier } sbeth_fc_t;
106 typedef enum { sbeth_state_uninit, sbeth_state_off, sbeth_state_on,
107 sbeth_state_broken } sbeth_state_t;
109 typedef uint64_t sbeth_enetaddr_t;
111 typedef struct sbeth_s sbeth_t; /* forward reference */
113 static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed);
114 static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc);
116 #define SBETH_MIIPOLL_TIMER (4*CFE_HZ)
118 /* *********************************************************************
119 * Descriptor structure
120 ********************************************************************* */
122 typedef struct sbdmadscr_s {
123 uint64_t dscr_a;
124 uint64_t dscr_b;
125 } sbdmadscr_t;
127 /* *********************************************************************
128 * DMA structure
129 ********************************************************************* */
131 typedef struct sbethdma_s {
134 * This stuff is used to identify the channel and the registers
135 * associated with it.
138 sbeth_t *sbdma_eth; /* back pointer to associated MAC */
139 int sbdma_channel; /* channel number */
140 int sbdma_txdir; /* direction (1=transmit) */
141 int sbdma_maxdescr; /* total # of descriptors in ring */
142 sbeth_port_t sbdma_config0; /* DMA config register 0 */
143 sbeth_port_t sbdma_config1; /* DMA config register 1 */
144 sbeth_port_t sbdma_dscrbase; /* Descriptor base address */
145 sbeth_port_t sbdma_dscrcnt; /* Descriptor count register */
146 sbeth_port_t sbdma_curdscr; /* current descriptor address */
149 * This stuff is for maintenance of the ring
152 sbdmadscr_t *sbdma_dscrtable; /* base of descriptor table */
153 sbdmadscr_t *sbdma_dscrtable_end; /* end of descriptor table */
155 void **sbdma_ctxtable; /* context table, one per descr */
157 int sbdma_onring; /* count of packets on ring */
159 sbeth_physaddr_t sbdma_dscrtable_phys; /* and also the phys addr */
160 sbdmadscr_t *sbdma_addptr; /* next dscr for sw to add */
161 sbdmadscr_t *sbdma_remptr; /* next dscr for sw to remove */
163 void (*sbdma_upcall)(void *ifctx,int chan,void *ctx,
164 uint64_t status,unsigned int length);
165 } sbethdma_t;
167 typedef struct sbeth_pkt_s {
168 struct sbeth_pkt_s *next;
169 void *devctx;
170 unsigned char *buffer;
171 int length;
172 /* packet data goes here */
173 } sbeth_pkt_t;
175 /* *********************************************************************
176 * Ethernet controller structure
177 ********************************************************************* */
179 struct sbeth_s {
180 cfe_devctx_t *sbe_devctx;
181 sbeth_port_t sbe_baseaddr; /* base address */
183 sbeth_state_t sbe_state; /* current state */
185 sbeth_port_t sbe_macenable; /* MAC Enable Register */
186 sbeth_port_t sbe_maccfg; /* MAC Configuration Register */
187 sbeth_port_t sbe_fifocfg; /* FIFO configuration register */
188 sbeth_port_t sbe_framecfg; /* Frame configuration register */
189 sbeth_port_t sbe_rxfilter; /* receive filter register */
190 sbeth_port_t sbe_isr; /* Interrupt status register */
191 sbeth_port_t sbe_imr; /* Interrupt mask register */
192 sbeth_port_t sbe_mdio; /* PHY control stuff */
194 sbeth_speed_t sbe_speed; /* current speed */
195 sbeth_duplex_t sbe_duplex; /* current duplex */
196 sbeth_fc_t sbe_fc; /* current flow control setting */
197 int sbe_rxflags; /* received packet flags */
198 int sbe_autospeed; /* true for automatic speed setting */
199 int sbe_curspeed; /* value for GET SPEED ioctl */
200 int sbe_loopback; /* IOCTL LOOPBACK stuff */
201 int sbe_linkstat; /* Current link status */
203 sbethdma_t sbe_txdma[SBETH_DMA_CHANNELS]; /* one for each channel */
204 sbethdma_t sbe_rxdma[SBETH_DMA_CHANNELS];
205 void *sbe_ifctx;
207 int sbe_minrxring; /* min packets to keep on RX ring */
209 sbeth_pkt_t *sbe_rxqueue; /* received packet queue */
211 sbeth_pkt_t *sbe_freelist; /* free packet list */
213 unsigned char *sbe_pktpool;
215 unsigned char sbe_hwaddr[SBETH_ADDR_LEN];
217 int sbe_phyaddr;
218 int sbe_zerormon;
220 uint32_t sbe_phy_oldbmsr;
221 uint32_t sbe_phy_oldbmcr;
222 uint32_t sbe_phy_oldanlpar;
223 uint32_t sbe_phy_oldk1stsr;
225 int64_t sbe_linkstat_timer;
226 int fifo_mode; /* true if in packet fifo mode */
231 /* *********************************************************************
232 * Prototypes
233 ********************************************************************* */
235 static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg);
236 static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg);
237 static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx);
239 static void sbeth_start(sbeth_t *s);
240 static void sbeth_stop(sbeth_t *s);
242 static void sbeth_initfreelist(sbeth_t *s);
243 static sbeth_pkt_t *sbeth_alloc_pkt(sbeth_t *s);
244 static void sbeth_free_pkt(sbeth_t *s,sbeth_pkt_t *pkt);
245 static void sbeth_tx_callback(void *ifctx,int chan,void *ctx,
246 uint64_t status,unsigned int pktsize);
247 static void sbeth_rx_callback(void *ifctx,int chan,void *ctx,
248 uint64_t status,unsigned int pktsize);
249 static void sbeth_fillrxring(sbeth_t *s,int chan);
250 static void sb1250_ether_probe(cfe_driver_t *drv,
251 unsigned long probe_a, unsigned long probe_b,
252 void *probe_ptr);
254 static void sbeth_setaddr(sbeth_t *s,uint8_t *addr);
256 /* *********************************************************************
257 * Macros
258 ********************************************************************* */
260 #define sbdma_nextbuf(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \
261 (d)->sbdma_dscrtable : (d)->f+1)
263 #define SBDMA_CACHESIZE 32 /* wants to be somewhere else */
264 #define SBDMA_NUMCACHEBLKS(x) ((x+SBDMA_CACHESIZE-1)/SBDMA_CACHESIZE)
266 #define STRAP_PHY1 0x0800
267 #define STRAP_NCMODE 0x0400
268 #define STRAP_MANMSCFG 0x0200
269 #define STRAP_ANENABLE 0x0100
270 #define STRAP_MSVAL 0x0080
271 #define STRAP_1KHDXADV 0x0010
272 #define STRAP_1KFDXADV 0x0008
273 #define STRAP_100ADV 0x0004
274 #define STRAP_SPEEDSEL 0x0000
275 #define STRAP_SPEED100 0x0001
277 #define PHYSUP_SPEED1000 0x10
278 #define PHYSUP_SPEED100 0x08
279 #define PHYSUP_SPEED10 0x00
280 #define PHYSUP_LINKUP 0x04
281 #define PHYSUP_FDX 0x02
283 #define M_MAC_MDIO_DIR_OUTPUT 0 /* for clarity */
286 /* ********************************************************************** */
290 /* *********************************************************************
291 * SBETH_MII_SYNC(s)
293 * Synchronize with the MII - send a pattern of bits to the MII
294 * that will guarantee that it is ready to accept a command.
296 * Input parameters:
297 * s - sbmac structure
299 * Return value:
300 * nothing
301 ********************************************************************* */
303 static void sbeth_mii_sync(sbeth_t *s)
305 int cnt;
306 uint64_t bits;
307 int mac_mdio_genc;
309 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
311 bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
313 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);
315 for (cnt = 0; cnt < 32; cnt++) {
316 SBETH_WRITECSR(s->sbe_mdio,bits | M_MAC_MDC | mac_mdio_genc);
317 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);
322 /* *********************************************************************
323 * SBETH_MII_SENDDATA(s,data,bitcnt)
325 * Send some bits to the MII. The bits to be sent are right-
326 * justified in the 'data' parameter.
328 * Input parameters:
329 * s - sbmac structure
330 * data - data to send
331 * bitcnt - number of bits to send
332 ********************************************************************* */
334 static void sbeth_mii_senddata(sbeth_t *s,unsigned int data, int bitcnt)
336 int i;
337 uint64_t bits;
338 unsigned int curmask;
339 int mac_mdio_genc;
341 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
343 bits = M_MAC_MDIO_DIR_OUTPUT;
344 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);
346 curmask = 1 << (bitcnt - 1);
348 for (i = 0; i < bitcnt; i++) {
349 if (data & curmask) bits |= M_MAC_MDIO_OUT;
350 else bits &= ~M_MAC_MDIO_OUT;
351 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);
352 SBETH_WRITECSR(s->sbe_mdio,bits | M_MAC_MDC | mac_mdio_genc);
353 SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);
354 curmask >>= 1;
360 /* *********************************************************************
361 * SBETH_MII_READ(s,phyaddr,regidx)
363 * Read a PHY register.
365 * Input parameters:
366 * s - sbmac structure
367 * phyaddr - PHY's address
368 * regidx = index of register to read
370 * Return value:
371 * value read, or 0 if an error occured.
372 ********************************************************************* */
374 static unsigned int sbeth_mii_read(sbeth_t *s,int phyaddr,int regidx)
376 int idx;
377 int error;
378 int regval;
379 int mac_mdio_genc;
382 * Synchronize ourselves so that the PHY knows the next
383 * thing coming down is a command
386 sbeth_mii_sync(s);
389 * Send the data to the PHY. The sequence is
390 * a "start" command (2 bits)
391 * a "read" command (2 bits)
392 * the PHY addr (5 bits)
393 * the register index (5 bits)
396 sbeth_mii_senddata(s,MII_COMMAND_START, 2);
397 sbeth_mii_senddata(s,MII_COMMAND_READ, 2);
398 sbeth_mii_senddata(s,phyaddr, 5);
399 sbeth_mii_senddata(s,regidx, 5);
401 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
404 * Switch the port around without a clock transition.
406 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
409 * Send out a clock pulse to signal we want the status
412 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
413 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
416 * If an error occured, the PHY will signal '1' back
418 error = SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN;
421 * Issue an 'idle' clock pulse, but keep the direction
422 * the same.
424 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
425 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
427 regval = 0;
429 for (idx = 0; idx < 16; idx++) {
430 regval <<= 1;
432 if (error == 0) {
433 if (SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN) regval |= 1;
436 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | M_MAC_MDC | mac_mdio_genc);
437 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
440 /* Switch back to output */
441 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
443 if (error == 0) return regval;
444 return 0;
448 /* *********************************************************************
449 * SBETH_MII_WRITE(s,phyaddr,regidx,regval)
451 * Write a value to a PHY register.
453 * Input parameters:
454 * s - sbmac structure
455 * phyaddr - PHY to use
456 * regidx - register within the PHY
457 * regval - data to write to register
459 * Return value:
460 * nothing
461 ********************************************************************* */
463 void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx,
464 unsigned int regval);
465 void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx,
466 unsigned int regval)
468 int mac_mdio_genc;
470 sbeth_mii_sync(s);
472 sbeth_mii_senddata(s,MII_COMMAND_START,2);
473 sbeth_mii_senddata(s,MII_COMMAND_WRITE,2);
474 sbeth_mii_senddata(s,phyaddr, 5);
475 sbeth_mii_senddata(s,regidx, 5);
476 sbeth_mii_senddata(s,MII_COMMAND_ACK,2);
477 sbeth_mii_senddata(s,regval,16);
479 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
481 SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
485 /* *********************************************************************
486 * SBDMA_INITCHAN(s,d)
488 * Initialize the DMA channel, programming the CSRs to the
489 * values calculated in the SBDMA_INITCTX routine.
491 * Input parameters:
492 * s - sbeth structure
493 * d - sbdma structure
495 * Return value:
496 * nothing
497 ********************************************************************* */
498 static void sbdma_initchan(sbeth_t *s,
499 sbethdma_t *d)
502 * Turn on the DMA channel
505 SBETH_WRITECSR(d->sbdma_config1,0);
507 SBETH_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
509 SBETH_WRITECSR(d->sbdma_config0,
510 V_DMA_RINGSZ(d->sbdma_maxdescr) |
515 /* *********************************************************************
516 * SBDMA_INITCTX(s,d,chan,txrx,maxdescr,callback)
518 * Initialize a DMA channel context. Since there are potentially
519 * eight DMA channels per MAC, it's nice to do this in a standard
520 * way.
522 * Input parameters:
523 * s - sbeth_t structure (pointer to a MAC)
524 * d - sbethdma_t structure (DMA channel context)
525 * chan - channel number (0..1 right now)
526 * txrx - Identifies DMA_TX or DMA_RX for channel direction
527 * maxdescr - number of descriptors to allocate for the ring
529 * Return value:
530 * nothing
531 ********************************************************************* */
533 static void sbdma_initctx(sbeth_t *s,
534 sbethdma_t *d,
535 int chan,
536 int txrx,
537 int maxdescr,
538 void (*callback)(void *,int,void *,uint64_t,unsigned int))
541 * Save away interesting stuff in the structure
544 d->sbdma_eth = s;
545 d->sbdma_channel = chan;
546 d->sbdma_txdir = txrx;
547 d->sbdma_maxdescr = maxdescr;
550 * initialize register pointers
553 d->sbdma_config0 = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
554 d->sbdma_config1 = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1));
555 d->sbdma_dscrbase = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE));
556 d->sbdma_dscrcnt = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT));
557 d->sbdma_curdscr = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR));
560 * initialize the ring
563 d->sbdma_dscrtable = (sbdmadscr_t *)
564 KMALLOC(maxdescr*sizeof(sbdmadscr_t),sizeof(sbdmadscr_t));
565 d->sbdma_dscrtable_end = d->sbdma_dscrtable + maxdescr;
567 d->sbdma_dscrtable_phys = K1_TO_PHYS((sbeth_physaddr_t) d->sbdma_dscrtable);
568 d->sbdma_addptr = d->sbdma_dscrtable;
569 d->sbdma_remptr = d->sbdma_dscrtable;
571 d->sbdma_ctxtable = (void **)
572 KMALLOC(maxdescr*sizeof(void *),sizeof(void *));
575 * install callback
578 d->sbdma_upcall = callback;
585 /* *********************************************************************
586 * SBDMA_RESET(d)
588 * Reset the software-maintained state for the specified
589 * DMA channel.
591 * Input parameters:
592 * d - dma channel
594 * Return value:
595 * nothing
596 ********************************************************************* */
598 static void sbdma_reset(sbethdma_t *d)
600 d->sbdma_addptr = d->sbdma_dscrtable;
601 d->sbdma_remptr = d->sbdma_dscrtable;
602 d->sbdma_onring = 0;
605 /* *********************************************************************
606 * SBDMA_PROCBUFFERS(d,procfunc)
608 * Process "completed" buffers on the specified DMA channel.
609 * This is normally called within the interrupt service routine.
610 * Note that this isn't really ideal for priority channels, since
611 * it processes all of the packets on a given channel before
612 * returning.
614 * Input parameters:
615 * d - DMA channel context
616 * procfunc - routine to call for each completed buffer. This
617 * is called with the context for the completed buffer,
618 * the status from the descriptor, and the length from
619 * the descriptor.
621 * Return value:
622 * number of packets processed.
623 ********************************************************************* */
625 static int sbdma_procbuffers(sbethdma_t *d,
626 void (*procfunc)(void *ifctx,int chan,void *ctx,
627 uint64_t status,
628 unsigned int pktlen))
630 int curidx;
631 int hwidx;
632 int count = 0;
633 sbdmadscr_t *dsc;
635 for (;;) {
637 * figure out where we are (as an index) and where
638 * the hardware is (also as an index)
640 * This could be done faster if (for example) the
641 * descriptor table was page-aligned and contiguous in
642 * both virtual and physical memory -- you could then
643 * just compare the low-order bits of the virtual address
644 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
647 curidx = d->sbdma_remptr - d->sbdma_dscrtable;
649 uint64_t tmp;
650 tmp = SBETH_READCSR(d->sbdma_curdscr);
651 if (!tmp) {
652 break;
654 hwidx = (int) (((tmp & M_DMA_CURDSCR_ADDR) -
655 d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
659 * If they're the same, that means we've processed all
660 * of the descriptors up to (but not including) the one that
661 * the hardware is working on right now.
664 if (curidx == hwidx) break;
667 * Remove packet from the on-ring count.
670 d->sbdma_onring--;
673 * Otherwise, issue the upcall.
677 dsc = &(d->sbdma_dscrtable[curidx]);
678 (*procfunc)(d->sbdma_eth->sbe_ifctx,
679 d->sbdma_channel,
680 d->sbdma_ctxtable[curidx],
681 dsc->dscr_a & M_DMA_DSCRA_STATUS,
682 (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b));
683 count++;
686 * .. and advance to the next buffer.
689 d->sbdma_remptr = sbdma_nextbuf(d,sbdma_remptr);
693 return count;
696 /* *********************************************************************
697 * SBDMA_ADDBUFFER(d,ptr,length,ctx)
699 * Add a buffer to the specified DMA channel. For transmit channels,
700 * this causes a transmission to start. For receive channels,
701 * this queues a buffer for inbound packets.
703 * Input parameters:
704 * d - DMA channel descriptor
705 * ptr - pointer to buffer (must by physically contiguous)
706 * length - length of buffer
707 * ctx - arbitrary data to be passed back when descriptor completes
708 * (for example, mbuf pointers, etc.)
710 * Return value:
711 * 0 if buffer could not be added (ring is full)
712 * 1 if buffer added successfully
713 ********************************************************************* */
715 static int sbdma_addbuffer(sbethdma_t *d,uint8_t *ptr,int length,void *ctx)
717 sbdmadscr_t *dsc;
718 sbdmadscr_t *nextdsc;
720 sbeth_t *s = d->sbdma_eth;
722 /* get pointer to our current place in the ring */
723 dsc = d->sbdma_addptr;
724 nextdsc = sbdma_nextbuf(d,sbdma_addptr);
727 * figure out if the ring is full - if the next descriptor
728 * is the same as the one that we're going to remove from
729 * the ring, the ring is full
732 if (nextdsc == d->sbdma_remptr) {
733 return 0;
737 * fill in the descriptor
740 if (d->sbdma_txdir) {
741 /* transmitting: set outbound options and length */
742 dsc->dscr_a = K1_TO_PHYS((sbeth_physaddr_t) ptr) |
743 V_DMA_DSCRA_A_SIZE(SBDMA_NUMCACHEBLKS(((uint64_t) length))) |
744 M_DMA_DSCRA_INTERRUPT |
745 M_DMA_ETHTX_SOP;
747 if (s->fifo_mode) {
748 dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_NOMODS) |
749 V_DMA_DSCRB_PKT_SIZE(length);
751 else {
752 dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
753 V_DMA_DSCRB_PKT_SIZE(length);
757 else {
758 /* receiving: no options */
759 dsc->dscr_a = K1_TO_PHYS((sbeth_physaddr_t) ptr) |
760 V_DMA_DSCRA_A_SIZE(SBDMA_NUMCACHEBLKS(((uint64_t) length))) |
761 M_DMA_DSCRA_INTERRUPT;
762 dsc->dscr_b = 0;
766 * fill in the context
769 d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = ctx;
772 * point at next packet
775 d->sbdma_addptr = nextdsc;
778 * Give the packet to the hardware
781 d->sbdma_onring++;
782 SBETH_WRITECSR(d->sbdma_dscrcnt,1);
784 return 1; /* we did it */
788 /* *********************************************************************
789 * SBETH_INITFREELIST(s)
791 * Initialize the buffer free list for this mac. The memory
792 * allocated to the free list is carved up and placed on a linked
793 * list of buffers for use by the mac.
795 * Input parameters:
796 * s - sbeth structure
798 * Return value:
799 * nothing
800 ********************************************************************* */
802 static void sbeth_initfreelist(sbeth_t *s)
804 int idx;
805 unsigned char *ptr;
806 sbeth_pkt_t *pkt;
808 s->sbe_freelist = NULL;
810 /* Must empty rxqueue, as we're about to free all the pkts on it */
811 s->sbe_rxqueue = NULL;
813 ptr = s->sbe_pktpool;
815 for (idx = 0; idx < SBETH_PKTPOOL_SIZE; idx++) {
816 pkt = (sbeth_pkt_t *) ptr;
817 sbeth_free_pkt(s,pkt);
818 ptr += SBETH_PKTBUF_SIZE;
823 /* *********************************************************************
824 * SBETH_ALLOC_PKT(s)
826 * Allocate a packet from the free list.
828 * Input parameters:
829 * s - sbeth structure
831 * Return value:
832 * pointer to packet structure, or NULL if none available
833 ********************************************************************* */
835 static sbeth_pkt_t *sbeth_alloc_pkt(sbeth_t *s)
837 uintptr_t addr;
838 sbeth_pkt_t *pkt = s->sbe_freelist;
840 if (!pkt) return NULL;
842 s->sbe_freelist = pkt->next;
843 pkt->next = NULL;
845 addr = (uintptr_t) (pkt+1);
846 if (addr & (SBDMA_CACHESIZE-1)) {
847 addr = (addr + SBDMA_CACHESIZE) & ~(SBDMA_CACHESIZE-1);
850 pkt->buffer = (unsigned char *) addr;
851 pkt->length = SBETH_PKT_SIZE;
853 return pkt;
856 /* *********************************************************************
857 * SBETH_FREE_PKT(s,pkt)
859 * Return a packet to the free list
861 * Input parameters:
862 * s - sbmac structure
863 * pkt - packet to return
865 * Return value:
866 * nothing
867 ********************************************************************* */
868 static void sbeth_free_pkt(sbeth_t *s,sbeth_pkt_t *pkt)
870 pkt->next = s->sbe_freelist;
871 s->sbe_freelist = pkt;
874 /* *********************************************************************
875 * SBETH_TX_CALLBACK(ifctx,chan,ctx,status,pktsize)
877 * Transmit callback routine. This routine is invoked when a
878 * queued transmit operation completes. In this simple driver,
879 * all we do is free the packet and try to re-fill the receive ring.
881 * Input parameters:
882 * ifctx - interface context (sbeth structure)
883 * chan - DMA Channel
884 * ctx - packet context (sbeth_pkt structure)
885 * status - Ethernet status from descriptor
886 * pktsize - length of packet (unused for transmits)
888 * Return value:
889 * nothing
890 ********************************************************************* */
892 static void sbeth_tx_callback(void *ifctx,int chan,void *ctx,
893 uint64_t status,unsigned int pktsize)
895 sbeth_t *s = ifctx;
896 sbeth_pkt_t *pkt = ctx;
898 sbeth_free_pkt(s,pkt); /* return packet to pool */
900 sbeth_fillrxring(s,chan); /* re-fill the receive ring */
903 /* *********************************************************************
904 * SBETH_RX_CALLBACK(ifctx,chan,ctx,status,pktsize)
906 * Receive callback routine. This routine is invoked when a
907 * buffer queued for receives is filled. In this simple driver,
908 * all we do is add the packet to a per-MAC queue for later
909 * processing, and try to put a new packet in the place of the one
910 * that was removed from the queue.
912 * Input parameters:
913 * ifctx - interface context (sbeth structure)
914 * chan - DMA Channel
915 * ctx - packet context (sbeth_pkt structure)
916 * status - Ethernet status from descriptor
917 * pktsize - length of packet (unused for transmits)
919 * Return value:
920 * nothing
921 ********************************************************************* */
922 static void sbeth_rx_callback(void *ifctx,int chan,void *ctx,
923 uint64_t status,unsigned int pktsize)
925 sbeth_t *s = ifctx;
926 sbeth_pkt_t *pkt = ctx;
927 sbeth_pkt_t *listptr;
929 if (!(status & M_DMA_ETHRX_BAD)) {
930 pkt->next = NULL;
931 pkt->length = pktsize;
933 if (s->sbe_rxqueue == NULL) {
934 s->sbe_rxqueue = pkt;
936 else {
937 listptr = s->sbe_rxqueue;
938 while (listptr->next) listptr = listptr->next;
939 listptr->next = pkt;
942 else {
943 sbeth_free_pkt(s,pkt);
946 sbeth_fillrxring(s,chan);
950 /* *********************************************************************
951 * SBETH_INITCHAN(s)
953 * Initialize the Ethernet channel (program the CSRs to
954 * get the channel set up)
956 * Input parameters:
957 * s - sbeth structure
959 * Return value:
960 * nothing
961 ********************************************************************* */
963 static void sbeth_initchan(sbeth_t *s)
965 sbeth_port_t port;
966 int idx;
967 uint64_t cfg,fifo,framecfg;
970 * Bring the controller out of reset, and set the "must be one"
971 * bits.
974 SBETH_WRITECSR(s->sbe_macenable,0);
977 * Set up some stuff in the control registers, but do not
978 * enable the channel
981 cfg = M_MAC_RETRY_EN |
982 M_MAC_TX_HOLD_SOP_EN |
983 V_MAC_TX_PAUSE_CNT_16K |
984 V_MAC_SPEED_SEL_100MBPS |
985 M_MAC_AP_STAT_EN |
986 M_MAC_FAST_SYNC |
987 M_MAC_SS_EN |
990 fifo = V_MAC_TX_WR_THRSH(4) | /* Must be '4' or '8' */
991 V_MAC_TX_RD_THRSH(8) |
992 V_MAC_TX_RL_THRSH(4) |
993 V_MAC_RX_PL_THRSH(4) |
994 V_MAC_RX_RD_THRSH(4) | /* Must be '4' */
995 V_MAC_RX_PL_THRSH(4) |
996 V_MAC_RX_RL_THRSH(8) |
1000 framecfg = V_MAC_MIN_FRAMESZ_DEFAULT |
1001 V_MAC_MAX_FRAMESZ_DEFAULT |
1002 V_MAC_BACKOFF_SEL(1);
1006 * Clear out the hash address map
1009 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_HASH_BASE);
1010 for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
1011 SBETH_WRITECSR(port,0);
1012 port += sizeof(uint64_t);
1017 * Clear out the exact-match table
1020 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE);
1021 for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
1022 SBETH_WRITECSR(port,0);
1023 port += sizeof(uint64_t);
1028 * Clear out the DMA Channel mapping table registers
1031 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHUP0_BASE);
1032 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
1033 SBETH_WRITECSR(port,0);
1034 port += sizeof(uint64_t);
1037 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHLO0_BASE);
1038 for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
1039 SBETH_WRITECSR(port,0);
1040 port += sizeof(uint64_t);
1043 if (!s->sbe_zerormon) {
1044 s->sbe_zerormon =1;
1045 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BYTES),0);
1046 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_COLLISIONS),0);
1047 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_LATE_COL),0);
1048 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_EX_COL),0);
1049 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_FCS_ERROR),0);
1050 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_ABORT),0);
1051 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BAD),0);
1052 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_GOOD),0);
1053 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_RUNT),0);
1054 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_OVERSIZE),0);
1055 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BYTES),0);
1056 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_MCAST),0);
1057 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BCAST),0);
1058 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BAD),0);
1059 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_GOOD),0);
1060 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_RUNT),0);
1061 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_OVERSIZE),0);
1062 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_FCS_ERROR),0);
1063 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_LENGTH_ERROR),0);
1064 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_CODE_ERROR),0);
1065 SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_ALIGN_ERROR),0);
1070 * Configure the receive filter for no packets
1073 SBETH_WRITECSR(s->sbe_rxfilter,0);
1074 SBETH_WRITECSR(s->sbe_imr,0);
1075 SBETH_WRITECSR(s->sbe_framecfg,framecfg);
1076 SBETH_WRITECSR(s->sbe_fifocfg,fifo);
1077 SBETH_WRITECSR(s->sbe_maccfg,cfg);
1082 /* *********************************************************************
1083 * SBETH_INITCTX(s,mac)
1085 * Initialize an Ethernet context structure - this is called
1086 * once per MAC on the 1250.
1088 * Input parameters:
1089 * s - sbeth context structure
1090 * mac - number of this MAC (0,1,2)
1091 * ifctx - interface context (reference saved by driver)
1093 * Return value:
1095 ********************************************************************* */
1096 static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx)
1100 * Start with all zeroes
1102 memset(s,0,sizeof(sbeth_t));
1105 * Identify ourselves
1108 s->sbe_baseaddr = baseaddr;
1109 s->sbe_ifctx = ifctx;
1111 s->sbe_minrxring = 8;
1114 * Set default hardware address. This is in case there is *no* environment.
1117 s->sbe_hwaddr[0] = 0x40;
1118 s->sbe_hwaddr[1] = 0x00;
1119 s->sbe_hwaddr[2] = (s->sbe_baseaddr >> 24) & 0xFF;
1120 s->sbe_hwaddr[3] = (s->sbe_baseaddr >> 16) & 0xFF;
1121 s->sbe_hwaddr[4] = (s->sbe_baseaddr >> 8) & 0xFF;
1122 s->sbe_hwaddr[5] = (s->sbe_baseaddr >> 0) & 0xFF;
1125 * figure out the addresses of some ports
1127 s->sbe_macenable = SBETH_PORT(s->sbe_baseaddr + R_MAC_ENABLE);
1128 s->sbe_maccfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_CFG);
1129 s->sbe_fifocfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_THRSH_CFG);
1130 s->sbe_framecfg = SBETH_PORT(s->sbe_baseaddr + R_MAC_FRAMECFG);
1131 s->sbe_rxfilter = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADFILTER_CFG);
1133 s->sbe_isr = SBETH_PORT(s->sbe_baseaddr + R_MAC_STATUS);
1134 s->sbe_imr = SBETH_PORT(s->sbe_baseaddr + R_MAC_INT_MASK);
1136 s->sbe_mdio = SBETH_PORT(s->sbe_baseaddr + R_MAC_MDIO);
1139 * Initialize the DMA channels.
1142 sbdma_initctx(s,&(s->sbe_txdma[0]),0,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback);
1143 sbdma_initctx(s,&(s->sbe_rxdma[0]),0,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback);
1144 #if (SBETH_DMA_CHANNELS == 2)
1145 sbdma_initctx(s,&(s->sbe_txdma[1]),1,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback);
1146 sbdma_initctx(s,&(s->sbe_rxdma[1]),1,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback);
1147 #endif
1150 * initialize free list
1153 s->sbe_freelist = NULL;
1154 s->sbe_rxqueue = NULL;
1156 s->sbe_pktpool = KMALLOC(SBETH_PKTBUF_SIZE*SBETH_PKTPOOL_SIZE,
1157 SBDMA_CACHESIZE);
1161 * Set values for the PHY so that when we poll the phy status
1162 * we'll notice that it has changed.
1165 s->sbe_phy_oldbmsr = 0xFFFFFFFF;
1166 s->sbe_phy_oldbmcr = 0xFFFFFFFF;
1167 s->sbe_phy_oldanlpar = 0xFFFFFFFF;
1168 s->sbe_phy_oldk1stsr = 0xFFFFFFFF;
1171 * initial state is OFF
1174 s->sbe_state = sbeth_state_off;
1176 return 0;
1180 /* *********************************************************************
1181 * SBETH_START(s)
1183 * Start packet processing on this MAC.
1185 * Input parameters:
1186 * s - sbeth structure
1188 * Return value:
1189 * nothing
1190 ********************************************************************* */
1192 static void sbeth_start(sbeth_t *s)
1194 uint64_t ctl;
1196 sbdma_initchan(s,&(s->sbe_txdma[0]));
1197 sbdma_initchan(s,&(s->sbe_rxdma[0]));
1198 #if (SBETH_DMA_CHANNELS == 2)
1199 sbdma_initchan(s,&(s->sbe_txdma[1]));
1200 sbdma_initchan(s,&(s->sbe_rxdma[1]));
1201 #endif
1202 sbeth_initchan(s);
1204 sbeth_setspeed(s,s->sbe_speed);
1205 sbeth_set_duplex(s,s->sbe_duplex,s->sbe_fc);
1207 SBETH_WRITECSR(s->sbe_rxfilter,0);
1209 ctl = SBETH_READCSR(s->sbe_macenable);
1211 ctl |= M_MAC_RXDMA_EN0 |
1212 M_MAC_TXDMA_EN0 |
1213 #if (SBETH_DMA_CHANNELS == 2)
1214 M_MAC_TXDMA_EN1 |
1215 M_MAC_RXDMA_EN1 |
1216 #endif
1217 M_MAC_RX_ENABLE |
1218 M_MAC_TX_ENABLE |
1221 sbeth_initfreelist(s);
1223 SBETH_WRITECSR(s->sbe_macenable,ctl);
1225 sbeth_setaddr(s,s->sbe_hwaddr);
1227 #ifdef _SB1250_PASS1_WORKAROUNDS_
1228 /* Must set the Ethernet address to zero in pass1 */
1229 do {
1230 sbeth_port_t port;
1231 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR);
1232 SBETH_WRITECSR(port,0);
1233 } while (0);
1234 #endif
1236 sbeth_fillrxring(s,0);
1238 SBETH_WRITECSR(s->sbe_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN |
1239 V_MAC_IPHDR_OFFSET(15) |
1240 /* M_MAC_ALLPKT_EN |*/ /* uncomment for promisc mode */
1244 s->sbe_state = sbeth_state_on;
1248 /* *********************************************************************
1249 * SBETH_STOP(s)
1251 * Stop packet processing on this MAC.
1253 * Input parameters:
1254 * s - sbeth structure
1256 * Return value:
1257 * nothing
1258 ********************************************************************* */
1260 static void sbeth_stop(sbeth_t *s)
1262 uint64_t ctl;
1263 int mac_mdio_genc;
1265 SBETH_WRITECSR(s->sbe_rxfilter,0);
1267 ctl = SBETH_READCSR(s->sbe_macenable);
1269 ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 | M_MAC_RXDMA_EN1 | M_MAC_TXDMA_EN1 |
1270 M_MAC_RX_ENABLE | M_MAC_TX_ENABLE);
1272 SBETH_WRITECSR(s->sbe_macenable,ctl);
1275 * The genc bit on the MAC MDIO register needs to be preserved through reset.
1276 * Read the MAC MDIO register and mask out genc bit.
1278 mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
1280 ctl |= M_MAC_PORT_RESET;
1282 SBETH_WRITECSR(s->sbe_macenable,ctl);
1284 /* Write back value of genc bit */
1285 SBETH_WRITECSR(s->sbe_mdio,mac_mdio_genc);
1287 s->sbe_state = sbeth_state_off;
1289 sbdma_reset(&(s->sbe_txdma[0]));
1290 sbdma_reset(&(s->sbe_rxdma[0]));
1296 /* *********************************************************************
1297 * SBETH_SETADDR(s,addr)
1299 * Set the ethernet address for the specified MAC
1301 * Input parameters:
1302 * s - sbeth structure
1303 * addr - Ethernet address
1305 * Return value:
1306 * nothing
1307 ********************************************************************* */
1309 static void sbeth_setaddr(sbeth_t *s,uint8_t *addr)
1311 sbeth_port_t port;
1312 uint64_t regval = 0;
1313 int idx;
1316 * Pack the bytes into the register, with the first byte transmitted
1317 * in the lowest-order 8 bits of the register.
1320 for (idx = 0; idx < 6; idx++) {
1321 regval |= (((uint64_t) (*addr)) << (idx*8));
1322 addr++;
1327 * Write to the port.
1330 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR);
1331 SBETH_WRITECSR(port,regval);
1333 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE);
1334 SBETH_WRITECSR(port,regval);
1338 /* *********************************************************************
1339 * SBETH_SETSPEED(s,speed)
1341 * Configure LAN speed for the specified MAC
1343 * Input parameters:
1344 * s - sbeth structure
1345 * speed - speed to set MAC to (see sbeth_speed_t enum)
1347 * Return value:
1348 * 1 if successful
1349 * 0 indicates invalid parameters
1350 ********************************************************************* */
1352 static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed)
1354 uint64_t cfg;
1355 uint64_t framecfg;
1358 * Read current register values
1361 cfg = SBETH_READCSR(s->sbe_maccfg);
1362 framecfg = SBETH_READCSR(s->sbe_framecfg);
1365 * Mask out the stuff we want to change
1368 cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
1369 framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
1370 M_MAC_SLOT_SIZE);
1373 * Now add in the new bits
1376 switch (speed) {
1377 case sbeth_speed_10:
1378 framecfg |= V_MAC_IFG_RX_10 |
1379 V_MAC_IFG_TX_10 |
1380 K_MAC_IFG_THRSH_10 |
1381 V_MAC_SLOT_SIZE_10;
1382 cfg |= V_MAC_SPEED_SEL_10MBPS;
1383 break;
1385 case sbeth_speed_100:
1386 framecfg |= V_MAC_IFG_RX_100 |
1387 V_MAC_IFG_TX_100 |
1388 V_MAC_IFG_THRSH_100 |
1389 V_MAC_SLOT_SIZE_100;
1390 cfg |= V_MAC_SPEED_SEL_100MBPS ;
1391 break;
1393 case sbeth_speed_1000:
1394 framecfg |= V_MAC_IFG_RX_1000 |
1395 V_MAC_IFG_TX_1000 |
1396 V_MAC_IFG_THRSH_1000 |
1397 V_MAC_SLOT_SIZE_1000;
1398 cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
1399 break;
1401 default:
1402 return 0;
1406 * Send the bits back to the hardware
1409 SBETH_WRITECSR(s->sbe_framecfg,framecfg);
1410 SBETH_WRITECSR(s->sbe_maccfg,cfg);
1412 return 1;
1416 /* *********************************************************************
1417 * SBETH_SET_DUPLEX(s,duplex,fc)
1419 * Set Ethernet duplex and flow control options for this MAC
1421 * Input parameters:
1422 * s - sbeth structure
1423 * duplex - duplex setting (see sbeth_duplex_t)
1424 * fc - flow control setting (see sbeth_fc_t)
1426 * Return value:
1427 * 1 if ok
1428 * 0 if an invalid parameter combination was specified
1429 ********************************************************************* */
1431 static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc)
1433 uint64_t cfg;
1436 * Read current register values
1439 cfg = SBETH_READCSR(s->sbe_maccfg);
1442 * Mask off the stuff we're about to change
1445 cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
1448 switch (duplex) {
1449 case sbeth_duplex_half:
1450 switch (fc) {
1451 case sbeth_fc_disabled:
1452 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
1453 break;
1455 case sbeth_fc_collision:
1456 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
1457 break;
1459 case sbeth_fc_carrier:
1460 cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
1461 break;
1463 case sbeth_fc_frame: /* not valid in half duplex */
1464 default: /* invalid selection */
1465 return 0;
1467 break;
1469 case sbeth_duplex_full:
1470 switch (fc) {
1471 case sbeth_fc_disabled:
1472 cfg |= V_MAC_FC_CMD_DISABLED;
1473 break;
1475 case sbeth_fc_frame:
1476 cfg |= V_MAC_FC_CMD_ENABLED;
1477 break;
1479 case sbeth_fc_collision: /* not valid in full duplex */
1480 case sbeth_fc_carrier: /* not valid in full duplex */
1481 /* fall through */
1482 default:
1483 return 0;
1485 break;
1489 * Send the bits back to the hardware
1492 SBETH_WRITECSR(s->sbe_maccfg,cfg);
1494 return 1;
1498 /* *********************************************************************
1499 * SBETH_TRANSMIT(s,pkt,len,arg)
1501 * Transmits a packet.
1503 * Input parameters:
1504 * s - mac to tramsmit on
1505 * chan - DMA Channel number (0 or 1)
1506 * pkt,len - buffer and length
1507 * arg - arg for callback
1509 * Return value:
1510 * 1 if packet was queued
1511 * 0 if packet was not queued
1512 ********************************************************************* */
1513 static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg)
1515 return sbdma_addbuffer(&(s->sbe_txdma[chan]),pkt,length,arg);
1518 /* *********************************************************************
1519 * SBETH_ADDRCVBUF(s,pkt,len,arg)
1521 * Add a receive buffer to the ring
1523 * Input parameters:
1524 * s - mac to add rx buffer to
1525 * chan - DMA Channel number (0 or 1)
1526 * pkt,len - buffer and length
1527 * arg - arg for callback
1529 * Return value:
1530 * 1 if packet was queued
1531 * 0 if packet was not queued
1532 ********************************************************************* */
1533 static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg)
1535 return sbdma_addbuffer(&(s->sbe_rxdma[chan]),pkt,length,arg);
1539 /* *********************************************************************
1540 * SBETH_FILLRXRING(s,chan)
1542 * Make sure there are at least "sbe_minrxring" packets on the
1543 * receive ring for this device.
1545 * Input parameters:
1546 * s - mac structure
1548 * Return value:
1549 * nothing
1550 ********************************************************************* */
1552 static void sbeth_fillrxring(sbeth_t *s,int chan)
1554 sbeth_pkt_t *pkt;
1556 while (s->sbe_rxdma[chan].sbdma_onring < s->sbe_minrxring) {
1557 pkt = sbeth_alloc_pkt(s);
1558 if (!pkt) break;
1559 if (!sbeth_addrcvbuf(s,chan,pkt->buffer,pkt->length,pkt)) {
1560 sbeth_free_pkt(s,pkt);
1561 break;
1568 /* *********************************************************************
1569 * SBETH_ISR()
1571 * Interrupt handler for MAC interrupts
1573 * Input parameters:
1574 * MAC structure
1576 * Return value:
1577 * nothing
1578 ********************************************************************* */
1579 static void sbeth_isr(sbeth_t *s)
1581 uint64_t isr;
1582 for (;;) {
1586 * Read the ISR (this clears the bits in the real register)
1589 isr = SBETH_READCSR(s->sbe_isr);
1591 if (isr == 0) {
1592 break;
1596 * for now, don't bother asking why we were interrupted,
1597 * just process the descriptors in any event.
1602 * Transmits on channel 0
1605 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
1606 sbdma_procbuffers(&(s->sbe_txdma[0]),s->sbe_txdma[0].sbdma_upcall);
1609 #if (SBETH_DMA_CHANNELS == 2)
1611 * Transmits on channel 1
1614 if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH1)) {
1615 sbdma_procbuffers(&(s->sbe_txdma[1]),s->sbe_txdma[1].sbdma_upcall);
1617 #endif
1620 * Receives on channel 0
1623 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
1624 sbdma_procbuffers(&(s->sbe_rxdma[0]),s->sbe_rxdma[0].sbdma_upcall);
1627 #if (SBETH_DMA_CHANNELS == 2)
1629 * Receives on channel 1
1632 if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH1)) {
1633 sbdma_procbuffers(&(s->sbe_rxdma[1]),s->sbe_rxdma[1].sbdma_upcall);
1635 #endif
1641 /* *********************************************************************
1642 * SBETH_PARSE_XDIGIT(str)
1644 * Parse a hex digit, returning its value
1646 * Input parameters:
1647 * str - character
1649 * Return value:
1650 * hex value, or -1 if invalid
1651 ********************************************************************* */
1653 static int sbeth_parse_xdigit(char str)
1655 int digit;
1657 if ((str >= '0') && (str <= '9')) digit = str - '0';
1658 else if ((str >= 'a') && (str <= 'f')) digit = str - 'a' + 10;
1659 else if ((str >= 'A') && (str <= 'F')) digit = str - 'A' + 10;
1660 else return -1;
1662 return digit;
1665 /* *********************************************************************
1666 * SBETH_PARSE_HWADDR(str,hwaddr)
1668 * Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
1669 * Ethernet address.
1671 * Input parameters:
1672 * str - string
1673 * hwaddr - pointer to hardware address
1675 * Return value:
1676 * 0 if ok, else -1
1677 ********************************************************************* */
1679 static int sbeth_parse_hwaddr(char *str,uint8_t *hwaddr)
1681 int digit1,digit2;
1682 int idx = 6;
1684 while (*str && (idx > 0)) {
1685 digit1 = sbeth_parse_xdigit(*str);
1686 if (digit1 < 0) return -1;
1687 str++;
1688 if (!*str) return -1;
1690 if ((*str == ':') || (*str == '-')) {
1691 digit2 = digit1;
1692 digit1 = 0;
1694 else {
1695 digit2 = sbeth_parse_xdigit(*str);
1696 if (digit2 < 0) return -1;
1697 str++;
1700 *hwaddr++ = (digit1 << 4) | digit2;
1701 idx--;
1703 if (*str == '-') str++;
1704 if (*str == ':') str++;
1706 return 0;
1709 /* *********************************************************************
1710 * SBETH_MII_FINDPHY(s)
1712 * Find the first available PHY.
1714 * Input parameters:
1715 * s - sbeth structure
1717 * Return value:
1718 * nothing
1719 ********************************************************************* */
1720 static void sbeth_mii_findphy(sbeth_t *s)
1722 int phy;
1723 uint16_t bmsr;
1725 for (phy = 0; phy < 31; phy++) {
1726 bmsr = sbeth_mii_read(s,phy,MII_BMSR);
1727 if (bmsr != 0) {
1728 s->sbe_phyaddr = phy;
1729 return;
1733 s->sbe_phyaddr = 0;
1736 /* *********************************************************************
1737 * SBETH_MII_POLL(s)
1739 * Ask the PHY what is going on, and configure speed appropriately.
1740 * For the moment, we only support automatic configuration.
1742 * Input parameters:
1743 * s - sbeth structure
1744 * noisy - display console messages
1746 * Return value:
1747 * 1 if something has changed and we should restart the channel
1748 * 0 if nothing has changed.
1749 ********************************************************************* */
1750 static int sbeth_mii_poll(sbeth_t *s,int noisy)
1752 uint16_t bmsr,bmcr,k1stsr,anlpar;
1753 int chg;
1754 char buffer[100];
1755 char *p = buffer;
1756 char *devname;
1758 /* Read the mode status and mode control registers. */
1759 bmsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMSR);
1760 bmcr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR);
1762 /* get the link partner status */
1763 anlpar = sbeth_mii_read(s,s->sbe_phyaddr,MII_ANLPAR);
1765 /* if supported, read the 1000baseT register */
1766 if (bmsr & BMSR_1000BT_XSR) {
1767 k1stsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_K1STSR);
1769 else {
1770 k1stsr = 0;
1773 chg = 0;
1775 if ((s->sbe_phy_oldbmsr != bmsr) ||
1776 (s->sbe_phy_oldbmcr != bmcr) ||
1777 (s->sbe_phy_oldanlpar != anlpar) ||
1778 (s->sbe_phy_oldk1stsr != k1stsr)) {
1779 s->sbe_phy_oldbmsr = bmsr;
1780 s->sbe_phy_oldbmcr = bmcr;
1781 s->sbe_phy_oldanlpar = anlpar;
1782 s->sbe_phy_oldk1stsr = k1stsr;
1783 chg = 1;
1786 if (chg == 0) return 0;
1788 p += xsprintf(p,"Link speed: ");
1790 if (k1stsr & K1STSR_LP1KFD) {
1791 s->sbe_speed = sbeth_speed_1000;
1792 s->sbe_duplex = sbeth_duplex_full;
1793 s->sbe_fc = sbeth_fc_frame;
1794 s->sbe_linkstat = ETHER_SPEED_1000FDX;
1795 p += xsprintf(p,"1000BaseT FDX");
1797 else if (k1stsr & K1STSR_LP1KHD) {
1798 s->sbe_speed = sbeth_speed_1000;
1799 s->sbe_duplex = sbeth_duplex_half;
1800 s->sbe_fc = sbeth_fc_disabled;
1801 s->sbe_linkstat = ETHER_SPEED_1000HDX;
1802 p += xsprintf(p,"1000BaseT HDX");
1804 else if (anlpar & ANLPAR_TXFD) {
1805 s->sbe_speed = sbeth_speed_100;
1806 s->sbe_duplex = sbeth_duplex_full;
1807 s->sbe_fc = (anlpar & ANLPAR_PAUSE) ? sbeth_fc_frame : sbeth_fc_disabled;
1808 s->sbe_linkstat = ETHER_SPEED_100FDX;
1809 p += xsprintf(p,"100BaseT FDX");
1811 else if (anlpar & ANLPAR_TXHD) {
1812 s->sbe_speed = sbeth_speed_100;
1813 s->sbe_duplex = sbeth_duplex_half;
1814 s->sbe_fc = sbeth_fc_disabled;
1815 s->sbe_linkstat = ETHER_SPEED_100HDX;
1816 p += xsprintf(p,"100BaseT HDX");
1818 else if (anlpar & ANLPAR_10FD) {
1819 s->sbe_speed = sbeth_speed_10;
1820 s->sbe_duplex = sbeth_duplex_full;
1821 s->sbe_fc = sbeth_fc_frame;
1822 s->sbe_linkstat = ETHER_SPEED_10FDX;
1823 p += xsprintf(p,"10BaseT FDX");
1825 else if (anlpar & ANLPAR_10HD) {
1826 s->sbe_speed = sbeth_speed_10;
1827 s->sbe_duplex = sbeth_duplex_half;
1828 s->sbe_fc = sbeth_fc_collision;
1829 s->sbe_linkstat = ETHER_SPEED_10HDX;
1830 p += xsprintf(p,"10BaseT HDX");
1832 else {
1833 s->sbe_linkstat = ETHER_SPEED_UNKNOWN;
1834 p += xsprintf(p,"Unknown");
1837 #if defined(_BCM91120C_DIAG_CFG_) || defined(_BCM91125C_DIAG_CFG_) || \
1838 defined(_CSWARM_DIAG_CFG_) || defined(_CSWARM_DIAG3E_CFG_) || \
1839 defined(_PTSWARM_DIAG_CFG_) || defined(_PTSWARM_CFG_)
1840 noisy = 0;
1841 #endif
1843 if (noisy) {
1844 devname = s->sbe_devctx ? cfe_device_name(s->sbe_devctx) : "eth?";
1845 console_log("%s: %s",devname,buffer);
1848 return 1;
1852 /* *********************************************************************
1853 * SBETH_MII_SONG_AND_DANCE(s)
1855 * The CSWARM boards leave the PHYs in JTAG mode. The sequence
1856 * below turns off JTAG mode and puts the PHYs back
1857 * into their regular reset state. This is only used with the BCM5411
1859 * Input parameters:
1860 * s - sbeth
1862 * Return value:
1863 * TRUE if we were on a 5411
1864 ********************************************************************* */
1865 static int sbeth_mii_song_and_dance(sbeth_t *s)
1867 int phyid1,phyid2;
1869 phyid1 = sbeth_mii_read(s,1,MII_PHYIDR1);
1870 phyid2 = sbeth_mii_read(s,1,MII_PHYIDR2);
1872 /* Check for the 5411. Don't do this unless it is a 5411. */
1874 if ((phyid1 == 0x0020) && ((phyid2 & 0xFFF0) == 0x6070)) {
1875 /* It's a BCM5411 */
1876 /* clear ext loopback */
1877 sbeth_mii_write(s,1,MII_AUXCTL,0x0420);
1879 /* clear swap rx MDIX/TXHalfOut bits */
1880 sbeth_mii_write(s,1,MII_AUXCTL,0x0004);
1882 /* set up 10/100 advertisement */
1883 sbeth_mii_write(s,1,MII_ANAR,0x01E1);
1885 /* set up 1000 advertisement */
1886 sbeth_mii_write(s,1,MII_K1CTL,0x0300);
1888 /* set autonegotiate bit and restart autoneg */
1889 sbeth_mii_write(s,1,MII_BMCR,0x1340);
1890 return 1;
1893 /* Check for the 5421. Don't do this unless it is a 5421. */
1895 if ((phyid1 == 0x0020) && ((phyid2 & 0xFFF0) == 0x60E0)) {
1896 /* It's a BCM5421 */
1899 * Make sure that the part is in GMII, not SGMII.
1900 * This was a problem with 5421 A0 silicon
1901 * the FDX pin
1903 sbeth_mii_write(s,1,0x18,0x0392);
1905 return 1;
1909 return 0;
1913 /* *********************************************************************
1914 * Declarations for CFE Device Driver Interface routines
1915 ********************************************************************* */
1917 static int sb1250_ether_open(cfe_devctx_t *ctx);
1918 static int sb1250_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
1919 static int sb1250_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
1920 static int sb1250_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
1921 static int sb1250_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
1922 static int sb1250_ether_close(cfe_devctx_t *ctx);
1923 static void sb1250_ether_poll(cfe_devctx_t *ctx,int64_t ticks);
1924 static void sb1250_ether_reset(void *softc);
1926 /* *********************************************************************
1927 * CFE Device Driver dispatch structure
1928 ********************************************************************* */
1930 const static cfe_devdisp_t sb1250_ether_dispatch = {
1931 sb1250_ether_open,
1932 sb1250_ether_read,
1933 sb1250_ether_inpstat,
1934 sb1250_ether_write,
1935 sb1250_ether_ioctl,
1936 sb1250_ether_close,
1937 sb1250_ether_poll,
1938 sb1250_ether_reset
1941 /* *********************************************************************
1942 * CFE Device Driver descriptor
1943 ********************************************************************* */
1945 const cfe_driver_t sb1250_ether = {
1946 "SB1250 Ethernet",
1947 "eth",
1948 CFE_DEV_NETWORK,
1949 &sb1250_ether_dispatch,
1950 sb1250_ether_probe
1954 /* *********************************************************************
1955 * SB1250_ETHER_PROBE(drv,probe_a,probe_b,probe_ptr)
1957 * Probe and install an Ethernet device driver. This routine
1958 * creates a context structure and attaches to the specified
1959 * MAC device.
1961 * Input parameters:
1962 * drv - driver descriptor
1963 * probe_a - base address of MAC to probe
1964 * probe_b - not used
1965 * probe_ptr - string pointer to hardware address for this
1966 * MAC, in the form xx:xx:xx:xx:xx:xx
1968 * Return value:
1969 * nothing
1970 ********************************************************************* */
1972 static void sb1250_ether_probe(cfe_driver_t *drv,
1973 unsigned long probe_a, unsigned long probe_b,
1974 void *probe_ptr)
1976 sbeth_t *softc;
1977 char descr[100];
1979 softc = (sbeth_t *) KMALLOC(sizeof(sbeth_t),0);
1981 if (softc) {
1982 sbeth_initctx(softc,probe_a,softc);
1983 if (probe_ptr) {
1984 sbeth_parse_hwaddr((char *) probe_ptr,softc->sbe_hwaddr);
1986 xsprintf(descr,"%s at 0x%X (%a)",drv->drv_description,probe_a,
1987 softc->sbe_hwaddr);
1988 sbeth_mii_song_and_dance(softc);
1989 cfe_attach(drv,softc,NULL,descr);
1990 sbeth_setaddr(softc,softc->sbe_hwaddr);
1995 /* *********************************************************************
1996 * SB1250_ETHER_READENV(ctx)
1998 * Read the environment variable that corresponds to this
1999 * interface to pick up the hardware address. Note that the way
2000 * we do this is somewhat slimey.
2002 * Input parameters:
2003 * ctx - device context
2005 * Return value:
2006 * nothing
2007 ********************************************************************* */
2009 static void sb1250_ether_readenv(cfe_devctx_t *ctx)
2011 sbeth_t *softc = ctx->dev_softc;
2012 char envbuf[100];
2013 char *hwaddr;
2016 * Gross - we should *not* be reaching into these data
2017 * structures like this!
2020 xsprintf(envbuf,"%s_HWADDR",cfe_device_name(ctx));
2021 strupr(envbuf);
2023 hwaddr = env_getenv(envbuf);
2025 if (hwaddr) {
2026 sbeth_parse_hwaddr(hwaddr,softc->sbe_hwaddr);
2031 /* *********************************************************************
2032 * SB1250_MII_DUMP(s)
2034 * Dump out the MII registers
2036 * Input parameters:
2037 * s - sbeth structure
2039 * Return value:
2040 * nothing
2041 ********************************************************************* */
2044 /* *********************************************************************
2045 * SB1250_ETHER_OPEN(ctx)
2047 * Open the Ethernet device. The MAC is reset, initialized, and
2048 * prepared to receive and send packets.
2050 * Input parameters:
2051 * ctx - device context (includes ptr to our softc)
2053 * Return value:
2054 * status, 0 = ok
2055 ********************************************************************* */
2057 static int sb1250_ether_open(cfe_devctx_t *ctx)
2059 sbeth_t *softc = ctx->dev_softc;
2061 softc->sbe_devctx = ctx;
2063 sbeth_stop(softc);
2065 sbeth_mii_findphy(softc);
2068 * Note: The Phy can take several seconds to become ready!
2069 * This gross code pounds on the phy until it says it is
2070 * ready, but it still takes 2 more seconds after this
2071 * before the link is usable. We're better off letting the
2072 * dhcp/arp retries do the right thing here.
2075 sbeth_mii_poll(softc,TRUE);
2077 sb1250_ether_readenv(ctx);
2079 TIMER_SET(softc->sbe_linkstat_timer,SBETH_MIIPOLL_TIMER);
2080 softc->sbe_autospeed = TRUE;
2081 softc->fifo_mode = FALSE;
2083 sbeth_start(softc);
2085 return 0;
2088 /* *********************************************************************
2089 * SB1250_ETHER_READ(ctx,buffer)
2091 * Read a packet from the Ethernet device. If no packets are
2092 * available, the read will succeed but return 0 bytes.
2094 * Input parameters:
2095 * ctx - device context (includes ptr to our softc)
2096 * buffer - pointer to buffer descriptor.
2098 * Return value:
2099 * status, 0 = ok
2100 ********************************************************************* */
2102 static int sb1250_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
2104 sbeth_t *softc = ctx->dev_softc;
2105 sbeth_pkt_t *pkt;
2106 int blen;
2108 if (softc->sbe_state != sbeth_state_on) return -1;
2110 sbeth_isr(softc);
2112 if (softc->sbe_rxqueue == NULL) {
2113 buffer->buf_retlen = 0;
2114 return 0;
2117 pkt = softc->sbe_rxqueue;
2118 softc->sbe_rxqueue = pkt->next;
2119 pkt->next = NULL;
2121 blen = buffer->buf_length;
2122 if (blen > pkt->length) blen = pkt->length;
2124 memcpy(buffer->buf_ptr,pkt->buffer,blen);
2125 buffer->buf_retlen = blen;
2127 sbeth_free_pkt(softc,pkt);
2128 sbeth_fillrxring(softc,0);
2129 sbeth_isr(softc);
2131 return 0;
2134 /* *********************************************************************
2135 * SB1250_ETHER_INPSTAT(ctx,inpstat)
2137 * Check for received packets on the Ethernet device
2139 * Input parameters:
2140 * ctx - device context (includes ptr to our softc)
2141 * inpstat - pointer to input status structure
2143 * Return value:
2144 * status, 0 = ok
2145 ********************************************************************* */
2146 static int sb1250_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
2148 sbeth_t *softc = ctx->dev_softc;
2150 if (softc->sbe_state != sbeth_state_on) return -1;
2152 sbeth_isr(softc);
2154 inpstat->inp_status = (softc->sbe_rxqueue == NULL) ? 0 : 1;
2156 return 0;
2159 /* *********************************************************************
2160 * SB1250_ETHER_WRITE(ctx,buffer)
2162 * Write a packet to the Ethernet device.
2164 * Input parameters:
2165 * ctx - device context (includes ptr to our softc)
2166 * buffer - pointer to buffer descriptor.
2168 * Return value:
2169 * status, 0 = ok
2170 ********************************************************************* */
2171 static int sb1250_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
2173 sbeth_t *softc = ctx->dev_softc;
2174 sbeth_pkt_t *pkt;
2175 int blen;
2177 if (softc->sbe_state != sbeth_state_on) return -1;
2180 if (!softc->fifo_mode) {
2181 /* Only do a speed check if not packet fifo mode*/
2182 if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) {
2183 sbeth_mii_poll(softc,1);
2184 if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) return -1;
2188 pkt = sbeth_alloc_pkt(softc);
2189 if (!pkt) return CFE_ERR_NOMEM;
2191 blen = buffer->buf_length;
2192 if (blen > pkt->length) blen = pkt->length;
2194 memcpy(pkt->buffer,buffer->buf_ptr,blen);
2195 pkt->length = blen;
2198 sbeth_isr(softc);
2200 if (sbeth_transmit(softc,0,pkt->buffer,pkt->length,pkt) != 1) {
2201 sbeth_free_pkt(softc,pkt);
2202 return CFE_ERR_IOERR;
2205 sbeth_isr(softc);
2207 buffer->buf_retlen = blen;
2209 return 0;
2212 /* *********************************************************************
2213 * SB1250_ETHER_IOCTL_LOOPBACK(s,loopback)
2215 * Set loopback modes
2217 * Input parameters:
2218 * s - sbeth structure
2219 * loopback - loopback modes
2221 * Return value:
2222 * 0 if ok, else error
2223 ********************************************************************* */
2225 static int sb1250_ether_ioctl_loopback(sbeth_t *s,int loopback)
2227 unsigned int miireg;
2228 uint64_t regval;
2230 switch (loopback) {
2231 case ETHER_LOOPBACK_OFF:
2232 miireg = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR);
2233 if (miireg & BMCR_LOOPBACK) {
2234 miireg &= ~BMCR_LOOPBACK;
2235 miireg |= BMCR_RESTARTAN;
2236 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,miireg);
2238 regval = SBETH_READCSR(s->sbe_maccfg);
2239 if (regval & M_MAC_LOOPBACK_SEL) {
2240 regval &= ~M_MAC_LOOPBACK_SEL;
2241 SBETH_WRITECSR(s->sbe_maccfg,regval);
2243 break;
2245 case ETHER_LOOPBACK_INT:
2246 regval = SBETH_READCSR(s->sbe_maccfg);
2247 regval |= M_MAC_LOOPBACK_SEL;
2248 SBETH_WRITECSR(s->sbe_maccfg,regval);
2249 break;
2251 case ETHER_LOOPBACK_EXT:
2252 regval = SBETH_READCSR(s->sbe_maccfg);
2253 if (regval & M_MAC_LOOPBACK_SEL) {
2254 regval &= ~M_MAC_LOOPBACK_SEL;
2255 SBETH_WRITECSR(s->sbe_maccfg,regval);
2257 miireg = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR);
2258 miireg |= BMCR_LOOPBACK;
2259 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,miireg);
2260 break;
2263 s->sbe_loopback = loopback;
2265 return 0;
2269 /* *********************************************************************
2270 * SB1250_ETHER_IOCTL_SPEED(s,speed)
2272 * Set speed forcibly via the IOCTL command
2274 * Input parameters:
2275 * s - sbeth structure
2276 * speed - speed IOCTL setting
2278 * Return value:
2279 * 0 if ok, else error
2280 ********************************************************************* */
2282 static int sb1250_ether_ioctl_speed(sbeth_t *s,int speed)
2284 switch (speed) {
2285 case ETHER_SPEED_AUTO:
2286 s->sbe_autospeed = TRUE;
2287 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2288 BMCR_ANENABLE|BMCR_RESTARTAN|BMCR_DUPLEX|BMCR_SPEED1);
2289 TIMER_SET(s->sbe_linkstat_timer,100);
2290 break;
2292 case ETHER_SPEED_10HDX:
2293 s->sbe_autospeed = FALSE;
2294 s->sbe_speed = sbeth_speed_10;
2295 s->sbe_duplex = sbeth_duplex_half;
2296 s->sbe_fc = sbeth_fc_disabled;
2297 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2298 BMCR_SPEED10);
2299 break;
2301 case ETHER_SPEED_10FDX:
2302 s->sbe_autospeed = FALSE;
2303 s->sbe_speed = sbeth_speed_10;
2304 s->sbe_duplex = sbeth_duplex_full;
2305 s->sbe_fc = sbeth_fc_frame;
2306 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2307 BMCR_SPEED10|BMCR_DUPLEX);
2308 break;
2310 case ETHER_SPEED_100HDX:
2311 s->sbe_autospeed = FALSE;
2312 s->sbe_speed = sbeth_speed_100;
2313 s->sbe_duplex = sbeth_duplex_half;
2314 s->sbe_fc = sbeth_fc_disabled;
2315 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2316 BMCR_SPEED100);
2317 break;
2319 case ETHER_SPEED_100FDX:
2320 s->sbe_autospeed = FALSE;
2321 s->sbe_speed = sbeth_speed_100;
2322 s->sbe_duplex = sbeth_duplex_full;
2323 s->sbe_fc = sbeth_fc_frame;
2324 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2325 BMCR_SPEED100|BMCR_DUPLEX);
2326 break;
2328 case ETHER_SPEED_1000HDX:
2329 s->sbe_autospeed = FALSE;
2330 s->sbe_speed = sbeth_speed_1000;
2331 s->sbe_duplex = sbeth_duplex_half;
2332 s->sbe_fc = sbeth_fc_disabled;
2333 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2334 BMCR_SPEED1000);
2335 break;
2337 case ETHER_SPEED_1000FDX:
2338 s->sbe_autospeed = FALSE;
2339 s->sbe_speed = sbeth_speed_1000;
2340 s->sbe_duplex = sbeth_duplex_full;
2341 s->sbe_fc = sbeth_fc_frame;
2342 sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2343 BMCR_SPEED1000|BMCR_DUPLEX);
2344 break;
2346 default:
2347 return -1;
2350 sbeth_stop(s);
2351 sbeth_start(s);
2353 s->sbe_curspeed = speed;
2354 if (speed != ETHER_SPEED_AUTO) s->sbe_linkstat = speed;
2356 return 0;
2358 /* *********************************************************************
2359 * SB1250_ETHER_IOCTL_PACKETFIFO(s,mode)
2361 * Swtich to a packet fifo mode.
2364 * Input parameters:
2365 * s - sbeth structure
2366 * mode - 8 or 16 bit packet fifo mode.
2368 * Return value:
2369 * 0 if ok, else error
2370 ********************************************************************* */
2371 static int sb1250_ether_ioctl_packetfifo(sbeth_t *s, int mode)
2373 uint64_t cfg;
2374 uint64_t enb;
2375 uint64_t frame;
2377 cfg = SBETH_READCSR(s->sbe_maccfg);
2378 switch (mode) {
2379 case ETHER_FIFO_8:
2380 cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_AP_STAT_EN | M_MAC_SPEED_SEL | M_MAC_BURST_EN);
2381 cfg |= M_MAC_BYPASS_SEL | V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
2383 /* disable rx/tx ethernet macs and enable rx/tx fifo engines */
2384 enb = SBETH_READCSR(s->sbe_macenable);
2385 enb &= ~(M_MAC_RX_ENABLE | M_MAC_TX_ENABLE);
2386 enb |= M_MAC_BYP_RX_ENABLE |
2387 M_MAC_BYP_TX_ENABLE |
2389 SBETH_WRITECSR(s->sbe_macenable,enb);
2391 /* accept all packets */
2392 SBETH_WRITECSR(s->sbe_rxfilter, M_MAC_ALLPKT_EN | 0);
2394 /* set min_frame_size to 9 bytes */
2395 frame = SBETH_READCSR(s->sbe_framecfg);
2396 frame |= V_MAC_MIN_FRAMESZ_FIFO;
2397 SBETH_WRITECSR(s->sbe_framecfg,frame);
2399 s->fifo_mode = TRUE;
2401 break;
2403 case ETHER_FIFO_16:
2404 cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | M_MAC_AP_STAT_EN | M_MAC_SPEED_SEL | M_MAC_BURST_EN);
2405 cfg |= M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
2407 /* disable rx/tx ethernet macs and enable rx/tx fifo engines */
2408 enb = SBETH_READCSR(s->sbe_macenable);
2409 enb &= ~(M_MAC_RX_ENABLE | M_MAC_TX_ENABLE);
2410 enb |= M_MAC_BYP_RX_ENABLE |
2411 M_MAC_BYP_TX_ENABLE |
2413 SBETH_WRITECSR(s->sbe_macenable,enb);
2415 /* accept all packets */
2416 SBETH_WRITECSR(s->sbe_rxfilter, M_MAC_ALLPKT_EN | 0);
2418 /* set min_frame_size to 9 bytes */
2419 frame = SBETH_READCSR(s->sbe_framecfg);
2420 frame |= V_MAC_MIN_FRAMESZ_FIFO;
2421 SBETH_WRITECSR(s->sbe_framecfg,frame);
2423 s->fifo_mode = TRUE;
2425 break;
2427 case ETHER_ETHER:
2428 cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | M_MAC_AP_STAT_EN );
2429 cfg |= M_MAC_AP_STAT_EN;
2430 break;
2432 default:
2433 return -1;
2436 SBETH_WRITECSR(s->sbe_maccfg,cfg);
2438 return 0;
2441 /* *********************************************************************
2442 * SB1250_ETHER_IOCTL_STROBESIGNAL
2444 * Set the strobe signal that are used on both transmit and receive
2445 * interfaces in packet fifo mode.
2447 * Input parameters:
2448 * s - sbeth structure
2449 * mode - GMII style, Encoded, SOP flagged, or EOP flagged mode.
2451 * Return value:
2452 * 0 if ok, else error
2453 ********************************************************************* */
2454 static int sb1250_ether_ioctl_strobesignal(sbeth_t *s, int mode)
2456 uint64_t cfg;
2458 cfg = SBETH_READCSR(s->sbe_maccfg);
2460 switch (mode) {
2461 case ETHER_STROBE_GMII:
2462 cfg &= ~(M_MAC_BYPASS_CFG);
2463 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_GMII);
2464 break;
2466 case ETHER_STROBE_ENCODED:
2467 cfg &= ~(M_MAC_BYPASS_CFG);
2468 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_ENCODED);
2469 break;
2471 case ETHER_STROBE_SOP: /* not valid in 16-bit fifo mode */
2472 cfg &= ~(M_MAC_BYPASS_CFG);
2473 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_SOP);
2474 break;
2476 case ETHER_STROBE_EOP: /* not valid in 16-bit fifo mode */
2477 cfg &= ~(M_MAC_BYPASS_CFG);
2478 cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_EOP);
2479 break;
2481 default:
2482 return -1;
2485 SBETH_WRITECSR(s->sbe_maccfg,cfg);
2487 return 0;
2490 /* *********************************************************************
2491 * SB1250_ETHER_IOCTL(ctx,buffer)
2493 * Do device-specific I/O control operations for the device
2495 * Input parameters:
2496 * ctx - device context (includes ptr to our softc)
2497 * buffer - pointer to buffer descriptor.
2499 * Return value:
2500 * status, 0 = ok
2501 ********************************************************************* */
2502 static int sb1250_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
2504 sbeth_t *softc = ctx->dev_softc;
2505 int *mode;
2507 switch ((int)buffer->buf_ioctlcmd) {
2508 case IOCTL_ETHER_GETHWADDR:
2509 memcpy(buffer->buf_ptr,softc->sbe_hwaddr,sizeof(softc->sbe_hwaddr));
2510 break;
2512 case IOCTL_ETHER_SETHWADDR:
2513 memcpy(softc->sbe_hwaddr,buffer->buf_ptr,sizeof(softc->sbe_hwaddr));
2514 sbeth_setaddr(softc,softc->sbe_hwaddr);
2515 #ifdef _SB1250_PASS1_WORKAROUNDS_
2516 SBETH_WRITECSR(SBETH_PORT(softc->sbe_baseaddr + R_MAC_ETHERNET_ADDR),0);
2517 #endif
2518 break;
2520 case IOCTL_ETHER_GETSPEED:
2521 mode = (int *) buffer->buf_ptr;
2522 *mode = softc->sbe_curspeed;
2523 break;
2525 case IOCTL_ETHER_SETSPEED:
2526 mode = (int *) buffer->buf_ptr;
2527 return sb1250_ether_ioctl_speed(softc,*mode);
2528 break;
2530 case IOCTL_ETHER_GETLINK:
2531 mode = (int *) buffer->buf_ptr;
2532 *mode = softc->sbe_linkstat;
2533 break;
2535 case IOCTL_ETHER_GETLOOPBACK:
2536 mode = (int *) buffer->buf_ptr;
2537 *mode = softc->sbe_loopback;
2538 break;
2540 case IOCTL_ETHER_SETLOOPBACK:
2541 mode = (int *) buffer->buf_ptr;
2542 return sb1250_ether_ioctl_loopback(softc,*mode);
2543 break;
2545 case IOCTL_ETHER_SETPACKETFIFO:
2546 mode = (int *) buffer->buf_ptr;
2547 return sb1250_ether_ioctl_packetfifo(softc,*mode);
2548 break;
2550 case IOCTL_ETHER_SETSTROBESIG:
2551 mode = (int *) buffer->buf_ptr;
2552 return sb1250_ether_ioctl_strobesignal(softc,*mode);
2553 break;
2555 default:
2556 return -1;
2559 return 0;
2562 /* *********************************************************************
2563 * SB1250_ETHER_CLOSE(ctx)
2565 * Close the Ethernet device.
2567 * Input parameters:
2568 * ctx - device context (includes ptr to our softc)
2570 * Return value:
2571 * status, 0 = ok
2572 ********************************************************************* */
2573 static int sb1250_ether_close(cfe_devctx_t *ctx)
2575 sbeth_t *softc = ctx->dev_softc;
2577 sbeth_stop(softc);
2579 /* Reprogram the default hardware address in case someone mucked with it */
2580 sbeth_setaddr(softc,softc->sbe_hwaddr);
2582 return 0;
2586 /* *********************************************************************
2587 * SB1250_ETHER_POLL(ctx,ticks)
2589 * Check for changes in the PHY, so we can track speed changes.
2591 * Input parameters:
2592 * ctx - device context (includes ptr to our softc)
2593 * ticks- current time in ticks
2595 * Return value:
2596 * nothing
2597 ********************************************************************* */
2599 static void sb1250_ether_poll(cfe_devctx_t *ctx,int64_t ticks)
2601 sbeth_t *softc = ctx->dev_softc;
2602 int chg;
2604 if (TIMER_RUNNING(softc->sbe_linkstat_timer) &&
2605 TIMER_EXPIRED(softc->sbe_linkstat_timer)) {
2606 if (softc->sbe_autospeed) {
2607 chg = sbeth_mii_poll(softc,TRUE);
2608 if (chg) {
2609 if (softc->sbe_state == sbeth_state_on) {
2610 TIMER_CLEAR(softc->sbe_linkstat_timer);
2611 sbeth_stop(softc);
2612 sbeth_start(softc);
2616 TIMER_SET(softc->sbe_linkstat_timer,SBETH_MIIPOLL_TIMER);
2621 /* *********************************************************************
2622 * SB1250_ETHER_RESET(softc)
2624 * This routine is called when CFE is restarted after a
2625 * program exits. We can clean up pending I/Os here.
2627 * Input parameters:
2628 * softc - pointer to sbmac_t
2630 * Return value:
2631 * nothing
2632 ********************************************************************* */
2634 static void sb1250_ether_reset(void *softc)
2636 sbeth_t *s = (sbeth_t *) softc;
2637 sbeth_port_t port;
2638 uint64_t regval = 0;
2639 int idx;
2640 uint8_t *addr;
2643 * Turn off the Ethernet interface.
2646 SBETH_WRITECSR(s->sbe_macenable,0);
2649 * Reset the address.
2650 * Pack the bytes into the register, with the first byte transmitted
2651 * in the lowest-order 8 bits of the register.
2654 addr = s->sbe_hwaddr;
2655 for (idx = 0; idx < 6; idx++) {
2656 regval |= (((uint64_t) (*addr)) << (idx*8));
2657 addr++;
2662 * Write to the port.
2665 port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR);
2666 SBETH_WRITECSR(port,regval);