1 /* *********************************************************************
4 * CFE Ethernet Driver File: DEV_SB1250_ETHERNET.C
6 * Author: Mitch Lichtenberg (mpl@broadcom.com)
8 * This is the console monitor Ethernet driver for the SB1250
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 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_malloc.h"
51 #include "lib_string.h"
52 #include "lib_printf.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"
63 #include "sb1250_defs.h"
64 #include "sb1250_regs.h"
65 #include "sb1250_mac.h"
66 #include "sb1250_dma.h"
69 /* *********************************************************************
71 ********************************************************************* */
74 typedef volatile uint64_t sbeth_port_t
;
75 typedef uint64_t sbeth_physaddr_t
;
76 #define SBETH_PORT(x) PHYS_TO_K1(x)
78 typedef volatile uint32_t sbeth_port_t
;
79 typedef uint32_t sbeth_physaddr_t
;
80 #define SBETH_PORT(x) PHYS_TO_K1(x)
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
{
127 /* *********************************************************************
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
);
167 typedef struct sbeth_pkt_s
{
168 struct sbeth_pkt_s
*next
;
170 unsigned char *buffer
;
172 /* packet data goes here */
175 /* *********************************************************************
176 * Ethernet controller structure
177 ********************************************************************* */
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
];
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
];
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 /* *********************************************************************
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
,
254 static void sbeth_setaddr(sbeth_t
*s
,uint8_t *addr
);
256 /* *********************************************************************
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 /* *********************************************************************
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.
297 * s - sbmac structure
301 ********************************************************************* */
303 static void sbeth_mii_sync(sbeth_t
*s
)
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.
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
)
338 unsigned int curmask
;
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
);
360 /* *********************************************************************
361 * SBETH_MII_READ(s,phyaddr,regidx)
363 * Read a PHY register.
366 * s - sbmac structure
367 * phyaddr - PHY's address
368 * regidx = index of register to read
371 * value read, or 0 if an error occured.
372 ********************************************************************* */
374 static unsigned int sbeth_mii_read(sbeth_t
*s
,int phyaddr
,int regidx
)
382 * Synchronize ourselves so that the PHY knows the next
383 * thing coming down is a command
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
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
);
429 for (idx
= 0; idx
< 16; idx
++) {
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
;
448 /* *********************************************************************
449 * SBETH_MII_WRITE(s,phyaddr,regidx,regval)
451 * Write a value to a PHY register.
454 * s - sbmac structure
455 * phyaddr - PHY to use
456 * regidx - register within the PHY
457 * regval - data to write to register
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
,
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.
492 * s - sbeth structure
493 * d - sbdma structure
497 ********************************************************************* */
498 static void sbdma_initchan(sbeth_t
*s
,
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
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
531 ********************************************************************* */
533 static void sbdma_initctx(sbeth_t
*s
,
538 void (*callback
)(void *,int,void *,uint64_t,unsigned int))
541 * Save away interesting stuff in the structure
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 *));
578 d
->sbdma_upcall
= callback
;
585 /* *********************************************************************
588 * Reset the software-maintained state for the specified
596 ********************************************************************* */
598 static void sbdma_reset(sbethdma_t
*d
)
600 d
->sbdma_addptr
= d
->sbdma_dscrtable
;
601 d
->sbdma_remptr
= d
->sbdma_dscrtable
;
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
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
622 * number of packets processed.
623 ********************************************************************* */
625 static int sbdma_procbuffers(sbethdma_t
*d
,
626 void (*procfunc
)(void *ifctx
,int chan
,void *ctx
,
628 unsigned int pktlen
))
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
;
650 tmp
= SBETH_READCSR(d
->sbdma_curdscr
);
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.
673 * Otherwise, issue the upcall.
677 dsc
= &(d
->sbdma_dscrtable
[curidx
]);
678 (*procfunc
)(d
->sbdma_eth
->sbe_ifctx
,
680 d
->sbdma_ctxtable
[curidx
],
681 dsc
->dscr_a
& M_DMA_DSCRA_STATUS
,
682 (int)G_DMA_DSCRB_PKT_SIZE(dsc
->dscr_b
));
686 * .. and advance to the next buffer.
689 d
->sbdma_remptr
= sbdma_nextbuf(d
,sbdma_remptr
);
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.
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.)
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
)
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
) {
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
|
748 dsc
->dscr_b
= V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_NOMODS
) |
749 V_DMA_DSCRB_PKT_SIZE(length
);
752 dsc
->dscr_b
= V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD
) |
753 V_DMA_DSCRB_PKT_SIZE(length
);
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
;
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
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.
796 * s - sbeth structure
800 ********************************************************************* */
802 static void sbeth_initfreelist(sbeth_t
*s
)
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 /* *********************************************************************
826 * Allocate a packet from the free list.
829 * s - sbeth structure
832 * pointer to packet structure, or NULL if none available
833 ********************************************************************* */
835 static sbeth_pkt_t
*sbeth_alloc_pkt(sbeth_t
*s
)
838 sbeth_pkt_t
*pkt
= s
->sbe_freelist
;
840 if (!pkt
) return NULL
;
842 s
->sbe_freelist
= pkt
->next
;
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
;
856 /* *********************************************************************
857 * SBETH_FREE_PKT(s,pkt)
859 * Return a packet to the free list
862 * s - sbmac structure
863 * pkt - packet to return
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.
882 * ifctx - interface context (sbeth structure)
884 * ctx - packet context (sbeth_pkt structure)
885 * status - Ethernet status from descriptor
886 * pktsize - length of packet (unused for transmits)
890 ********************************************************************* */
892 static void sbeth_tx_callback(void *ifctx
,int chan
,void *ctx
,
893 uint64_t status
,unsigned int pktsize
)
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.
913 * ifctx - interface context (sbeth structure)
915 * ctx - packet context (sbeth_pkt structure)
916 * status - Ethernet status from descriptor
917 * pktsize - length of packet (unused for transmits)
921 ********************************************************************* */
922 static void sbeth_rx_callback(void *ifctx
,int chan
,void *ctx
,
923 uint64_t status
,unsigned int pktsize
)
926 sbeth_pkt_t
*pkt
= ctx
;
927 sbeth_pkt_t
*listptr
;
929 if (!(status
& M_DMA_ETHRX_BAD
)) {
931 pkt
->length
= pktsize
;
933 if (s
->sbe_rxqueue
== NULL
) {
934 s
->sbe_rxqueue
= pkt
;
937 listptr
= s
->sbe_rxqueue
;
938 while (listptr
->next
) listptr
= listptr
->next
;
943 sbeth_free_pkt(s
,pkt
);
946 sbeth_fillrxring(s
,chan
);
950 /* *********************************************************************
953 * Initialize the Ethernet channel (program the CSRs to
954 * get the channel set up)
957 * s - sbeth structure
961 ********************************************************************* */
963 static void sbeth_initchan(sbeth_t
*s
)
967 uint64_t cfg
,fifo
,framecfg
;
970 * Bring the controller out of reset, and set the "must be one"
974 SBETH_WRITECSR(s
->sbe_macenable
,0);
977 * Set up some stuff in the control registers, but do not
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
|
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
) {
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.
1089 * s - sbeth context structure
1090 * mac - number of this MAC (0,1,2)
1091 * ifctx - interface context (reference saved by driver)
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
);
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
,
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
;
1180 /* *********************************************************************
1183 * Start packet processing on this MAC.
1186 * s - sbeth structure
1190 ********************************************************************* */
1192 static void sbeth_start(sbeth_t
*s
)
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]));
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
|
1213 #if (SBETH_DMA_CHANNELS == 2)
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 */
1231 port
= SBETH_PORT(s
->sbe_baseaddr
+ R_MAC_ETHERNET_ADDR
);
1232 SBETH_WRITECSR(port
,0);
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 /* *********************************************************************
1251 * Stop packet processing on this MAC.
1254 * s - sbeth structure
1258 ********************************************************************* */
1260 static void sbeth_stop(sbeth_t
*s
)
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
1302 * s - sbeth structure
1303 * addr - Ethernet address
1307 ********************************************************************* */
1309 static void sbeth_setaddr(sbeth_t
*s
,uint8_t *addr
)
1312 uint64_t regval
= 0;
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));
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
1344 * s - sbeth structure
1345 * speed - speed to set MAC to (see sbeth_speed_t enum)
1349 * 0 indicates invalid parameters
1350 ********************************************************************* */
1352 static int sbeth_setspeed(sbeth_t
*s
,sbeth_speed_t speed
)
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
|
1373 * Now add in the new bits
1377 case sbeth_speed_10
:
1378 framecfg
|= V_MAC_IFG_RX_10
|
1380 K_MAC_IFG_THRSH_10
|
1382 cfg
|= V_MAC_SPEED_SEL_10MBPS
;
1385 case sbeth_speed_100
:
1386 framecfg
|= V_MAC_IFG_RX_100
|
1388 V_MAC_IFG_THRSH_100
|
1389 V_MAC_SLOT_SIZE_100
;
1390 cfg
|= V_MAC_SPEED_SEL_100MBPS
;
1393 case sbeth_speed_1000
:
1394 framecfg
|= V_MAC_IFG_RX_1000
|
1396 V_MAC_IFG_THRSH_1000
|
1397 V_MAC_SLOT_SIZE_1000
;
1398 cfg
|= V_MAC_SPEED_SEL_1000MBPS
| M_MAC_BURST_EN
;
1406 * Send the bits back to the hardware
1409 SBETH_WRITECSR(s
->sbe_framecfg
,framecfg
);
1410 SBETH_WRITECSR(s
->sbe_maccfg
,cfg
);
1416 /* *********************************************************************
1417 * SBETH_SET_DUPLEX(s,duplex,fc)
1419 * Set Ethernet duplex and flow control options for this MAC
1422 * s - sbeth structure
1423 * duplex - duplex setting (see sbeth_duplex_t)
1424 * fc - flow control setting (see sbeth_fc_t)
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
)
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
);
1449 case sbeth_duplex_half
:
1451 case sbeth_fc_disabled
:
1452 cfg
|= M_MAC_HDX_EN
| V_MAC_FC_CMD_DISABLED
;
1455 case sbeth_fc_collision
:
1456 cfg
|= M_MAC_HDX_EN
| V_MAC_FC_CMD_ENABLED
;
1459 case sbeth_fc_carrier
:
1460 cfg
|= M_MAC_HDX_EN
| V_MAC_FC_CMD_ENAB_FALSECARR
;
1463 case sbeth_fc_frame
: /* not valid in half duplex */
1464 default: /* invalid selection */
1469 case sbeth_duplex_full
:
1471 case sbeth_fc_disabled
:
1472 cfg
|= V_MAC_FC_CMD_DISABLED
;
1475 case sbeth_fc_frame
:
1476 cfg
|= V_MAC_FC_CMD_ENABLED
;
1479 case sbeth_fc_collision
: /* not valid in full duplex */
1480 case sbeth_fc_carrier
: /* not valid in full duplex */
1489 * Send the bits back to the hardware
1492 SBETH_WRITECSR(s
->sbe_maccfg
,cfg
);
1498 /* *********************************************************************
1499 * SBETH_TRANSMIT(s,pkt,len,arg)
1501 * Transmits a packet.
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
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
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
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.
1550 ********************************************************************* */
1552 static void sbeth_fillrxring(sbeth_t
*s
,int chan
)
1556 while (s
->sbe_rxdma
[chan
].sbdma_onring
< s
->sbe_minrxring
) {
1557 pkt
= sbeth_alloc_pkt(s
);
1559 if (!sbeth_addrcvbuf(s
,chan
,pkt
->buffer
,pkt
->length
,pkt
)) {
1560 sbeth_free_pkt(s
,pkt
);
1568 /* *********************************************************************
1571 * Interrupt handler for MAC interrupts
1578 ********************************************************************* */
1579 static void sbeth_isr(sbeth_t
*s
)
1586 * Read the ISR (this clears the bits in the real register)
1589 isr
= SBETH_READCSR(s
->sbe_isr
);
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
);
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
);
1641 /* *********************************************************************
1642 * SBETH_PARSE_XDIGIT(str)
1644 * Parse a hex digit, returning its value
1650 * hex value, or -1 if invalid
1651 ********************************************************************* */
1653 static int sbeth_parse_xdigit(char str
)
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;
1665 /* *********************************************************************
1666 * SBETH_PARSE_HWADDR(str,hwaddr)
1668 * Convert a string in the form xx:xx:xx:xx:xx:xx into a 6-byte
1673 * hwaddr - pointer to hardware address
1677 ********************************************************************* */
1679 static int sbeth_parse_hwaddr(char *str
,uint8_t *hwaddr
)
1684 while (*str
&& (idx
> 0)) {
1685 digit1
= sbeth_parse_xdigit(*str
);
1686 if (digit1
< 0) return -1;
1688 if (!*str
) return -1;
1690 if ((*str
== ':') || (*str
== '-')) {
1695 digit2
= sbeth_parse_xdigit(*str
);
1696 if (digit2
< 0) return -1;
1700 *hwaddr
++ = (digit1
<< 4) | digit2
;
1703 if (*str
== '-') str
++;
1704 if (*str
== ':') str
++;
1709 /* *********************************************************************
1710 * SBETH_MII_FINDPHY(s)
1712 * Find the first available PHY.
1715 * s - sbeth structure
1719 ********************************************************************* */
1720 static void sbeth_mii_findphy(sbeth_t
*s
)
1725 for (phy
= 0; phy
< 31; phy
++) {
1726 bmsr
= sbeth_mii_read(s
,phy
,MII_BMSR
);
1728 s
->sbe_phyaddr
= phy
;
1736 /* *********************************************************************
1739 * Ask the PHY what is going on, and configure speed appropriately.
1740 * For the moment, we only support automatic configuration.
1743 * s - sbeth structure
1744 * noisy - display console messages
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
;
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
);
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
;
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");
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_)
1844 devname
= s
->sbe_devctx
? cfe_device_name(s
->sbe_devctx
) : "eth?";
1845 console_log("%s: %s",devname
,buffer
);
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
1863 * TRUE if we were on a 5411
1864 ********************************************************************* */
1865 static int sbeth_mii_song_and_dance(sbeth_t
*s
)
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);
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
1903 sbeth_mii_write(s
,1,0x18,0x0392);
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
= {
1933 sb1250_ether_inpstat
,
1941 /* *********************************************************************
1942 * CFE Device Driver descriptor
1943 ********************************************************************* */
1945 const cfe_driver_t sb1250_ether
= {
1949 &sb1250_ether_dispatch
,
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
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
1970 ********************************************************************* */
1972 static void sb1250_ether_probe(cfe_driver_t
*drv
,
1973 unsigned long probe_a
, unsigned long probe_b
,
1979 softc
= (sbeth_t
*) KMALLOC(sizeof(sbeth_t
),0);
1982 sbeth_initctx(softc
,probe_a
,softc
);
1984 sbeth_parse_hwaddr((char *) probe_ptr
,softc
->sbe_hwaddr
);
1986 xsprintf(descr
,"%s at 0x%X (%a)",drv
->drv_description
,probe_a
,
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.
2003 * ctx - device context
2007 ********************************************************************* */
2009 static void sb1250_ether_readenv(cfe_devctx_t
*ctx
)
2011 sbeth_t
*softc
= ctx
->dev_softc
;
2016 * Gross - we should *not* be reaching into these data
2017 * structures like this!
2020 xsprintf(envbuf
,"%s_HWADDR",cfe_device_name(ctx
));
2023 hwaddr
= env_getenv(envbuf
);
2026 sbeth_parse_hwaddr(hwaddr
,softc
->sbe_hwaddr
);
2031 /* *********************************************************************
2032 * SB1250_MII_DUMP(s)
2034 * Dump out the MII registers
2037 * s - sbeth structure
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.
2051 * ctx - device context (includes ptr to our softc)
2055 ********************************************************************* */
2057 static int sb1250_ether_open(cfe_devctx_t
*ctx
)
2059 sbeth_t
*softc
= ctx
->dev_softc
;
2061 softc
->sbe_devctx
= ctx
;
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
;
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.
2095 * ctx - device context (includes ptr to our softc)
2096 * buffer - pointer to buffer descriptor.
2100 ********************************************************************* */
2102 static int sb1250_ether_read(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
2104 sbeth_t
*softc
= ctx
->dev_softc
;
2108 if (softc
->sbe_state
!= sbeth_state_on
) return -1;
2112 if (softc
->sbe_rxqueue
== NULL
) {
2113 buffer
->buf_retlen
= 0;
2117 pkt
= softc
->sbe_rxqueue
;
2118 softc
->sbe_rxqueue
= pkt
->next
;
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);
2134 /* *********************************************************************
2135 * SB1250_ETHER_INPSTAT(ctx,inpstat)
2137 * Check for received packets on the Ethernet device
2140 * ctx - device context (includes ptr to our softc)
2141 * inpstat - pointer to input status structure
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;
2154 inpstat
->inp_status
= (softc
->sbe_rxqueue
== NULL
) ? 0 : 1;
2159 /* *********************************************************************
2160 * SB1250_ETHER_WRITE(ctx,buffer)
2162 * Write a packet to the Ethernet device.
2165 * ctx - device context (includes ptr to our softc)
2166 * buffer - pointer to buffer descriptor.
2170 ********************************************************************* */
2171 static int sb1250_ether_write(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
2173 sbeth_t
*softc
= ctx
->dev_softc
;
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
);
2200 if (sbeth_transmit(softc
,0,pkt
->buffer
,pkt
->length
,pkt
) != 1) {
2201 sbeth_free_pkt(softc
,pkt
);
2202 return CFE_ERR_IOERR
;
2207 buffer
->buf_retlen
= blen
;
2212 /* *********************************************************************
2213 * SB1250_ETHER_IOCTL_LOOPBACK(s,loopback)
2215 * Set loopback modes
2218 * s - sbeth structure
2219 * loopback - loopback modes
2222 * 0 if ok, else error
2223 ********************************************************************* */
2225 static int sb1250_ether_ioctl_loopback(sbeth_t
*s
,int loopback
)
2227 unsigned int miireg
;
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
);
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
);
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
);
2263 s
->sbe_loopback
= loopback
;
2269 /* *********************************************************************
2270 * SB1250_ETHER_IOCTL_SPEED(s,speed)
2272 * Set speed forcibly via the IOCTL command
2275 * s - sbeth structure
2276 * speed - speed IOCTL setting
2279 * 0 if ok, else error
2280 ********************************************************************* */
2282 static int sb1250_ether_ioctl_speed(sbeth_t
*s
,int 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);
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
,
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
);
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
,
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
);
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
,
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
);
2353 s
->sbe_curspeed
= speed
;
2354 if (speed
!= ETHER_SPEED_AUTO
) s
->sbe_linkstat
= speed
;
2358 /* *********************************************************************
2359 * SB1250_ETHER_IOCTL_PACKETFIFO(s,mode)
2361 * Swtich to a packet fifo mode.
2365 * s - sbeth structure
2366 * mode - 8 or 16 bit packet fifo mode.
2369 * 0 if ok, else error
2370 ********************************************************************* */
2371 static int sb1250_ether_ioctl_packetfifo(sbeth_t
*s
, int mode
)
2377 cfg
= SBETH_READCSR(s
->sbe_maccfg
);
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
;
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
;
2428 cfg
&= ~(M_MAC_BYPASS_SEL
| M_MAC_BYPASS_16
| M_MAC_AP_STAT_EN
);
2429 cfg
|= M_MAC_AP_STAT_EN
;
2436 SBETH_WRITECSR(s
->sbe_maccfg
,cfg
);
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.
2448 * s - sbeth structure
2449 * mode - GMII style, Encoded, SOP flagged, or EOP flagged mode.
2452 * 0 if ok, else error
2453 ********************************************************************* */
2454 static int sb1250_ether_ioctl_strobesignal(sbeth_t
*s
, int mode
)
2458 cfg
= SBETH_READCSR(s
->sbe_maccfg
);
2461 case ETHER_STROBE_GMII
:
2462 cfg
&= ~(M_MAC_BYPASS_CFG
);
2463 cfg
|= V_MAC_BYPASS_CFG(K_MAC_BYPASS_GMII
);
2466 case ETHER_STROBE_ENCODED
:
2467 cfg
&= ~(M_MAC_BYPASS_CFG
);
2468 cfg
|= V_MAC_BYPASS_CFG(K_MAC_BYPASS_ENCODED
);
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
);
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
);
2485 SBETH_WRITECSR(s
->sbe_maccfg
,cfg
);
2490 /* *********************************************************************
2491 * SB1250_ETHER_IOCTL(ctx,buffer)
2493 * Do device-specific I/O control operations for the device
2496 * ctx - device context (includes ptr to our softc)
2497 * buffer - pointer to buffer descriptor.
2501 ********************************************************************* */
2502 static int sb1250_ether_ioctl(cfe_devctx_t
*ctx
,iocb_buffer_t
*buffer
)
2504 sbeth_t
*softc
= ctx
->dev_softc
;
2507 switch ((int)buffer
->buf_ioctlcmd
) {
2508 case IOCTL_ETHER_GETHWADDR
:
2509 memcpy(buffer
->buf_ptr
,softc
->sbe_hwaddr
,sizeof(softc
->sbe_hwaddr
));
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);
2520 case IOCTL_ETHER_GETSPEED
:
2521 mode
= (int *) buffer
->buf_ptr
;
2522 *mode
= softc
->sbe_curspeed
;
2525 case IOCTL_ETHER_SETSPEED
:
2526 mode
= (int *) buffer
->buf_ptr
;
2527 return sb1250_ether_ioctl_speed(softc
,*mode
);
2530 case IOCTL_ETHER_GETLINK
:
2531 mode
= (int *) buffer
->buf_ptr
;
2532 *mode
= softc
->sbe_linkstat
;
2535 case IOCTL_ETHER_GETLOOPBACK
:
2536 mode
= (int *) buffer
->buf_ptr
;
2537 *mode
= softc
->sbe_loopback
;
2540 case IOCTL_ETHER_SETLOOPBACK
:
2541 mode
= (int *) buffer
->buf_ptr
;
2542 return sb1250_ether_ioctl_loopback(softc
,*mode
);
2545 case IOCTL_ETHER_SETPACKETFIFO
:
2546 mode
= (int *) buffer
->buf_ptr
;
2547 return sb1250_ether_ioctl_packetfifo(softc
,*mode
);
2550 case IOCTL_ETHER_SETSTROBESIG
:
2551 mode
= (int *) buffer
->buf_ptr
;
2552 return sb1250_ether_ioctl_strobesignal(softc
,*mode
);
2562 /* *********************************************************************
2563 * SB1250_ETHER_CLOSE(ctx)
2565 * Close the Ethernet device.
2568 * ctx - device context (includes ptr to our softc)
2572 ********************************************************************* */
2573 static int sb1250_ether_close(cfe_devctx_t
*ctx
)
2575 sbeth_t
*softc
= ctx
->dev_softc
;
2579 /* Reprogram the default hardware address in case someone mucked with it */
2580 sbeth_setaddr(softc
,softc
->sbe_hwaddr
);
2586 /* *********************************************************************
2587 * SB1250_ETHER_POLL(ctx,ticks)
2589 * Check for changes in the PHY, so we can track speed changes.
2592 * ctx - device context (includes ptr to our softc)
2593 * ticks- current time in ticks
2597 ********************************************************************* */
2599 static void sb1250_ether_poll(cfe_devctx_t
*ctx
,int64_t ticks
)
2601 sbeth_t
*softc
= ctx
->dev_softc
;
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
);
2609 if (softc
->sbe_state
== sbeth_state_on
) {
2610 TIMER_CLEAR(softc
->sbe_linkstat_timer
);
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.
2628 * softc - pointer to sbmac_t
2632 ********************************************************************* */
2634 static void sb1250_ether_reset(void *softc
)
2636 sbeth_t
*s
= (sbeth_t
*) softc
;
2638 uint64_t regval
= 0;
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));
2662 * Write to the port.
2665 port
= SBETH_PORT(s
->sbe_baseaddr
+ R_MAC_ETHERNET_ADDR
);
2666 SBETH_WRITECSR(port
,regval
);