1/*  *********************************************************************
2    *  SB1250_ETHERNET
3    *
4    *  CFE Ethernet Driver		File: DEV_SB1250_ETHERNET.C
5    *
6    *  Author:  Mitch Lichtenberg
7    *
8    *  This is the console monitor Ethernet driver for the SB1250
9    *
10    *********************************************************************
11    *
12    *  Copyright 2000,2001,2002,2003
13    *  Broadcom Corporation. All rights reserved.
14    *
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.
21    *
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.
25    *
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.
31    *
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    ********************************************************************* */
46
47#undef SIBYTE_HDR_FEATURES	/* we want all constants here */
48
49#include "cfe.h"
50#include "sbmips.h"
51
52#include "env_subr.h"
53
54#include "net_enet.h"
55
56#include "sb1250_defs.h"
57#include "sb1250_regs.h"
58#include "sb1250_mac.h"
59#include "sb1250_dma.h"
60#include "mii.h"
61
62/*  *********************************************************************
63    *  Simple types
64    ********************************************************************* */
65
66#ifdef __long64
67typedef volatile uint64_t sbeth_port_t;
68typedef uint64_t sbeth_physaddr_t;
69#define SBETH_PORT(x) PHYS_TO_K1(x)
70#else
71typedef volatile uint32_t sbeth_port_t;
72typedef uint32_t sbeth_physaddr_t;
73#define SBETH_PORT(x) PHYS_TO_K1(x)
74#endif
75
76#define SBETH_READCSR(t) (*((volatile uint64_t *) (t)))
77#define SBETH_WRITECSR(t,v) *((volatile uint64_t *) (t)) = (v)
78
79#define SBETH_MAX_TXDESCR	8
80#define SBETH_MAX_RXDESCR	8
81#define SBETH_MIN_RCV_RING	4
82#define SBETH_PKTPOOL_SIZE	16
83#define SBETH_DMA_CHANNELS	1
84#define SBETH_PKT_SIZE	        (ENET_MAX_PKT+ENET_CRC_SIZE)
85#define SBETH_PKTBUF_SIZE	2048
86
87#if CFG_L2_RAM
88#define SBETH_VTOP(x) ((sbeth_physaddr_t)0xD0000000 + (sbeth_physaddr_t)(x))
89#else
90#define SBETH_VTOP(x) (K1_TO_PHYS((sbeth_physaddr_t)(x)))
91#endif
92
93
94typedef enum { sbeth_speed_10, sbeth_speed_100,
95	       sbeth_speed_1000 } sbeth_speed_t;
96
97typedef enum { sbeth_duplex_half,
98	       sbeth_duplex_full } sbeth_duplex_t;
99
100typedef enum { sbeth_fc_disabled, sbeth_fc_frame,
101	       sbeth_fc_collision, sbeth_fc_carrier } sbeth_fc_t;
102
103typedef enum { sbeth_state_uninit, sbeth_state_off, sbeth_state_on,
104	       sbeth_state_broken } sbeth_state_t;
105
106typedef uint64_t  sbeth_enetaddr_t;
107
108typedef struct sbeth_s sbeth_t;		/* forward reference */
109
110static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed);
111static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc);
112static int sb1250_ether_ioctl_speed(sbeth_t *s,int speed);
113
114#define SBETH_MIIPOLL_TIMER	(4*CFE_HZ)
115
116/*  *********************************************************************
117    *  Descriptor structure
118    ********************************************************************* */
119
120typedef struct sbdmadscr_s {
121    uint64_t  dscr_a;
122    uint64_t  dscr_b;
123} sbdmadscr_t;
124
125/*  *********************************************************************
126    *  DMA structure
127    ********************************************************************* */
128
129typedef struct sbethdma_s {
130
131    /*
132     * This stuff is used to identify the channel and the registers
133     * associated with it.
134     */
135
136    sbeth_t         *sbdma_eth;	        /* back pointer to associated MAC */
137    int              sbdma_channel;	/* channel number */
138    int		     sbdma_txdir;       /* direction (1=transmit) */
139    int		     sbdma_maxdescr;	/* total # of descriptors in ring */
140    sbeth_port_t     sbdma_config0;	/* DMA config register 0 */
141    sbeth_port_t     sbdma_config1;	/* DMA config register 1 */
142    sbeth_port_t     sbdma_dscrbase;	/* Descriptor base address */
143    sbeth_port_t     sbdma_dscrcnt;     /* Descriptor count register */
144    sbeth_port_t     sbdma_curdscr;	/* current descriptor address */
145
146    /*
147     * This stuff is for maintenance of the ring
148     */
149
150    sbdmadscr_t     *sbdma_dscrtable;	/* base of descriptor table */
151    sbdmadscr_t     *sbdma_dscrtable_end; /* end of descriptor table */
152
153    void            **sbdma_ctxtable;   /* context table, one per descr */
154
155    int		     sbdma_onring;	/* count of packets on ring */
156
157    sbeth_physaddr_t sbdma_dscrtable_phys; /* and also the phys addr */
158    sbdmadscr_t     *sbdma_addptr;	/* next dscr for sw to add */
159    sbdmadscr_t     *sbdma_remptr;	/* next dscr for sw to remove */
160
161    void	   (*sbdma_upcall)(void *ifctx,int chan,void *ctx,
162				   uint64_t status,unsigned int length);
163} sbethdma_t;
164
165typedef struct sbeth_pkt_s {
166    struct sbeth_pkt_s *next;
167    void *devctx;
168    unsigned char *buffer;
169    int length;
170    /* packet data goes here */
171} sbeth_pkt_t;
172
173/*  *********************************************************************
174    *  Ethernet controller structure
175    ********************************************************************* */
176
177struct sbeth_s {
178    cfe_devctx_t    *sbe_devctx;
179    sbeth_port_t     sbe_baseaddr;	/* base address */
180
181    sbeth_state_t    sbe_state;         /* current state */
182
183    sbeth_port_t     sbe_macenable;	/* MAC Enable Register */
184    sbeth_port_t     sbe_maccfg;	/* MAC Configuration Register */
185    sbeth_port_t     sbe_fifocfg;	/* FIFO configuration register */
186    sbeth_port_t     sbe_framecfg;	/* Frame configuration register */
187    sbeth_port_t     sbe_rxfilter;	/* receive filter register */
188    sbeth_port_t     sbe_isr;		/* Interrupt status register */
189    sbeth_port_t     sbe_imr;		/* Interrupt mask register */
190    sbeth_port_t     sbe_mdio;		/* PHY control stuff */
191
192    sbeth_speed_t    sbe_speed;		/* current speed */
193    sbeth_duplex_t   sbe_duplex;	/* current duplex */
194    sbeth_fc_t       sbe_fc;		/* current flow control setting */
195    int		     sbe_rxflags;	/* received packet flags */
196    int		     sbe_autospeed;	/* true for automatic speed setting */
197    int		     sbe_curspeed;	/* value for GET SPEED ioctl */
198    int		     sbe_loopback;	/* IOCTL LOOPBACK stuff */
199    int		     sbe_linkstat;	/* Current link status */
200
201    sbethdma_t       sbe_txdma[SBETH_DMA_CHANNELS];	/* one for each channel */
202    sbethdma_t       sbe_rxdma[SBETH_DMA_CHANNELS];
203    void	    *sbe_ifctx;
204
205    int              sbe_minrxring;	/* min packets to keep on RX ring */
206
207    sbeth_pkt_t	    *sbe_rxqueue;	/* received packet queue */
208
209    sbeth_pkt_t     *sbe_freelist;	/* free packet list */
210
211    unsigned char   *sbe_pktpool;
212
213    unsigned char    sbe_hwaddr[ENET_ADDR_LEN];
214
215    int		     sbe_phyaddr;
216    uint32_t	     sbe_phyvendor;
217    uint32_t	     sbe_phydevice;
218    int		     sbe_zerormon;
219
220    uint32_t	     sbe_phy_oldbmsr;
221    uint32_t	     sbe_phy_oldbmcr;
222    uint32_t	     sbe_phy_oldanlpar;
223    uint32_t	     sbe_phy_oldk1stsr;
224
225    int64_t	     sbe_linkstat_timer;
226    int		     fifo_mode;		/* true if in packet fifo mode */
227
228};
229
230
231/*  *********************************************************************
232    *  Prototypes
233    ********************************************************************* */
234
235static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg);
236static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg);
237static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx);
238
239static void sbeth_start(sbeth_t *s);
240static void sbeth_stop(sbeth_t *s);
241
242static void sbeth_initfreelist(sbeth_t *s);
243static sbeth_pkt_t *sbeth_alloc_pkt(sbeth_t *s);
244static void sbeth_free_pkt(sbeth_t *s,sbeth_pkt_t *pkt);
245static void sbeth_tx_callback(void *ifctx,int chan,void *ctx,
246			      uint64_t status,unsigned int pktsize);
247static void sbeth_rx_callback(void *ifctx,int chan,void *ctx,
248			      uint64_t status,unsigned int pktsize);
249static void sbeth_fillrxring(sbeth_t *s,int chan);
250static void sb1250_ether_probe(cfe_driver_t *drv,
251			       unsigned long probe_a, unsigned long probe_b,
252			       void *probe_ptr);
253
254static void sbeth_setaddr(sbeth_t *s,uint8_t *addr);
255
256/*  *********************************************************************
257    *  Macros
258    ********************************************************************* */
259
260#define sbdma_nextbuf(d,f) ((((d)->f+1) == (d)->sbdma_dscrtable_end) ? \
261			  (d)->sbdma_dscrtable : (d)->f+1)
262
263#define SBDMA_CACHESIZE 32		/* wants to be somewhere else */
264#define SBDMA_NUMCACHEBLKS(x) ((x+SBDMA_CACHESIZE-1)/SBDMA_CACHESIZE)
265
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
276
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
282
283#define M_MAC_MDIO_DIR_OUTPUT	0		/* for clarity */
284
285
286/* ********************************************************************** */
287
288
289
290/*  *********************************************************************
291    *  SBETH_MII_SYNC(s)
292    *
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.
295    *
296    *  Input parameters:
297    *  	   s - sbmac structure
298    *
299    *  Return value:
300    *  	   nothing
301    ********************************************************************* */
302
303static void sbeth_mii_sync(sbeth_t *s)
304{
305    int cnt;
306    uint64_t bits;
307    int mac_mdio_genc;
308
309    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
310
311    bits = M_MAC_MDIO_DIR_OUTPUT | M_MAC_MDIO_OUT;
312
313    SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);
314
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);
318	}
319
320}
321
322/*  *********************************************************************
323    *  SBETH_MII_SENDDATA(s,data,bitcnt)
324    *
325    *  Send some bits to the MII.  The bits to be sent are right-
326    *  justified in the 'data' parameter.
327    *
328    *  Input parameters:
329    *  	   s - sbmac structure
330    *  	   data - data to send
331    *  	   bitcnt - number of bits to send
332    ********************************************************************* */
333
334static void sbeth_mii_senddata(sbeth_t *s,unsigned int data, int bitcnt)
335{
336    int i;
337    uint64_t bits;
338    unsigned int curmask;
339    int mac_mdio_genc;
340
341    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
342
343    bits = M_MAC_MDIO_DIR_OUTPUT;
344    SBETH_WRITECSR(s->sbe_mdio,bits | mac_mdio_genc);
345
346    curmask = 1 << (bitcnt - 1);
347
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;
355	}
356}
357
358
359
360/*  *********************************************************************
361    *  SBETH_MII_READ(s,phyaddr,regidx)
362    *
363    *  Read a PHY register.
364    *
365    *  Input parameters:
366    *  	   s - sbmac structure
367    *  	   phyaddr - PHY's address
368    *  	   regidx = index of register to read
369    *
370    *  Return value:
371    *  	   value read, or 0 if an error occured.
372    ********************************************************************* */
373
374static unsigned int sbeth_mii_read(sbeth_t *s,int phyaddr,int regidx)
375{
376    int idx;
377    int error;
378    int regval;
379    int mac_mdio_genc;
380
381    /*
382     * Synchronize ourselves so that the PHY knows the next
383     * thing coming down is a command
384     */
385
386    sbeth_mii_sync(s);
387
388    /*
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)
394     */
395
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);
400
401    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
402
403    /*
404     * Switch the port around without a clock transition.
405     */
406    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_INPUT | mac_mdio_genc);
407
408    /*
409     * Send out a clock pulse to signal we want the status
410     */
411
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);
414
415    /*
416     * If an error occured, the PHY will signal '1' back
417     */
418    error = SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN;
419
420    /*
421     * Issue an 'idle' clock pulse, but keep the direction
422     * the same.
423     */
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);
426
427    regval = 0;
428
429    for (idx = 0; idx < 16; idx++) {
430	regval <<= 1;
431
432	if (error == 0) {
433	    if (SBETH_READCSR(s->sbe_mdio) & M_MAC_MDIO_IN) regval |= 1;
434	    }
435
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);
438	}
439
440    /* Switch back to output */
441    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
442
443    if (error == 0) return regval;
444    return 0;
445}
446
447
448/*  *********************************************************************
449    *  SBETH_MII_WRITE(s,phyaddr,regidx,regval)
450    *
451    *  Write a value to a PHY register.
452    *
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
458    *
459    *  Return value:
460    *  	   nothing
461    ********************************************************************* */
462
463void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx,
464		     unsigned int regval);
465void sbeth_mii_write(sbeth_t *s,int phyaddr,int regidx,
466			    unsigned int regval)
467{
468    int mac_mdio_genc;
469
470    sbeth_mii_sync(s);
471
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);
478
479    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
480
481    SBETH_WRITECSR(s->sbe_mdio,M_MAC_MDIO_DIR_OUTPUT | mac_mdio_genc);
482}
483
484
485/*  *********************************************************************
486    *  SBETH_PHY_DUMP(s)
487    *
488    *  Dump out the MII registers
489    *
490    *  Input parameters:
491    *  	   s - sbeth structure
492    *      phy_addr - phy address
493    *      label - text for banner line
494    *
495    *  Return value:
496    *  	   nothing
497    ********************************************************************* */
498
499#if 0
500static void
501sbeth_phy_dump(sbeth_t *sc, unsigned int phy_addr, const char *label)
502{
503    int i;
504    uint16_t  r, r1;
505    uint16_t  id1, id2;
506    uint32_t  phy_vendor;
507    uint16_t  phy_device;
508
509    xprintf("%s, MII(%d):\n", label, phy_addr);
510
511    id1 = sbeth_mii_read(sc, phy_addr, MII_PHYIDR1);
512    id2 = sbeth_mii_read(sc, phy_addr, MII_PHYIDR2);
513    phy_vendor = ((uint32_t)id1 << 6) | ((id2 >> 10) & 0x3F);
514    phy_device = (id2 >> 4) & 0x3F;
515
516    /* Required registers */
517    for (i = 0x0; i <= 0x6; ++i) {
518	r = sbeth_mii_read(sc, phy_addr, i);
519	r1 = sbeth_mii_read(sc, phy_addr, i);
520	xprintf(" REG%02X: %04X", i, r);
521	if (r1 != r)
522	    xprintf("/%04X", r1);
523	if (i == 3 || i == 6)
524	    xprintf("\n");
525	}
526
527    /* GMII extensions */
528    for (i = 0x9; i <= 0xA; ++i) {
529	r = sbeth_mii_read(sc, phy_addr, i);
530	xprintf(" REG%02X: %04X", i, r);
531	}
532    r = sbeth_mii_read(sc, phy_addr, 0xF);
533    xprintf(" REG%02X: %04X\n", 0xF, r);
534
535    /* Broadcom extensions (54xx family) */
536    if (phy_vendor == OUI_BCM) {
537	for (i = 0x10; i <= 0x14; i++) {
538	    r = sbeth_mii_read(sc, phy_addr, i);
539	    xprintf(" REG%02X: %04X", i, r);
540	    }
541	xprintf("\n");
542	for (i = 0x18; i <= 0x1A; i++) {
543	    r = sbeth_mii_read(sc, phy_addr, i);
544	    xprintf(" REG%02X: %04X", i, r);
545	    }
546	xprintf("\n");
547
548	if (phy_device == DEV_BCM5461 || phy_device == DEV_BCM5464) {
549	    uint16_t shadow, shadow1;
550
551	    xprintf(" REG1C/\n");
552
553	    for (i = 0x18; i <= 0x1F; i++) {
554		shadow = (i << 10);
555		sbeth_mii_write(sc, phy_addr, 0x1C, shadow);
556		shadow = sbeth_mii_read(sc, phy_addr, 0x1C);
557		shadow1 = sbeth_mii_read(sc, phy_addr, 0x1C);
558		xprintf(" %02X: %04X", i, shadow);
559		if (shadow1 != shadow)
560		    xprintf("/%04X", shadow1);
561		if (i % 4 == 3) xprintf("\n");
562		}
563	    }
564	}
565}
566#else
567#define sbeth_phy_dump(sc,phy_addr,label)
568#endif
569
570
571/*  *********************************************************************
572    *  SBDMA_INITCHAN(s,d)
573    *
574    *  Initialize the DMA channel, programming the CSRs to the
575    *  values calculated in the SBDMA_INITCTX routine.
576    *
577    *  Input parameters:
578    *  	   s - sbeth structure
579    *  	   d - sbdma structure
580    *
581    *  Return value:
582    *  	   nothing
583    ********************************************************************* */
584static void sbdma_initchan(sbeth_t *s,
585			   sbethdma_t *d)
586{
587    /*
588     * Turn on the DMA channel
589     */
590
591    SBETH_WRITECSR(d->sbdma_config1,0);
592
593    SBETH_WRITECSR(d->sbdma_dscrbase,d->sbdma_dscrtable_phys);
594
595    SBETH_WRITECSR(d->sbdma_config0,
596		   V_DMA_RINGSZ(d->sbdma_maxdescr) |
597		   0);
598
599}
600
601/*  *********************************************************************
602    *  SBDMA_INITCTX(s,d,chan,txrx,maxdescr,callback)
603    *
604    *  Initialize a DMA channel context.  Since there are potentially
605    *  eight DMA channels per MAC, it's nice to do this in a standard
606    *  way.
607    *
608    *  Input parameters:
609    *  	   s - sbeth_t structure (pointer to a MAC)
610    *  	   d - sbethdma_t structure (DMA channel context)
611    *  	   chan - channel number (0..1 right now)
612    *  	   txrx - Identifies DMA_TX or DMA_RX for channel direction
613    *  	   maxdescr - number of descriptors to allocate for the ring
614    *
615    *  Return value:
616    *  	   nothing
617    ********************************************************************* */
618
619static void sbdma_initctx(sbeth_t *s,
620			  sbethdma_t *d,
621			  int chan,
622			  int txrx,
623			  int maxdescr,
624			  void (*callback)(void *,int,void *,uint64_t,unsigned int))
625{
626    /*
627     * Save away interesting stuff in the structure
628     */
629
630    d->sbdma_eth       = s;
631    d->sbdma_channel   = chan;
632    d->sbdma_txdir     = txrx;
633    d->sbdma_maxdescr  = maxdescr;
634
635    /*
636     * initialize register pointers
637     */
638
639    d->sbdma_config0 = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG0));
640    d->sbdma_config1 = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CONFIG1));
641    d->sbdma_dscrbase = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_BASE));
642    d->sbdma_dscrcnt = SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_DSCR_CNT));
643    d->sbdma_curdscr = 	SBETH_PORT(s->sbe_baseaddr + R_MAC_DMA_REGISTER(txrx,chan,R_MAC_DMA_CUR_DSCRADDR));
644
645    /*
646     * initialize the ring
647     */
648
649    d->sbdma_dscrtable = (sbdmadscr_t *)
650	KMALLOC(maxdescr*sizeof(sbdmadscr_t),sizeof(sbdmadscr_t));
651    d->sbdma_dscrtable_end = d->sbdma_dscrtable + maxdescr;
652
653    d->sbdma_dscrtable_phys = SBETH_VTOP(d->sbdma_dscrtable);
654    d->sbdma_addptr = d->sbdma_dscrtable;
655    d->sbdma_remptr = d->sbdma_dscrtable;
656
657    d->sbdma_ctxtable = (void **)
658	KMALLOC(maxdescr*sizeof(void *),sizeof(void *));
659
660    /*
661     * install callback
662     */
663
664    d->sbdma_upcall = callback;
665
666
667}
668
669
670
671/*  *********************************************************************
672    *  SBDMA_RESET(d)
673    *
674    *  Reset the software-maintained state for the specified
675    *  DMA channel.
676    *
677    *  Input parameters:
678    *  	   d - dma channel
679    *
680    *  Return value:
681    *  	   nothing
682    ********************************************************************* */
683
684static void sbdma_reset(sbethdma_t *d)
685{
686    d->sbdma_addptr = d->sbdma_dscrtable;
687    d->sbdma_remptr = d->sbdma_dscrtable;
688    d->sbdma_onring = 0;
689}
690
691/*  *********************************************************************
692    *  SBDMA_PROCBUFFERS(d,procfunc)
693    *
694    *  Process "completed" buffers on the specified DMA channel.
695    *  This is normally called within the interrupt service routine.
696    *  Note that this isn't really ideal for priority channels, since
697    *  it processes all of the packets on a given channel before
698    *  returning.
699    *
700    *  Input parameters:
701    *  	   d - DMA channel context
702    *  	   procfunc - routine to call for each completed buffer.  This
703    *  	              is called with the context for the completed buffer,
704    *  	              the status from the descriptor, and the length from
705    *  	              the descriptor.
706    *
707    *  Return value:
708    *  	   number of packets processed.
709    ********************************************************************* */
710
711static int sbdma_procbuffers(sbethdma_t *d,
712			     void (*procfunc)(void *ifctx,int chan,void *ctx,
713					      uint64_t status,
714					      unsigned int pktlen))
715{
716    int curidx;
717    int hwidx;
718    int count = 0;
719    sbdmadscr_t *dsc;
720
721    for (;;) {
722	/*
723	 * figure out where we are (as an index) and where
724	 * the hardware is (also as an index)
725	 *
726	 * This could be done faster if (for example) the
727	 * descriptor table was page-aligned and contiguous in
728	 * both virtual and physical memory -- you could then
729	 * just compare the low-order bits of the virtual address
730	 * (sbdma_remptr) and the physical address (sbdma_curdscr CSR)
731	 */
732
733	curidx = d->sbdma_remptr - d->sbdma_dscrtable;
734	{
735	    uint64_t tmp;
736	    tmp = SBETH_READCSR(d->sbdma_curdscr);
737	    if (!tmp) {
738	        break;
739	        }
740	    hwidx = (int) (((tmp & M_DMA_CURDSCR_ADDR) -
741				d->sbdma_dscrtable_phys) / sizeof(sbdmadscr_t));
742	}
743
744	/*
745	 * If they're the same, that means we've processed all
746	 * of the descriptors up to (but not including) the one that
747	 * the hardware is working on right now.
748	 */
749
750	if (curidx == hwidx) break;
751
752	/*
753	 * Remove packet from the on-ring count.
754	 */
755
756	d->sbdma_onring--;
757
758	/*
759	 * Otherwise, issue the upcall.
760	 */
761
762	dsc = &(d->sbdma_dscrtable[curidx]);
763	(*procfunc)(d->sbdma_eth->sbe_ifctx,
764		    d->sbdma_channel,
765		    d->sbdma_ctxtable[curidx],
766		    dsc->dscr_a & M_DMA_DSCRA_STATUS,
767		    (int)G_DMA_DSCRB_PKT_SIZE(dsc->dscr_b));
768	count++;
769
770	/*
771	 * .. and advance to the next buffer.
772	 */
773
774	d->sbdma_remptr = sbdma_nextbuf(d,sbdma_remptr);
775
776	}
777
778    return count;
779}
780
781/*  *********************************************************************
782    *  SBDMA_ADDBUFFER(d,ptr,length,ctx)
783    *
784    *  Add a buffer to the specified DMA channel.  For transmit channels,
785    *  this causes a transmission to start.  For receive channels,
786    *  this queues a buffer for inbound packets.
787    *
788    *  Input parameters:
789    *  	   d - DMA channel descriptor
790    *  	   ptr - pointer to buffer (must by physically contiguous)
791    *  	   length - length of buffer
792    *  	   ctx - arbitrary data to be passed back when descriptor completes
793    *  	         (for example, mbuf pointers, etc.)
794    *
795    *  Return value:
796    *  	   0 if buffer could not be added (ring is full)
797    *  	   1 if buffer added successfully
798    ********************************************************************* */
799
800static int sbdma_addbuffer(sbethdma_t *d,uint8_t *ptr,int length,void *ctx)
801{
802    sbdmadscr_t *dsc;
803    sbdmadscr_t *nextdsc;
804
805    sbeth_t         *s = d->sbdma_eth;
806
807    /* get pointer to our current place in the ring */
808    dsc = d->sbdma_addptr;
809    nextdsc = sbdma_nextbuf(d,sbdma_addptr);
810
811    /*
812     * figure out if the ring is full - if the next descriptor
813     * is the same as the one that we're going to remove from
814     * the ring, the ring is full
815     */
816
817    if (nextdsc == d->sbdma_remptr) {
818	return 0;
819	}
820
821    /*
822     * fill in the descriptor
823     */
824
825    if (d->sbdma_txdir) {
826	/* transmitting: set outbound options and length */
827	dsc->dscr_a = SBETH_VTOP(ptr) |
828	    V_DMA_DSCRA_A_SIZE(SBDMA_NUMCACHEBLKS(((uint64_t) length))) |
829	    M_DMA_DSCRA_INTERRUPT |
830	    M_DMA_ETHTX_SOP;
831
832	if (s->fifo_mode) {
833	    dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_NOMODS) |
834		V_DMA_DSCRB_PKT_SIZE(length);
835	    }
836	else {
837	    dsc->dscr_b = V_DMA_DSCRB_OPTIONS(K_DMA_ETHTX_APPENDCRC_APPENDPAD) |
838		V_DMA_DSCRB_PKT_SIZE(length);
839	    }
840
841	}
842    else {
843	/* receiving: no options */
844	dsc->dscr_a = SBETH_VTOP(ptr) |
845	    V_DMA_DSCRA_A_SIZE(SBDMA_NUMCACHEBLKS(((uint64_t) length))) |
846	    M_DMA_DSCRA_INTERRUPT;
847	dsc->dscr_b = 0;
848	}
849
850    /*
851     * fill in the context
852     */
853
854    d->sbdma_ctxtable[dsc-d->sbdma_dscrtable] = ctx;
855
856    /*
857     * point at next packet
858     */
859
860    d->sbdma_addptr = nextdsc;
861
862    /*
863     * Give the packet to the hardware
864     */
865
866    d->sbdma_onring++;
867    SBETH_WRITECSR(d->sbdma_dscrcnt,1);
868
869    return 1;					/* we did it */
870}
871
872
873/*  *********************************************************************
874    *  SBETH_INITFREELIST(s)
875    *
876    *  Initialize the buffer free list for this mac.  The memory
877    *  allocated to the free list is carved up and placed on a linked
878    *  list of buffers for use by the mac.
879    *
880    *  Input parameters:
881    *  	   s - sbeth structure
882    *
883    *  Return value:
884    *  	   nothing
885    ********************************************************************* */
886
887static void sbeth_initfreelist(sbeth_t *s)
888{
889    int idx;
890    unsigned char *ptr;
891    sbeth_pkt_t *pkt;
892
893    s->sbe_freelist = NULL;
894
895    /* Must empty rxqueue, as we're about to free all the pkts on it */
896    s->sbe_rxqueue = NULL;
897
898    ptr = s->sbe_pktpool;
899
900    for (idx = 0; idx < SBETH_PKTPOOL_SIZE; idx++) {
901	pkt = (sbeth_pkt_t *) ptr;
902	sbeth_free_pkt(s,pkt);
903	ptr += SBETH_PKTBUF_SIZE;
904	}
905}
906
907
908/*  *********************************************************************
909    *  SBETH_ALLOC_PKT(s)
910    *
911    *  Allocate a packet from the free list.
912    *
913    *  Input parameters:
914    *  	   s - sbeth structure
915    *
916    *  Return value:
917    *  	   pointer to packet structure, or NULL if none available
918    ********************************************************************* */
919
920static sbeth_pkt_t *sbeth_alloc_pkt(sbeth_t *s)
921{
922    uintptr_t addr;
923    sbeth_pkt_t *pkt = s->sbe_freelist;
924
925    if (!pkt) return NULL;
926
927    s->sbe_freelist = pkt->next;
928    pkt->next = NULL;
929
930    addr = (uintptr_t) (pkt+1);
931    if (addr & (SBDMA_CACHESIZE-1)) {
932	addr = (addr + SBDMA_CACHESIZE) & ~(SBDMA_CACHESIZE-1);
933	}
934
935    pkt->buffer = (unsigned char *) addr;
936    pkt->length = SBETH_PKT_SIZE;
937
938    return pkt;
939}
940
941/*  *********************************************************************
942    *  SBETH_FREE_PKT(s,pkt)
943    *
944    *  Return a packet to the free list
945    *
946    *  Input parameters:
947    *  	   s - sbmac structure
948    *  	   pkt - packet to return
949    *
950    *  Return value:
951    *  	   nothing
952    ********************************************************************* */
953static void sbeth_free_pkt(sbeth_t *s,sbeth_pkt_t *pkt)
954{
955    pkt->next = s->sbe_freelist;
956    s->sbe_freelist = pkt;
957}
958
959/*  *********************************************************************
960    *  SBETH_TX_CALLBACK(ifctx,chan,ctx,status,pktsize)
961    *
962    *  Transmit callback routine.  This routine is invoked when a
963    *  queued transmit operation completes.  In this simple driver,
964    *  all we do is free the packet and try to re-fill the receive ring.
965    *
966    *  Input parameters:
967    *  	   ifctx - interface context (sbeth structure)
968    *  	   chan - DMA Channel
969    *  	   ctx - packet context (sbeth_pkt structure)
970    *  	   status - Ethernet status from descriptor
971    *  	   pktsize - length of packet (unused for transmits)
972    *
973    *  Return value:
974    *  	   nothing
975    ********************************************************************* */
976
977static void sbeth_tx_callback(void *ifctx,int chan,void *ctx,
978		       uint64_t status,unsigned int pktsize)
979{
980    sbeth_t *s = ifctx;
981    sbeth_pkt_t *pkt = ctx;
982
983    sbeth_free_pkt(s,pkt);		/* return packet to pool */
984
985    sbeth_fillrxring(s,chan);		/* re-fill the receive ring */
986}
987
988/*  *********************************************************************
989    *  SBETH_RX_CALLBACK(ifctx,chan,ctx,status,pktsize)
990    *
991    *  Receive callback routine.  This routine is invoked when a
992    *  buffer queued for receives is filled. In this simple driver,
993    *  all we do is add the packet to a per-MAC queue for later
994    *  processing, and try to put a new packet in the place of the one
995    *  that was removed from the queue.
996    *
997    *  Input parameters:
998    *  	   ifctx - interface context (sbeth structure)
999    *  	   chan - DMA Channel
1000    *  	   ctx - packet context (sbeth_pkt structure)
1001    *  	   status - Ethernet status from descriptor
1002    *  	   pktsize - length of packet (unused for transmits)
1003    *
1004    *  Return value:
1005    *  	   nothing
1006    ********************************************************************* */
1007static void sbeth_rx_callback(void *ifctx,int chan,void *ctx,
1008		       uint64_t status,unsigned int pktsize)
1009{
1010    sbeth_t *s = ifctx;
1011    sbeth_pkt_t *pkt = ctx;
1012    sbeth_pkt_t *listptr;
1013
1014    if (!(status & M_DMA_ETHRX_BAD)) {
1015	pkt->next = NULL;
1016	pkt->length = pktsize;
1017
1018	if (s->sbe_rxqueue == NULL) {
1019	    s->sbe_rxqueue = pkt;
1020	    }
1021	else {
1022	    listptr = s->sbe_rxqueue;
1023	    while (listptr->next) listptr = listptr->next;
1024	    listptr->next = pkt;
1025	    }
1026	}
1027    else {
1028	sbeth_free_pkt(s,pkt);
1029	}
1030
1031    sbeth_fillrxring(s,chan);
1032}
1033
1034
1035/*  *********************************************************************
1036    *  SBETH_INITCHAN(s)
1037    *
1038    *  Initialize the Ethernet channel (program the CSRs to
1039    *  get the channel set up)
1040    *
1041    *  Input parameters:
1042    *  	   s - sbeth structure
1043    *
1044    *  Return value:
1045    *  	   nothing
1046    ********************************************************************* */
1047
1048static void sbeth_initchan(sbeth_t *s)
1049{
1050    sbeth_port_t port;
1051    int idx;
1052    uint64_t cfg,fifo,framecfg;
1053
1054    /*
1055     * Bring the controller out of reset, and set the "must be one"
1056     * bits.
1057     */
1058
1059    SBETH_WRITECSR(s->sbe_macenable,0);
1060
1061    /*
1062     * Set up some stuff in the control registers, but do not
1063     * enable the channel
1064     */
1065
1066    cfg = M_MAC_RETRY_EN |
1067	M_MAC_TX_HOLD_SOP_EN |
1068	V_MAC_TX_PAUSE_CNT_16K |
1069	V_MAC_SPEED_SEL_100MBPS |
1070	M_MAC_AP_STAT_EN |
1071	M_MAC_FAST_SYNC |
1072	M_MAC_SS_EN |
1073	0;
1074
1075    fifo = V_MAC_TX_WR_THRSH(4) |	/* Must be '4' or '8' */
1076	   V_MAC_TX_RD_THRSH(8) |
1077	   V_MAC_TX_RL_THRSH(4) |
1078	   V_MAC_RX_PL_THRSH(4) |
1079	   V_MAC_RX_RD_THRSH(4) |	/* Must be '4' */
1080	   V_MAC_RX_PL_THRSH(4) |
1081    	   V_MAC_RX_RL_THRSH(8) |
1082	   0;
1083
1084    framecfg = V_MAC_MIN_FRAMESZ_DEFAULT |
1085	V_MAC_MAX_FRAMESZ_DEFAULT |
1086	V_MAC_BACKOFF_SEL(1);
1087
1088    /*
1089     * Clear out the hash address map
1090     */
1091
1092    port = SBETH_PORT(s->sbe_baseaddr + R_MAC_HASH_BASE);
1093        for (idx = 0; idx < MAC_HASH_COUNT; idx++) {
1094	SBETH_WRITECSR(port,0);
1095	port += sizeof(uint64_t);
1096	}
1097
1098    /*
1099     * Clear out the exact-match table
1100     */
1101
1102    port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE);
1103    for (idx = 0; idx < MAC_ADDR_COUNT; idx++) {
1104	SBETH_WRITECSR(port,0);
1105	port += sizeof(uint64_t);
1106	}
1107
1108    /*
1109     * Clear out the DMA Channel mapping table registers
1110     */
1111
1112    port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHUP0_BASE);
1113    for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
1114	SBETH_WRITECSR(port,0);
1115	port += sizeof(uint64_t);
1116	}
1117
1118    port = SBETH_PORT(s->sbe_baseaddr + R_MAC_CHLO0_BASE);
1119    for (idx = 0; idx < MAC_CHMAP_COUNT; idx++) {
1120	SBETH_WRITECSR(port,0);
1121	port += sizeof(uint64_t);
1122	}
1123
1124    if (!s->sbe_zerormon) {
1125	s->sbe_zerormon =1;
1126	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BYTES),0);
1127	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_COLLISIONS),0);
1128	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_LATE_COL),0);
1129	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_EX_COL),0);
1130	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_FCS_ERROR),0);
1131	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_ABORT),0);
1132	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_BAD),0);
1133	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_GOOD),0);
1134	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_RUNT),0);
1135	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_TX_OVERSIZE),0);
1136	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BYTES),0);
1137	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_MCAST),0);
1138	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BCAST),0);
1139	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_BAD),0);
1140	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_GOOD),0);
1141	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_RUNT),0);
1142	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_OVERSIZE),0);
1143	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_FCS_ERROR),0);
1144	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_LENGTH_ERROR),0);
1145	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_CODE_ERROR),0);
1146	SBETH_WRITECSR(SBETH_PORT(s->sbe_baseaddr+R_MAC_RMON_RX_ALIGN_ERROR),0);
1147	}
1148
1149    /*
1150     * Configure the receive filter for no packets
1151     */
1152
1153    SBETH_WRITECSR(s->sbe_rxfilter,0);
1154    SBETH_WRITECSR(s->sbe_imr,0);
1155    SBETH_WRITECSR(s->sbe_framecfg,framecfg);
1156    SBETH_WRITECSR(s->sbe_fifocfg,fifo);
1157    SBETH_WRITECSR(s->sbe_maccfg,cfg);
1158
1159}
1160
1161/*  *********************************************************************
1162    *  SBETH_INITCTX(s,mac)
1163    *
1164    *  Initialize an Ethernet context structure - this is called
1165    *  once per MAC on the 1250.
1166    *
1167    *  Input parameters:
1168    *  	   s - sbeth context structure
1169    *  	   mac - number of this MAC (0,1,2)
1170    *      ifctx - interface context (reference saved by driver)
1171    *
1172    *  Return value:
1173    *  	   0
1174    ********************************************************************* */
1175static int sbeth_initctx(sbeth_t *s,unsigned long baseaddr,void *ifctx)
1176{
1177
1178    /*
1179     * Start with all zeroes
1180     */
1181    memset(s,0,sizeof(sbeth_t));
1182
1183    /*
1184     * Identify ourselves
1185     */
1186
1187    s->sbe_baseaddr = baseaddr;
1188    s->sbe_ifctx   = ifctx;
1189
1190    s->sbe_minrxring = 8;
1191
1192    /*
1193     * Set default hardware address.  This is in case there is *no* environment.
1194     */
1195
1196    s->sbe_hwaddr[0] = 0x02;
1197    s->sbe_hwaddr[1] = 0x10;
1198    s->sbe_hwaddr[2] = 0x18;
1199    s->sbe_hwaddr[3] = (s->sbe_baseaddr >> 24) & 0xFF;
1200    s->sbe_hwaddr[4] = (s->sbe_baseaddr >> 16) & 0xFF;
1201    s->sbe_hwaddr[5] = (s->sbe_baseaddr >>  8) & 0xFF;
1202
1203    /*
1204     * figure out the addresses of some ports
1205     */
1206    s->sbe_macenable = SBETH_PORT(s->sbe_baseaddr + R_MAC_ENABLE);
1207    s->sbe_maccfg    = SBETH_PORT(s->sbe_baseaddr + R_MAC_CFG);
1208    s->sbe_fifocfg   = SBETH_PORT(s->sbe_baseaddr + R_MAC_THRSH_CFG);
1209    s->sbe_framecfg  = SBETH_PORT(s->sbe_baseaddr + R_MAC_FRAMECFG);
1210    s->sbe_rxfilter  = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADFILTER_CFG);
1211
1212    s->sbe_isr = SBETH_PORT(s->sbe_baseaddr + R_MAC_STATUS);
1213    s->sbe_imr = SBETH_PORT(s->sbe_baseaddr + R_MAC_INT_MASK);
1214
1215    s->sbe_mdio = SBETH_PORT(s->sbe_baseaddr + R_MAC_MDIO);
1216
1217    /*
1218     * Initialize the DMA channels.
1219     */
1220
1221    sbdma_initctx(s,&(s->sbe_txdma[0]),0,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback);
1222    sbdma_initctx(s,&(s->sbe_rxdma[0]),0,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback);
1223#if (SBETH_DMA_CHANNELS == 2)
1224    sbdma_initctx(s,&(s->sbe_txdma[1]),1,DMA_TX,SBETH_MAX_TXDESCR,sbeth_tx_callback);
1225    sbdma_initctx(s,&(s->sbe_rxdma[1]),1,DMA_RX,SBETH_MAX_RXDESCR,sbeth_rx_callback);
1226#endif
1227
1228    /*
1229     * initialize free list
1230     */
1231
1232    s->sbe_freelist = NULL;
1233    s->sbe_rxqueue = NULL;
1234
1235    s->sbe_pktpool = KMALLOC(SBETH_PKTBUF_SIZE*SBETH_PKTPOOL_SIZE,
1236			     SBDMA_CACHESIZE);
1237
1238    /*
1239     * Set values for the PHY so that when we poll the phy status
1240     * we'll notice that it has changed.
1241     */
1242
1243    s->sbe_phy_oldbmsr   = 0xFFFFFFFF;
1244    s->sbe_phy_oldbmcr   = 0xFFFFFFFF;
1245    s->sbe_phy_oldanlpar = 0xFFFFFFFF;
1246    s->sbe_phy_oldk1stsr = 0xFFFFFFFF;
1247
1248    /*
1249     * initial state is OFF
1250     */
1251
1252    s->sbe_state = sbeth_state_off;
1253
1254    return 0;
1255}
1256
1257
1258/*  *********************************************************************
1259    *  SBETH_START(s)
1260    *
1261    *  Start packet processing on this MAC.
1262    *
1263    *  Input parameters:
1264    *  	   s - sbeth structure
1265    *
1266    *  Return value:
1267    *  	   nothing
1268    ********************************************************************* */
1269
1270static void sbeth_start(sbeth_t *s)
1271{
1272    uint64_t ctl;
1273
1274    sbdma_initchan(s,&(s->sbe_txdma[0]));
1275    sbdma_initchan(s,&(s->sbe_rxdma[0]));
1276#if (SBETH_DMA_CHANNELS == 2)
1277    sbdma_initchan(s,&(s->sbe_txdma[1]));
1278    sbdma_initchan(s,&(s->sbe_rxdma[1]));
1279#endif
1280    sbeth_initchan(s);
1281
1282    sbeth_setspeed(s,s->sbe_speed);
1283    sbeth_set_duplex(s,s->sbe_duplex,s->sbe_fc);
1284
1285    SBETH_WRITECSR(s->sbe_rxfilter,0);
1286
1287    ctl = SBETH_READCSR(s->sbe_macenable);
1288
1289    ctl |= M_MAC_RXDMA_EN0 |
1290   	   M_MAC_TXDMA_EN0 |
1291#if (SBETH_DMA_CHANNELS == 2)
1292	   M_MAC_TXDMA_EN1 |
1293	   M_MAC_RXDMA_EN1 |
1294#endif
1295	   M_MAC_RX_ENABLE |
1296	   M_MAC_TX_ENABLE |
1297	0;
1298
1299    sbeth_initfreelist(s);
1300
1301    SBETH_WRITECSR(s->sbe_macenable,ctl);
1302
1303    sbeth_setaddr(s,s->sbe_hwaddr);
1304
1305#ifdef _SB1250_PASS1_WORKAROUNDS_
1306    /* Must set the Ethernet address to zero in pass1 */
1307    do {
1308	sbeth_port_t port;
1309	port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR);
1310	SBETH_WRITECSR(port,0);
1311	} while (0);
1312#endif
1313
1314    sbeth_fillrxring(s,0);
1315
1316    SBETH_WRITECSR(s->sbe_rxfilter,M_MAC_UCAST_EN | M_MAC_BCAST_EN |
1317	V_MAC_IPHDR_OFFSET(15) |
1318		   /* M_MAC_ALLPKT_EN |*/  /* uncomment for promisc mode */
1319	0
1320	);
1321
1322    s->sbe_state = sbeth_state_on;
1323
1324}
1325
1326/*  *********************************************************************
1327    *  SBETH_STOP(s)
1328    *
1329    *  Stop packet processing on this MAC.
1330    *
1331    *  Input parameters:
1332    *  	   s - sbeth structure
1333    *
1334    *  Return value:
1335    *  	   nothing
1336    ********************************************************************* */
1337
1338static void sbeth_stop(sbeth_t *s)
1339{
1340    uint64_t ctl;
1341    int mac_mdio_genc;
1342
1343    SBETH_WRITECSR(s->sbe_rxfilter,0);
1344
1345    ctl = SBETH_READCSR(s->sbe_macenable);
1346
1347    ctl &= ~(M_MAC_RXDMA_EN0 | M_MAC_TXDMA_EN0 | M_MAC_RXDMA_EN1 | M_MAC_TXDMA_EN1 |
1348	M_MAC_RX_ENABLE | M_MAC_TX_ENABLE);
1349
1350    SBETH_WRITECSR(s->sbe_macenable,ctl);
1351
1352    /*
1353     * The genc bit on the MAC MDIO register needs to be preserved through reset.
1354     * Read the MAC MDIO register and mask out genc bit.
1355     */
1356    mac_mdio_genc = SBETH_READCSR(s->sbe_mdio) & M_MAC_GENC;
1357
1358    ctl |= M_MAC_PORT_RESET;
1359
1360    SBETH_WRITECSR(s->sbe_macenable,ctl);
1361
1362    /* Write back value of genc bit */
1363    SBETH_WRITECSR(s->sbe_mdio,mac_mdio_genc);
1364
1365    s->sbe_state = sbeth_state_off;
1366
1367    sbdma_reset(&(s->sbe_txdma[0]));
1368    sbdma_reset(&(s->sbe_rxdma[0]));
1369
1370
1371}
1372
1373
1374/*  *********************************************************************
1375    *  SBETH_SETADDR(s,addr)
1376    *
1377    *  Set the ethernet address for the specified MAC
1378    *
1379    *  Input parameters:
1380    *  	   s - sbeth structure
1381    *  	   addr - Ethernet address
1382    *
1383    *  Return value:
1384    *  	   nothing
1385    ********************************************************************* */
1386
1387static void sbeth_setaddr(sbeth_t *s,uint8_t *addr)
1388{
1389    sbeth_port_t port;
1390    uint64_t regval = 0;
1391    int idx;
1392
1393    /*
1394     * Pack the bytes into the register, with the first byte transmitted
1395     * in the lowest-order 8 bits of the register.
1396     */
1397
1398    for (idx = 0; idx < 6; idx++) {
1399	regval |= (((uint64_t) (*addr)) << (idx*8));
1400	addr++;
1401	}
1402
1403    /*
1404     * Write to the port.
1405     */
1406
1407    port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR);
1408    SBETH_WRITECSR(port,regval);
1409
1410    port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ADDR_BASE);
1411    SBETH_WRITECSR(port,regval);
1412
1413}
1414
1415/*  *********************************************************************
1416    *  SBETH_SETSPEED(s,speed)
1417    *
1418    *  Configure LAN speed for the specified MAC
1419    *
1420    *  Input parameters:
1421    *  	   s - sbeth structure
1422    *  	   speed - speed to set MAC to (see sbeth_speed_t enum)
1423    *
1424    *  Return value:
1425    *  	   1 if successful
1426    *      0 indicates invalid parameters
1427    ********************************************************************* */
1428
1429static int sbeth_setspeed(sbeth_t *s,sbeth_speed_t speed)
1430{
1431    uint64_t cfg;
1432    uint64_t framecfg;
1433
1434    /*
1435     * Read current register values
1436     */
1437
1438    cfg = SBETH_READCSR(s->sbe_maccfg);
1439    framecfg = SBETH_READCSR(s->sbe_framecfg);
1440
1441    /*
1442     * Mask out the stuff we want to change
1443     */
1444
1445    cfg &= ~(M_MAC_BURST_EN | M_MAC_SPEED_SEL);
1446    framecfg &= ~(M_MAC_IFG_RX | M_MAC_IFG_TX | M_MAC_IFG_THRSH |
1447		  M_MAC_SLOT_SIZE);
1448
1449    /*
1450     * Now add in the new bits
1451     */
1452
1453    switch (speed) {
1454	case sbeth_speed_10:
1455	    framecfg |= V_MAC_IFG_RX_10 |
1456		V_MAC_IFG_TX_10 |
1457		K_MAC_IFG_THRSH_10 |
1458		V_MAC_SLOT_SIZE_10;
1459	    cfg |= V_MAC_SPEED_SEL_10MBPS;
1460	    break;
1461
1462	case sbeth_speed_100:
1463	    framecfg |= V_MAC_IFG_RX_100 |
1464		V_MAC_IFG_TX_100 |
1465		V_MAC_IFG_THRSH_100 |
1466		V_MAC_SLOT_SIZE_100;
1467	    cfg |= V_MAC_SPEED_SEL_100MBPS ;
1468	    break;
1469
1470	case sbeth_speed_1000:
1471	    framecfg |= V_MAC_IFG_RX_1000 |
1472		V_MAC_IFG_TX_1000 |
1473		V_MAC_IFG_THRSH_1000 |
1474		V_MAC_SLOT_SIZE_1000;
1475	    cfg |= V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
1476	    break;
1477
1478	default:
1479	    return 0;
1480	}
1481
1482    /*
1483     * Send the bits back to the hardware
1484     */
1485
1486    SBETH_WRITECSR(s->sbe_framecfg,framecfg);
1487    SBETH_WRITECSR(s->sbe_maccfg,cfg);
1488
1489    return 1;
1490
1491}
1492
1493/*  *********************************************************************
1494    *  SBETH_SET_DUPLEX(s,duplex,fc)
1495    *
1496    *  Set Ethernet duplex and flow control options for this MAC
1497    *
1498    *  Input parameters:
1499    *  	   s - sbeth structure
1500    *  	   duplex - duplex setting (see sbeth_duplex_t)
1501    *  	   fc - flow control setting (see sbeth_fc_t)
1502    *
1503    *  Return value:
1504    *  	   1 if ok
1505    *  	   0 if an invalid parameter combination was specified
1506    ********************************************************************* */
1507
1508static int sbeth_set_duplex(sbeth_t *s,sbeth_duplex_t duplex,sbeth_fc_t fc)
1509{
1510    uint64_t cfg;
1511
1512    /*
1513     * Read current register values
1514     */
1515
1516    cfg = SBETH_READCSR(s->sbe_maccfg);
1517
1518    /*
1519     * Mask off the stuff we're about to change
1520     */
1521
1522    cfg &= ~(M_MAC_FC_SEL | M_MAC_FC_CMD | M_MAC_HDX_EN);
1523
1524    switch (duplex) {
1525	case sbeth_duplex_half:
1526	    switch (fc) {
1527		case sbeth_fc_disabled:
1528		    cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_DISABLED;
1529		    break;
1530
1531		case sbeth_fc_collision:
1532		    cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENABLED;
1533		    break;
1534
1535		case sbeth_fc_carrier:
1536		    cfg |= M_MAC_HDX_EN | V_MAC_FC_CMD_ENAB_FALSECARR;
1537		    break;
1538
1539		case sbeth_fc_frame:		/* not valid in half duplex */
1540		default:			/* invalid selection */
1541		    return 0;
1542		}
1543	    break;
1544
1545	case sbeth_duplex_full:
1546	    switch (fc) {
1547		case sbeth_fc_disabled:
1548		    cfg |= V_MAC_FC_CMD_DISABLED;
1549		    break;
1550
1551		case sbeth_fc_frame:
1552		    cfg |=  V_MAC_FC_CMD_ENABLED;
1553		    break;
1554
1555		case sbeth_fc_collision:	/* not valid in full duplex */
1556		case sbeth_fc_carrier:		/* not valid in full duplex */
1557		    /* fall through */
1558		default:
1559		    return 0;
1560		}
1561	    break;
1562	}
1563
1564    /*
1565     * Send the bits back to the hardware
1566     */
1567
1568    SBETH_WRITECSR(s->sbe_maccfg,cfg);
1569
1570    return 1;
1571}
1572
1573
1574/*  *********************************************************************
1575    *  SBETH_TRANSMIT(s,pkt,len,arg)
1576    *
1577    *  Transmits a packet.
1578    *
1579    *  Input parameters:
1580    *  	   s - mac to tramsmit on
1581    *      chan - DMA Channel number (0 or 1)
1582    *  	   pkt,len - buffer and length
1583    *  	   arg - arg for callback
1584    *
1585    *  Return value:
1586    *  	   1 if packet was queued
1587    *  	   0 if packet was not queued
1588    ********************************************************************* */
1589static int sbeth_transmit(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg)
1590{
1591    return sbdma_addbuffer(&(s->sbe_txdma[chan]),pkt,length,arg);
1592}
1593
1594/*  *********************************************************************
1595    *  SBETH_ADDRCVBUF(s,pkt,len,arg)
1596    *
1597    *  Add a receive buffer to the ring
1598    *
1599    *  Input parameters:
1600    *  	   s - mac to add rx buffer to
1601    *      chan - DMA Channel number (0 or 1)
1602    *  	   pkt,len - buffer and length
1603    *  	   arg - arg for callback
1604    *
1605    *  Return value:
1606    *  	   1 if packet was queued
1607    *  	   0 if packet was not queued
1608    ********************************************************************* */
1609static int sbeth_addrcvbuf(sbeth_t *s,int chan,unsigned char *pkt,int length,void *arg)
1610{
1611    return sbdma_addbuffer(&(s->sbe_rxdma[chan]),pkt,length,arg);
1612}
1613
1614
1615/*  *********************************************************************
1616    *  SBETH_FILLRXRING(s,chan)
1617    *
1618    *  Make sure there are at least "sbe_minrxring" packets on the
1619    *  receive ring for this device.
1620    *
1621    *  Input parameters:
1622    *  	   s - mac structure
1623    *
1624    *  Return value:
1625    *  	   nothing
1626    ********************************************************************* */
1627
1628static void sbeth_fillrxring(sbeth_t *s,int chan)
1629{
1630    sbeth_pkt_t *pkt;
1631
1632    while (s->sbe_rxdma[chan].sbdma_onring < s->sbe_minrxring) {
1633	pkt = sbeth_alloc_pkt(s);
1634	if (!pkt) break;
1635	if (!sbeth_addrcvbuf(s,chan,pkt->buffer,pkt->length,pkt)) {
1636	    sbeth_free_pkt(s,pkt);
1637	    break;
1638	    }
1639	}
1640}
1641
1642
1643
1644/*  *********************************************************************
1645    *  SBETH_ISR()
1646    *
1647    *  Interrupt handler for MAC interrupts
1648    *
1649    *  Input parameters:
1650    *  	   MAC structure
1651    *
1652    *  Return value:
1653    *  	   nothing
1654    ********************************************************************* */
1655static void sbeth_isr(sbeth_t *s)
1656{
1657    uint64_t isr;
1658    for (;;) {
1659
1660	/*
1661	 * Read the ISR (this clears the bits in the real register)
1662	 */
1663
1664	isr = SBETH_READCSR(s->sbe_isr);
1665
1666	if (isr == 0)  {
1667		break;
1668	}
1669
1670	/*
1671	 * for now, don't bother asking why we were interrupted,
1672	 * just process the descriptors in any event.
1673	 */
1674
1675	/*
1676	 * Transmits on channel 0
1677	 */
1678
1679	if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH0)) {
1680	    sbdma_procbuffers(&(s->sbe_txdma[0]),s->sbe_txdma[0].sbdma_upcall);
1681	}
1682
1683#if (SBETH_DMA_CHANNELS == 2)
1684	/*
1685	 * Transmits on channel 1
1686	 */
1687
1688	if (isr & (M_MAC_INT_CHANNEL << S_MAC_TX_CH1)) {
1689	    sbdma_procbuffers(&(s->sbe_txdma[1]),s->sbe_txdma[1].sbdma_upcall);
1690	    }
1691#endif
1692
1693	/*
1694	 * Receives on channel 0
1695	 */
1696
1697	if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH0)) {
1698	    sbdma_procbuffers(&(s->sbe_rxdma[0]),s->sbe_rxdma[0].sbdma_upcall);
1699	    }
1700
1701#if (SBETH_DMA_CHANNELS == 2)
1702	/*
1703	 * Receives on channel 1
1704	 */
1705
1706	if (isr & (M_MAC_INT_CHANNEL << S_MAC_RX_CH1)) {
1707            sbdma_procbuffers(&(s->sbe_rxdma[1]),s->sbe_rxdma[1].sbdma_upcall);
1708	    }
1709#endif
1710	}
1711
1712}
1713
1714
1715/*  *********************************************************************
1716    *  SBETH_MII_FINDROBO(s)
1717    *
1718    *  Check if MII is hooked up to a RoboSwitch.
1719    *
1720    *  Input parameters:
1721    *  	   s - sbeth structure
1722    *
1723    *  Return value:
1724    *  	   true if RoboSwitch found
1725    ********************************************************************* */
1726static int sbeth_mii_findrobo(sbeth_t *s)
1727{
1728    int phy;
1729    int cnt;
1730    uint16_t bmsr;
1731
1732    for (phy = 0, cnt = 0; phy < 31; phy++) {
1733	bmsr = sbeth_mii_read(s,phy,MII_BMSR);
1734	if (bmsr != 0) {
1735	    cnt++;
1736	    }
1737	}
1738
1739    return (cnt >= 5);
1740}
1741
1742/*  *********************************************************************
1743    *  SBETH_MII_FINDPHY(s)
1744    *
1745    *  Find the first available PHY.
1746    *
1747    *  Input parameters:
1748    *  	   s - sbeth structure
1749    *
1750    *  Return value:
1751    *  	   nothing
1752    ********************************************************************* */
1753static void sbeth_mii_findphy(sbeth_t *s)
1754{
1755    int phy;
1756    uint16_t bmsr;
1757    uint16_t id1, id2;
1758
1759    for (phy = 0; phy < 31; phy++) {
1760	bmsr = sbeth_mii_read(s,phy,MII_BMSR);
1761	if (bmsr != 0) {
1762	    s->sbe_phyaddr = phy;
1763	    id1 = sbeth_mii_read(s,phy,MII_PHYIDR1);
1764	    id2 = sbeth_mii_read(s,phy,MII_PHYIDR2);
1765	    s->sbe_phyvendor = ((uint32_t)id1 << 6) | ((id2 >> 10) & 0x3F);
1766	    s->sbe_phydevice = (id2 >> 4) & 0x3F;
1767	    xprintf("sbeth: found phy %d, vendor %06X part %02X\n",
1768		    phy, s->sbe_phyvendor, s->sbe_phydevice);
1769	    return;
1770	    }
1771	}
1772
1773    s->sbe_phyaddr = 0;
1774}
1775
1776/*  *********************************************************************
1777    *  SBETH_MII_POLL(s)
1778    *
1779    *  Ask the PHY what is going on, and configure speed appropriately.
1780    *  For the moment, we only support automatic configuration.
1781    *
1782    *  Input parameters:
1783    *  	   s - sbeth structure
1784    *      noisy - display console messages
1785    *
1786    *  Return value:
1787    *  	   1 if something has changed and we should restart the channel
1788    *	   0 if nothing has changed.
1789    ********************************************************************* */
1790static int sbeth_mii_poll(sbeth_t *s,int noisy)
1791{
1792    uint16_t bmsr,bmcr,k1stsr,anlpar;
1793    int chg;
1794    char buffer[100];
1795    char *p = buffer;
1796    char *devname;
1797
1798    /* Read the mode status and mode control registers. */
1799    bmsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMSR);
1800    bmcr = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR);
1801
1802    /* get the link partner status */
1803    anlpar = sbeth_mii_read(s,s->sbe_phyaddr,MII_ANLPAR);
1804
1805    /* if supported, read the 1000baseT register */
1806    if (bmsr & BMSR_1000BT_XSR) {
1807	k1stsr = sbeth_mii_read(s,s->sbe_phyaddr,MII_K1STSR);
1808	}
1809    else {
1810	k1stsr = 0;
1811	}
1812
1813    chg = 0;
1814
1815    if ((s->sbe_phy_oldbmsr != bmsr) ||
1816	(s->sbe_phy_oldbmcr != bmcr) ||
1817	(s->sbe_phy_oldanlpar != anlpar) ||
1818	(s->sbe_phy_oldk1stsr != k1stsr)) {
1819	s->sbe_phy_oldbmsr = bmsr;
1820	s->sbe_phy_oldbmcr = bmcr;
1821	s->sbe_phy_oldanlpar = anlpar;
1822	s->sbe_phy_oldk1stsr = k1stsr;
1823	chg = 1;
1824	}
1825
1826    if (chg == 0) return 0;
1827
1828    if (!s->sbe_autospeed) return 0;
1829
1830    p += xsprintf(p,"Link speed: ");
1831
1832    if (k1stsr & K1STSR_LP1KFD) {
1833	s->sbe_speed = sbeth_speed_1000;
1834	s->sbe_duplex = sbeth_duplex_full;
1835	s->sbe_fc = sbeth_fc_frame;
1836	s->sbe_linkstat = ETHER_SPEED_1000FDX;
1837	p += xsprintf(p,"1000BaseT FDX");
1838	}
1839    else if (k1stsr & K1STSR_LP1KHD) {
1840	s->sbe_speed = sbeth_speed_1000;
1841	s->sbe_duplex = sbeth_duplex_half;
1842	s->sbe_fc = sbeth_fc_disabled;
1843	s->sbe_linkstat = ETHER_SPEED_1000HDX;
1844	p += xsprintf(p,"1000BaseT HDX");
1845	}
1846    else if (anlpar & ANLPAR_TXFD) {
1847	s->sbe_speed = sbeth_speed_100;
1848	s->sbe_duplex = sbeth_duplex_full;
1849	s->sbe_fc = (anlpar & ANLPAR_PAUSE) ? sbeth_fc_frame : sbeth_fc_disabled;
1850	s->sbe_linkstat = ETHER_SPEED_100FDX;
1851	p += xsprintf(p,"100BaseT FDX");
1852	}
1853    else if (anlpar & ANLPAR_TXHD) {
1854	s->sbe_speed = sbeth_speed_100;
1855	s->sbe_duplex = sbeth_duplex_half;
1856	s->sbe_fc = sbeth_fc_disabled;
1857	s->sbe_linkstat = ETHER_SPEED_100HDX;
1858	p += xsprintf(p,"100BaseT HDX");
1859	}
1860    else if (anlpar & ANLPAR_10FD) {
1861	s->sbe_speed = sbeth_speed_10;
1862	s->sbe_duplex = sbeth_duplex_full;
1863	s->sbe_fc = sbeth_fc_frame;
1864	s->sbe_linkstat = ETHER_SPEED_10FDX;
1865	p += xsprintf(p,"10BaseT FDX");
1866	}
1867    else if (anlpar & ANLPAR_10HD) {
1868	s->sbe_speed = sbeth_speed_10;
1869	s->sbe_duplex = sbeth_duplex_half;
1870	s->sbe_fc = sbeth_fc_collision;
1871	s->sbe_linkstat = ETHER_SPEED_10HDX;
1872	p += xsprintf(p,"10BaseT HDX");
1873	}
1874    else {
1875	s->sbe_linkstat = ETHER_SPEED_UNKNOWN;
1876	p += xsprintf(p,"Unknown");
1877	}
1878
1879#if defined(_BCM91120C_DIAG_CFG_) || defined(_BCM91125C_DIAG_CFG_) || \
1880    defined(_CSWARM_DIAG_CFG_) || defined(_CSWARM_DIAG3E_CFG_) || \
1881    defined(_PTSWARM_DIAG_CFG_) || defined(_PTSWARM_CFG_)
1882    noisy = 0;
1883#endif
1884
1885    if (noisy) {
1886	devname = s->sbe_devctx ? cfe_device_name(s->sbe_devctx) : "eth?";
1887	console_log("%s: %s",devname,buffer);
1888	}
1889
1890    return 1;
1891}
1892
1893
1894/*  *********************************************************************
1895    *  SBETH_MII_SETUP(s)
1896    *
1897    *
1898    *  Input parameters:
1899    *  	   s - sbeth
1900    *
1901    *  Various boards have PHYs that are incorrectly strapped or
1902    *  need other preconfiguration to enable autonegotiation and
1903    *  establish a valid link.
1904    *
1905    *  Return value:
1906    *  	   TRUE if we were on a 5411
1907    ********************************************************************* */
1908
1909/* Helper routine for bcm546x extended register (0x1C shadow) access. */
1910static void bcm546x_update(sbeth_t *s, unsigned int ext,
1911			   uint16_t clear_bits, uint16_t set_bits)
1912{
1913    uint16_t ext_val;
1914    int phy_addr = s->sbe_phyaddr;
1915
1916    ext_val = (ext << 10);
1917    sbeth_mii_write(s, phy_addr, 0x1C, ext_val);
1918    ext_val = sbeth_mii_read(s, phy_addr, 0x1C);
1919    ext_val |= (0x1 << 15);
1920    sbeth_mii_write(s, phy_addr, 0x1C, ext_val);  /* needed? */
1921    cfe_usleep(100);                              /* ditto */
1922    ext_val &= ~clear_bits;
1923    ext_val |= set_bits;
1924    sbeth_mii_write(s, phy_addr, 0x1C, ext_val);
1925    cfe_usleep(100);
1926    ext_val &= ~(0x1 << 15);                      /* ditto */
1927    sbeth_mii_write(s, phy_addr, 0x1C, ext_val);  /* ditto */
1928}
1929
1930/* Helper routines to restart autonegotiation. */
1931static void sbeth_mii_restart_an(sbeth_t *s)
1932{
1933    uint16_t anar, k1ctl, bmcr;
1934    int phy_addr = s->sbe_phyaddr;
1935
1936    /* Standard (copper mode) autonegotiation. */
1937    anar = sbeth_mii_read(s, phy_addr, MII_ANAR);
1938    anar |= (ANAR_TXFD | ANAR_TXHD | ANAR_10FD | ANAR_10HD);
1939    sbeth_mii_write(s, phy_addr, MII_ANAR, anar);
1940    k1ctl = sbeth_mii_read(s, phy_addr, MII_K1CTL);
1941    k1ctl |= (K1TCR_1000BT_FDX | K1TCR_1000BT_HDX);
1942    sbeth_mii_write(s, phy_addr, MII_K1CTL, k1ctl);
1943    bmcr = sbeth_mii_read(s, phy_addr, MII_BMCR);
1944    bmcr |= (BMCR_ANENABLE | BMCR_RESTARTAN);
1945    sbeth_mii_write(s, phy_addr, MII_BMCR, bmcr);
1946}
1947
1948static int sbeth_mii_setup(sbeth_t *s)
1949{
1950    if (s->sbe_phyvendor == OUI_BCM) {
1951	int phy_addr = s->sbe_phyaddr;
1952
1953	switch (s->sbe_phydevice) {
1954	    case DEV_BCM5411:
1955		/* The CSWARM boards leave the PHYs in JTAG mode.  The
1956		 *  sequence * below turns off JTAG mode and puts the
1957		 *  PHYs back * into their regular reset state.  This
1958		 *  is only used with the BCM5411
1959		 */
1960
1961		 /* clear ext loopback */
1962		sbeth_mii_write(s,phy_addr,MII_AUXCTL,0x0420);
1963
1964		/* clear swap rx MDIX/TXHalfOut bits */
1965		sbeth_mii_write(s,phy_addr,MII_AUXCTL,0x0004);
1966
1967		sbeth_mii_restart_an(s);
1968		break;
1969
1970	    case DEV_BCM5421:
1971		/*
1972		 * Make sure that the part is in GMII, not SGMII.
1973		 * This was a problem with 5421 A0 silicon
1974		 * the FDX pin
1975		 */
1976		sbeth_mii_write(s,phy_addr,0x18,0x0392);
1977		break;
1978
1979	    case DEV_BCM5461:
1980		/* Note: The bcm5461 and bcm5461S have the same device
1981		   code.  The following is for a 5461S. */
1982#if defined(_BCM91125CPCI_)
1983		/* The 5461S attached to the 1125 MAC is for GMII to
1984		   copper but is strapped for GMII to SerDes with
1985		   autodetect enabled.  That leaves the wrong set of
1986		   PHY registers visible. */
1987
1988		/* Undo autodetect. */
1989		bcm546x_update(s, 0x1E, (0x1 << 0), 0);
1990		/* Force copper. */
1991		bcm546x_update(s, 0x1F, ((0x3 << 1)|(0x1 << 0)), 0);
1992
1993		/* Redo the autonegotiation. */
1994		sbeth_mii_restart_an(s);
1995
1996		/* Remap LINKSPD[1] selector to Link Quality. */
1997		bcm546x_update(s, 0x0D, (0xF << 0), 0x7);
1998#else
1999		(void)bcm546x_update;  /* keep compiler happy */
2000#endif
2001		break;
2002
2003	    case DEV_BCM5464:
2004	        /* Defaults are ok in current applications. */
2005		break;
2006	    }
2007	}
2008
2009    return 0;
2010}
2011
2012
2013/*  *********************************************************************
2014    *  Declarations for CFE Device Driver Interface routines
2015    ********************************************************************* */
2016
2017static int sb1250_ether_open(cfe_devctx_t *ctx);
2018static int sb1250_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
2019static int sb1250_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat);
2020static int sb1250_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
2021static int sb1250_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer);
2022static int sb1250_ether_close(cfe_devctx_t *ctx);
2023static void sb1250_ether_poll(cfe_devctx_t *ctx,int64_t ticks);
2024static void sb1250_ether_reset(void *softc);
2025
2026/*  *********************************************************************
2027    *  CFE Device Driver dispatch structure
2028    ********************************************************************* */
2029
2030const static cfe_devdisp_t sb1250_ether_dispatch = {
2031    sb1250_ether_open,
2032    sb1250_ether_read,
2033    sb1250_ether_inpstat,
2034    sb1250_ether_write,
2035    sb1250_ether_ioctl,
2036    sb1250_ether_close,
2037    sb1250_ether_poll,
2038    sb1250_ether_reset
2039};
2040
2041/*  *********************************************************************
2042    *  CFE Device Driver descriptor
2043    ********************************************************************* */
2044
2045const cfe_driver_t sb1250_ether = {
2046    "SiByte Ethernet",
2047    "eth",
2048    CFE_DEV_NETWORK,
2049    &sb1250_ether_dispatch,
2050    sb1250_ether_probe
2051};
2052
2053
2054/*  *********************************************************************
2055    *  SB1250_ETHER_PROBE(drv,probe_a,probe_b,probe_ptr)
2056    *
2057    *  Probe and install an Ethernet device driver.  This routine
2058    *  creates a context structure and attaches to the specified
2059    *  MAC device.
2060    *
2061    *  Input parameters:
2062    *  	   drv - driver descriptor
2063    *  	   probe_a - base address of MAC to probe
2064    *  	   probe_b - not used
2065    *  	   probe_ptr - string pointer to hardware address for this
2066    *  	               MAC, in the form xx:xx:xx:xx:xx:xx
2067    *
2068    *  Return value:
2069    *  	   nothing
2070    ********************************************************************* */
2071
2072static void sb1250_ether_probe(cfe_driver_t *drv,
2073			       unsigned long probe_a, unsigned long probe_b,
2074			       void *probe_ptr)
2075{
2076    sbeth_t *softc;
2077    char descr[100];
2078
2079    softc = (sbeth_t *) KMALLOC(sizeof(sbeth_t),0);
2080
2081    if (softc) {
2082	sbeth_initctx(softc,probe_a,softc);
2083	if (probe_ptr) {
2084	    enet_parse_hwaddr((char *) probe_ptr,softc->sbe_hwaddr);
2085	    }
2086	xsprintf(descr,"%s at 0x%X (%a)",drv->drv_description,probe_a,
2087		 softc->sbe_hwaddr);
2088
2089	sbeth_mii_findphy(softc);
2090	sbeth_mii_setup(softc);
2091	cfe_attach(drv,softc,NULL,descr);
2092	sbeth_setaddr(softc,softc->sbe_hwaddr);
2093	}
2094}
2095
2096
2097/*  *********************************************************************
2098    *  SB1250_ETHER_READENV(ctx)
2099    *
2100    *  Read the environment variable that corresponds to this
2101    *  interface to pick up the hardware address.  Note that the way
2102    *  we do this is somewhat slimey.
2103    *
2104    *  Input parameters:
2105    *  	   ctx - device context
2106    *
2107    *  Return value:
2108    *  	   nothing
2109    ********************************************************************* */
2110
2111static void sb1250_ether_readenv(cfe_devctx_t *ctx)
2112{
2113    sbeth_t *softc = ctx->dev_softc;
2114    char envbuf[100];
2115    char *hwaddr;
2116
2117    /*
2118     * Gross - we should *not* be reaching into these data
2119     * structures like this!
2120     */
2121
2122    xsprintf(envbuf,"%s_HWADDR",cfe_device_name(ctx));
2123    strupr(envbuf);
2124
2125    hwaddr = env_getenv(envbuf);
2126
2127    if (hwaddr) {
2128	enet_parse_hwaddr(hwaddr,softc->sbe_hwaddr);
2129	}
2130
2131}
2132
2133/*  *********************************************************************
2134    *  SB1250_ETHER_OPEN(ctx)
2135    *
2136    *  Open the Ethernet device.  The MAC is reset, initialized, and
2137    *  prepared to receive and send packets.
2138    *
2139    *  Input parameters:
2140    *  	   ctx - device context (includes ptr to our softc)
2141    *
2142    *  Return value:
2143    *  	   status, 0 = ok
2144    ********************************************************************* */
2145
2146static int sb1250_ether_open(cfe_devctx_t *ctx)
2147{
2148    sbeth_t *softc = ctx->dev_softc;
2149
2150    softc->sbe_devctx = ctx;
2151
2152    sbeth_stop(softc);
2153
2154    /*
2155     * Look for RoboSwitch on MII interface and set fixed speed
2156     * if found, otherwise go ahead and look for a normal PHY.
2157     */
2158
2159    if (sbeth_mii_findrobo(softc)) {
2160        sb1250_ether_ioctl_speed(softc,ETHER_SPEED_100FDX);
2161        }
2162    else {
2163        sbeth_mii_findphy(softc);
2164        softc->sbe_autospeed = TRUE;
2165        }
2166
2167    /*
2168     * Note: The Phy can take several seconds to become ready!
2169     * This gross code pounds on the phy until  it says it is
2170     * ready, but it still takes 2 more seconds after this
2171     * before the link is usable.  We're better off letting the
2172     * dhcp/arp retries do the right thing here.
2173     */
2174
2175#if 0
2176    do {
2177	int64_t timer;
2178	TIMER_SET(timer,2*CFE_HZ);
2179	while (!TIMER_EXPIRED(timer)) {
2180	    sbeth_mii_poll(softc,FALSE);
2181	    if (softc->sbe_linkstat != ETHER_SPEED_UNKNOWN) break;
2182	    }
2183	} while (0);
2184#else
2185    if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) {
2186        sbeth_mii_poll(softc,TRUE);
2187        }
2188#endif
2189
2190    sb1250_ether_readenv(ctx);
2191
2192    TIMER_SET(softc->sbe_linkstat_timer,SBETH_MIIPOLL_TIMER);
2193    softc->fifo_mode = FALSE;
2194
2195    /* Make sure we see a change with autospeed set (rework?) */
2196    softc->sbe_phy_oldbmsr &= ~BMSR_ANCOMPLETE;
2197
2198    sbeth_start(softc);
2199
2200    return 0;
2201}
2202
2203/*  *********************************************************************
2204    *  SB1250_ETHER_READ(ctx,buffer)
2205    *
2206    *  Read a packet from the Ethernet device.  If no packets are
2207    *  available, the read will succeed but return 0 bytes.
2208    *
2209    *  Input parameters:
2210    *  	   ctx - device context (includes ptr to our softc)
2211    *      buffer - pointer to buffer descriptor.
2212    *
2213    *  Return value:
2214    *  	   status, 0 = ok
2215    ********************************************************************* */
2216
2217static int sb1250_ether_read(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
2218{
2219    sbeth_t *softc = ctx->dev_softc;
2220    sbeth_pkt_t *pkt;
2221    int blen;
2222
2223    if (softc->sbe_state != sbeth_state_on) return -1;
2224
2225    sbeth_isr(softc);
2226
2227    if (softc->sbe_rxqueue == NULL) {
2228	buffer->buf_retlen = 0;
2229	return 0;
2230	}
2231
2232    pkt = softc->sbe_rxqueue;
2233    softc->sbe_rxqueue = pkt->next;
2234    pkt->next = NULL;
2235
2236    blen = buffer->buf_length;
2237    if (blen > pkt->length) blen = pkt->length;
2238
2239    hs_memcpy_to_hs(buffer->buf_ptr,pkt->buffer,blen);
2240    buffer->buf_retlen = blen;
2241
2242    sbeth_free_pkt(softc,pkt);
2243    sbeth_fillrxring(softc,0);
2244    sbeth_isr(softc);
2245
2246    return 0;
2247}
2248
2249/*  *********************************************************************
2250    *  SB1250_ETHER_INPSTAT(ctx,inpstat)
2251    *
2252    *  Check for received packets on the Ethernet device
2253    *
2254    *  Input parameters:
2255    *  	   ctx - device context (includes ptr to our softc)
2256    *      inpstat - pointer to input status structure
2257    *
2258    *  Return value:
2259    *  	   status, 0 = ok
2260    ********************************************************************* */
2261static int sb1250_ether_inpstat(cfe_devctx_t *ctx,iocb_inpstat_t *inpstat)
2262{
2263    sbeth_t *softc = ctx->dev_softc;
2264
2265    if (softc->sbe_state != sbeth_state_on) return -1;
2266
2267    sbeth_isr(softc);
2268
2269    inpstat->inp_status = (softc->sbe_rxqueue == NULL) ? 0 : 1;
2270
2271    return 0;
2272}
2273
2274/*  *********************************************************************
2275    *  SB1250_ETHER_WRITE(ctx,buffer)
2276    *
2277    *  Write a packet to the Ethernet device.
2278    *
2279    *  Input parameters:
2280    *  	   ctx - device context (includes ptr to our softc)
2281    *      buffer - pointer to buffer descriptor.
2282    *
2283    *  Return value:
2284    *  	   status, 0 = ok
2285    ********************************************************************* */
2286static int sb1250_ether_write(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
2287{
2288    sbeth_t *softc = ctx->dev_softc;
2289    sbeth_pkt_t *pkt;
2290    int blen;
2291
2292    if (softc->sbe_state != sbeth_state_on) return -1;
2293
2294
2295    if (!softc->fifo_mode) {
2296	/* Only do a speed check if not packet fifo mode*/
2297	int chg;
2298
2299	if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) {
2300	    chg = sbeth_mii_poll(softc,TRUE);
2301	    if (softc->sbe_linkstat == ETHER_SPEED_UNKNOWN) return -1;
2302	    if (chg) {
2303		sbeth_stop(softc);
2304		sbeth_start(softc);
2305		}
2306	    }
2307	}
2308
2309    pkt = sbeth_alloc_pkt(softc);
2310    if (!pkt) return CFE_ERR_NOMEM;
2311
2312    blen = buffer->buf_length;
2313    if (blen > pkt->length) blen = pkt->length;
2314
2315    hs_memcpy_from_hs(pkt->buffer,buffer->buf_ptr,blen);
2316    pkt->length = blen;
2317
2318    sbeth_isr(softc);
2319
2320    if (sbeth_transmit(softc,0,pkt->buffer,pkt->length,pkt) != 1) {
2321	sbeth_free_pkt(softc,pkt);
2322	return CFE_ERR_IOERR;
2323	}
2324
2325    sbeth_isr(softc);
2326
2327    buffer->buf_retlen = blen;
2328
2329    return 0;
2330}
2331
2332/*  *********************************************************************
2333    *  SB1250_ETHER_IOCTL_LOOPBACK(s,loopback)
2334    *
2335    *  Set loopback modes
2336    *
2337    *  Input parameters:
2338    *  	   s - sbeth structure
2339    *  	   loopback - loopback modes
2340    *
2341    *  Return value:
2342    *  	   0 if ok, else error
2343    ********************************************************************* */
2344
2345static int sb1250_ether_ioctl_loopback(sbeth_t *s,int loopback)
2346{
2347    unsigned int miireg;
2348    uint64_t regval;
2349
2350    switch (loopback) {
2351	case ETHER_LOOPBACK_OFF:
2352	    miireg = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR);
2353	    if (miireg & BMCR_LOOPBACK) {
2354		miireg &= ~BMCR_LOOPBACK;
2355		miireg |= BMCR_RESTARTAN;
2356		sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,miireg);
2357		}
2358	    regval = SBETH_READCSR(s->sbe_maccfg);
2359	    if (regval & M_MAC_LOOPBACK_SEL) {
2360		regval &= ~M_MAC_LOOPBACK_SEL;
2361		SBETH_WRITECSR(s->sbe_maccfg,regval);
2362		}
2363	    break;
2364
2365	case ETHER_LOOPBACK_INT:
2366	    regval = SBETH_READCSR(s->sbe_maccfg);
2367	    regval |= M_MAC_LOOPBACK_SEL;
2368	    SBETH_WRITECSR(s->sbe_maccfg,regval);
2369	    break;
2370
2371	case ETHER_LOOPBACK_EXT:
2372	    regval = SBETH_READCSR(s->sbe_maccfg);
2373	    if (regval & M_MAC_LOOPBACK_SEL) {
2374		regval &= ~M_MAC_LOOPBACK_SEL;
2375		SBETH_WRITECSR(s->sbe_maccfg,regval);
2376		}
2377	    miireg = sbeth_mii_read(s,s->sbe_phyaddr,MII_BMCR);
2378	    miireg |= BMCR_LOOPBACK;
2379	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,miireg);
2380	    break;
2381	}
2382
2383    s->sbe_loopback = loopback;
2384
2385    return 0;
2386}
2387
2388
2389/*  *********************************************************************
2390    *  SB1250_ETHER_IOCTL_SPEED(s,speed)
2391    *
2392    *  Set speed forcibly via the IOCTL command
2393    *
2394    *  Input parameters:
2395    *  	   s - sbeth structure
2396    *  	   speed - speed IOCTL setting
2397    *
2398    *  Return value:
2399    *  	   0 if ok, else error
2400    ********************************************************************* */
2401
2402static int sb1250_ether_ioctl_speed(sbeth_t *s,int speed)
2403{
2404    switch (speed) {
2405	case ETHER_SPEED_AUTO:
2406	    s->sbe_autospeed = TRUE;
2407	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2408			    BMCR_ANENABLE|BMCR_RESTARTAN|BMCR_DUPLEX|BMCR_SPEED1);
2409	    TIMER_SET(s->sbe_linkstat_timer,100);
2410	    break;
2411
2412	case ETHER_SPEED_10HDX:
2413	    s->sbe_autospeed = FALSE;
2414	    s->sbe_speed = sbeth_speed_10;
2415	    s->sbe_duplex = sbeth_duplex_half;
2416	    s->sbe_fc = sbeth_fc_disabled;
2417	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2418			BMCR_SPEED10);
2419	    break;
2420
2421	case ETHER_SPEED_10FDX:
2422	    s->sbe_autospeed = FALSE;
2423	    s->sbe_speed = sbeth_speed_10;
2424	    s->sbe_duplex = sbeth_duplex_full;
2425	    s->sbe_fc = sbeth_fc_frame;
2426	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2427			BMCR_SPEED10|BMCR_DUPLEX);
2428	    break;
2429
2430	case ETHER_SPEED_100HDX:
2431	    s->sbe_autospeed = FALSE;
2432	    s->sbe_speed = sbeth_speed_100;
2433	    s->sbe_duplex = sbeth_duplex_half;
2434	    s->sbe_fc = sbeth_fc_disabled;
2435	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2436			BMCR_SPEED100);
2437	    break;
2438
2439	case ETHER_SPEED_100FDX:
2440	    s->sbe_autospeed = FALSE;
2441	    s->sbe_speed = sbeth_speed_100;
2442	    s->sbe_duplex = sbeth_duplex_full;
2443	    s->sbe_fc = sbeth_fc_frame;
2444	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2445			BMCR_SPEED100|BMCR_DUPLEX);
2446	    break;
2447
2448	case ETHER_SPEED_1000HDX:
2449	    s->sbe_autospeed = FALSE;
2450	    s->sbe_speed = sbeth_speed_1000;
2451	    s->sbe_duplex = sbeth_duplex_half;
2452	    s->sbe_fc = sbeth_fc_disabled;
2453	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2454			BMCR_SPEED1000);
2455	    break;
2456
2457	case ETHER_SPEED_1000FDX:
2458	    s->sbe_autospeed = FALSE;
2459	    s->sbe_speed = sbeth_speed_1000;
2460	    s->sbe_duplex = sbeth_duplex_full;
2461	    s->sbe_fc = sbeth_fc_frame;
2462	    sbeth_mii_write(s,s->sbe_phyaddr,MII_BMCR,
2463			BMCR_SPEED1000|BMCR_DUPLEX);
2464	    break;
2465
2466	default:
2467	    return -1;
2468	}
2469
2470    sbeth_stop(s);
2471    sbeth_start(s);
2472
2473    s->sbe_curspeed = speed;
2474    if (speed != ETHER_SPEED_AUTO) s->sbe_linkstat = speed;
2475
2476    return 0;
2477}
2478/*  *********************************************************************
2479    *  SB1250_ETHER_IOCTL_PACKETFIFO(s,mode)
2480    *
2481    *  Swtich to a packet fifo mode.
2482    *
2483    *
2484    *  Input parameters:
2485    *  	   s - sbeth structure
2486    *  	   mode - 8 or 16 bit packet fifo mode.
2487    *
2488    *  Return value:
2489    *  	   0 if ok, else error
2490    ********************************************************************* */
2491static int sb1250_ether_ioctl_packetfifo(sbeth_t *s, int mode)
2492{
2493    uint64_t cfg;
2494    uint64_t enb;
2495    uint64_t frame;
2496
2497    cfg = SBETH_READCSR(s->sbe_maccfg);
2498    switch (mode) {
2499	case ETHER_FIFO_8:
2500	    cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_AP_STAT_EN | M_MAC_SPEED_SEL | M_MAC_BURST_EN);
2501	    cfg |= M_MAC_BYPASS_SEL | V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
2502
2503	    /* disable rx/tx ethernet macs and  enable rx/tx fifo engines */
2504	    enb = SBETH_READCSR(s->sbe_macenable);
2505	    enb &= ~(M_MAC_RX_ENABLE | M_MAC_TX_ENABLE);
2506	    enb |= M_MAC_BYP_RX_ENABLE |
2507		M_MAC_BYP_TX_ENABLE |
2508		0;
2509	    SBETH_WRITECSR(s->sbe_macenable,enb);
2510
2511	    /* accept all packets */
2512	    SBETH_WRITECSR(s->sbe_rxfilter, M_MAC_ALLPKT_EN | 0);
2513
2514	    /* set min_frame_size to 9 bytes */
2515	    frame = SBETH_READCSR(s->sbe_framecfg);
2516	    frame |= V_MAC_MIN_FRAMESZ_FIFO;
2517	    SBETH_WRITECSR(s->sbe_framecfg,frame);
2518
2519	    s->fifo_mode = TRUE;
2520
2521	    break;
2522
2523	case ETHER_FIFO_16:
2524	    cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | M_MAC_AP_STAT_EN | M_MAC_SPEED_SEL | M_MAC_BURST_EN);
2525	    cfg |= M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | V_MAC_SPEED_SEL_1000MBPS | M_MAC_BURST_EN;
2526
2527	    /* disable rx/tx ethernet macs and  enable rx/tx fifo engines */
2528	    enb = SBETH_READCSR(s->sbe_macenable);
2529	    enb &= ~(M_MAC_RX_ENABLE | M_MAC_TX_ENABLE);
2530	    enb |= M_MAC_BYP_RX_ENABLE |
2531		M_MAC_BYP_TX_ENABLE |
2532		0;
2533	    SBETH_WRITECSR(s->sbe_macenable,enb);
2534
2535	    /* accept all packets */
2536	    SBETH_WRITECSR(s->sbe_rxfilter, M_MAC_ALLPKT_EN | 0);
2537
2538	    /* set min_frame_size to 9 bytes */
2539	    frame = SBETH_READCSR(s->sbe_framecfg);
2540	    frame |= V_MAC_MIN_FRAMESZ_FIFO;
2541	    SBETH_WRITECSR(s->sbe_framecfg,frame);
2542
2543	    s->fifo_mode = TRUE;
2544
2545	    break;
2546
2547	case ETHER_ETHER:
2548	    cfg &= ~(M_MAC_BYPASS_SEL | M_MAC_BYPASS_16 | M_MAC_AP_STAT_EN );
2549	    cfg |= M_MAC_AP_STAT_EN;
2550	    break;
2551
2552	default:
2553	    return -1;
2554	}
2555
2556    SBETH_WRITECSR(s->sbe_maccfg,cfg);
2557
2558    return 0;
2559}
2560
2561/*  *********************************************************************
2562    *  SB1250_ETHER_IOCTL_STROBESIGNAL
2563    *
2564    *  Set the strobe signal that are used on both transmit and receive
2565    *  interfaces in packet fifo mode.
2566    *
2567    *  Input parameters:
2568    *  	   s - sbeth structure
2569    *  	   mode - GMII style, Encoded, SOP flagged, or EOP flagged mode.
2570    *
2571    *  Return value:
2572    * 	   0 if ok, else error
2573    ********************************************************************* */
2574static int sb1250_ether_ioctl_strobesignal(sbeth_t *s, int mode)
2575{
2576    uint64_t cfg;
2577
2578    cfg = SBETH_READCSR(s->sbe_maccfg);
2579
2580    switch (mode) {
2581	case ETHER_STROBE_GMII:
2582	    cfg &= ~(M_MAC_BYPASS_CFG);
2583	    cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_GMII);
2584	    break;
2585
2586	case ETHER_STROBE_ENCODED:
2587	    cfg &= ~(M_MAC_BYPASS_CFG);
2588	    cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_ENCODED);
2589	    break;
2590
2591	case ETHER_STROBE_SOP:	/* not valid in 16-bit fifo mode */
2592	    cfg &= ~(M_MAC_BYPASS_CFG);
2593	    cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_SOP);
2594	    break;
2595
2596	case ETHER_STROBE_EOP: /* not valid in 16-bit fifo mode */
2597	    cfg &= ~(M_MAC_BYPASS_CFG);
2598	    cfg |= V_MAC_BYPASS_CFG(K_MAC_BYPASS_EOP);
2599	    break;
2600
2601	default:
2602	    return -1;
2603	}
2604
2605    SBETH_WRITECSR(s->sbe_maccfg,cfg);
2606
2607    return 0;
2608}
2609
2610/*  *********************************************************************
2611    *  SB1250_ETHER_IOCTL(ctx,buffer)
2612    *
2613    *  Do device-specific I/O control operations for the device
2614    *
2615    *  Input parameters:
2616    *  	   ctx - device context (includes ptr to our softc)
2617    *      buffer - pointer to buffer descriptor.
2618    *
2619    *  Return value:
2620    *  	   status, 0 = ok
2621    ********************************************************************* */
2622static int sb1250_ether_ioctl(cfe_devctx_t *ctx,iocb_buffer_t *buffer)
2623{
2624    sbeth_t *softc = ctx->dev_softc;
2625    int m;
2626
2627    switch ((int)buffer->buf_ioctlcmd) {
2628	case IOCTL_ETHER_GETHWADDR:
2629	    hs_memcpy_to_hs(buffer->buf_ptr,softc->sbe_hwaddr,sizeof(softc->sbe_hwaddr));
2630	    break;
2631
2632	case IOCTL_ETHER_SETHWADDR:
2633	    hs_memcpy_from_hs(softc->sbe_hwaddr,buffer->buf_ptr,sizeof(softc->sbe_hwaddr));
2634	    sbeth_setaddr(softc,softc->sbe_hwaddr);
2635#ifdef _SB1250_PASS1_WORKAROUNDS_
2636	    SBETH_WRITECSR(SBETH_PORT(softc->sbe_baseaddr + R_MAC_ETHERNET_ADDR),0);
2637#endif
2638	    break;
2639
2640	case IOCTL_ETHER_GETSPEED:
2641	    m = softc->sbe_curspeed;
2642	    hs_memcpy_to_hs(buffer->buf_ptr,&m,sizeof(int));
2643	    break;
2644
2645	case IOCTL_ETHER_SETSPEED:
2646	    hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int));
2647	    return sb1250_ether_ioctl_speed(softc,m);
2648	    break;
2649
2650	case IOCTL_ETHER_GETLINK:
2651	    m = softc->sbe_linkstat;
2652	    hs_memcpy_to_hs(buffer->buf_ptr,&m,sizeof(int));
2653	    break;
2654
2655	case IOCTL_ETHER_GETLOOPBACK:
2656	    m = softc->sbe_loopback;
2657	    hs_memcpy_to_hs(buffer->buf_ptr,&m,sizeof(int));
2658	    break;
2659
2660	case IOCTL_ETHER_SETLOOPBACK:
2661	    hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int));
2662	    return sb1250_ether_ioctl_loopback(softc,m);
2663	    break;
2664
2665        case IOCTL_ETHER_SETPACKETFIFO:
2666	    hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int));
2667	    return sb1250_ether_ioctl_packetfifo(softc,m);
2668	    break;
2669
2670	case IOCTL_ETHER_SETSTROBESIG:
2671	    hs_memcpy_from_hs(&m,buffer->buf_ptr,sizeof(int));
2672	    return sb1250_ether_ioctl_strobesignal(softc,m);
2673	    break;
2674
2675	default:
2676	    return -1;
2677	}
2678
2679    return 0;
2680}
2681
2682/*  *********************************************************************
2683    *  SB1250_ETHER_CLOSE(ctx)
2684    *
2685    *  Close the Ethernet device.
2686    *
2687    *  Input parameters:
2688    *  	   ctx - device context (includes ptr to our softc)
2689    *
2690    *  Return value:
2691    *  	   status, 0 = ok
2692    ********************************************************************* */
2693static int sb1250_ether_close(cfe_devctx_t *ctx)
2694{
2695    sbeth_t *softc = ctx->dev_softc;
2696
2697    sbeth_stop(softc);
2698
2699    /* Reprogram the default hardware address in case someone mucked with it */
2700    sbeth_setaddr(softc,softc->sbe_hwaddr);
2701
2702    return 0;
2703}
2704
2705
2706/*  *********************************************************************
2707    *  SB1250_ETHER_POLL(ctx,ticks)
2708    *
2709    *  Check for changes in the PHY, so we can track speed changes.
2710    *
2711    *  Input parameters:
2712    *  	   ctx - device context (includes ptr to our softc)
2713    *      ticks- current time in ticks
2714    *
2715    *  Return value:
2716    *  	   nothing
2717    ********************************************************************* */
2718
2719static void sb1250_ether_poll(cfe_devctx_t *ctx,int64_t ticks)
2720{
2721    sbeth_t *softc = ctx->dev_softc;
2722    int chg;
2723
2724    if (TIMER_RUNNING(softc->sbe_linkstat_timer) &&
2725	TIMER_EXPIRED(softc->sbe_linkstat_timer)) {
2726	if (softc->sbe_autospeed) {
2727	    chg = sbeth_mii_poll(softc,TRUE);
2728	    if (chg) {
2729		if (softc->sbe_state == sbeth_state_on) {
2730		    TIMER_CLEAR(softc->sbe_linkstat_timer);
2731		    sbeth_stop(softc);
2732		    sbeth_start(softc);
2733		    }
2734		}
2735	    }
2736	TIMER_SET(softc->sbe_linkstat_timer,SBETH_MIIPOLL_TIMER);
2737	}
2738
2739}
2740
2741/*  *********************************************************************
2742    *  SB1250_ETHER_RESET(softc)
2743    *
2744    *  This routine is called when CFE is restarted after a
2745    *  program exits.  We can clean up pending I/Os here.
2746    *
2747    *  Input parameters:
2748    *  	   softc - pointer to sbmac_t
2749    *
2750    *  Return value:
2751    *  	   nothing
2752    ********************************************************************* */
2753
2754static void sb1250_ether_reset(void *softc)
2755{
2756    sbeth_t *s = (sbeth_t *) softc;
2757    sbeth_port_t port;
2758    uint64_t regval = 0;
2759    int idx;
2760    uint8_t *addr;
2761
2762    /*
2763     * Turn off the Ethernet interface.
2764     */
2765
2766    SBETH_WRITECSR(s->sbe_macenable,0);
2767
2768    /*
2769     * Reset the address.
2770     * Pack the bytes into the register, with the first byte transmitted
2771     * in the lowest-order 8 bits of the register.
2772     */
2773
2774    addr = s->sbe_hwaddr;
2775    for (idx = 0; idx < 6; idx++) {
2776	regval |= (((uint64_t) (*addr)) << (idx*8));
2777	addr++;
2778	}
2779
2780    /*
2781     * Write to the port.
2782     */
2783
2784    port = SBETH_PORT(s->sbe_baseaddr + R_MAC_ETHERNET_ADDR);
2785    SBETH_WRITECSR(port,regval);
2786
2787}
2788