rge.c revision 212553
1198157Srrs/*-
2198157Srrs * Copyright (c) 2003-2009 RMI Corporation
3198157Srrs * All rights reserved.
4198157Srrs *
5198157Srrs * Redistribution and use in source and binary forms, with or without
6198157Srrs * modification, are permitted provided that the following conditions
7198157Srrs * are met:
8198157Srrs * 1. Redistributions of source code must retain the above copyright
9198157Srrs *    notice, this list of conditions and the following disclaimer.
10198157Srrs * 2. Redistributions in binary form must reproduce the above copyright
11198157Srrs *    notice, this list of conditions and the following disclaimer in the
12198157Srrs *    documentation and/or other materials provided with the distribution.
13198157Srrs * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14198157Srrs *    may be used to endorse or promote products derived from this software
15198157Srrs *    without specific prior written permission.
16198157Srrs *
17198157Srrs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18198157Srrs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19198157Srrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20198157Srrs * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21198157Srrs * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22198157Srrs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23198157Srrs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24198157Srrs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25198157Srrs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26198157Srrs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27198157Srrs * SUCH DAMAGE.
28198157Srrs *
29202066Simp * RMI_BSD
30202066Simp */
31198157Srrs
32202066Simp#include <sys/cdefs.h>
33202066Simp__FBSDID("$FreeBSD: head/sys/mips/rmi/dev/xlr/rge.c 212553 2010-09-13 13:11:50Z jchandra $");
34202066Simp
35198157Srrs#ifdef HAVE_KERNEL_OPTION_HEADERS
36198157Srrs#include "opt_device_polling.h"
37198157Srrs#endif
38198157Srrs
39198157Srrs#include <sys/types.h>
40198157Srrs#include <sys/endian.h>
41198157Srrs#include <sys/systm.h>
42198157Srrs#include <sys/sockio.h>
43198157Srrs#include <sys/param.h>
44198157Srrs#include <sys/lock.h>
45198157Srrs#include <sys/mutex.h>
46198157Srrs#include <sys/proc.h>
47198157Srrs#include <sys/limits.h>
48198157Srrs#include <sys/bus.h>
49198157Srrs#include <sys/mbuf.h>
50198157Srrs#include <sys/malloc.h>
51198157Srrs#include <sys/kernel.h>
52198157Srrs#include <sys/module.h>
53198157Srrs#include <sys/socket.h>
54198157Srrs#define __RMAN_RESOURCE_VISIBLE
55198157Srrs#include <sys/rman.h>
56198157Srrs#include <sys/taskqueue.h>
57208165Srrs#include <sys/smp.h>
58211994Sjchandra#include <sys/sysctl.h>
59198157Srrs
60198157Srrs#include <net/if.h>
61198157Srrs#include <net/if_arp.h>
62198157Srrs#include <net/ethernet.h>
63198157Srrs#include <net/if_dl.h>
64198157Srrs#include <net/if_media.h>
65198157Srrs
66198157Srrs#include <net/bpf.h>
67198157Srrs#include <net/if_types.h>
68198157Srrs#include <net/if_vlan_var.h>
69198157Srrs
70198157Srrs#include <netinet/in_systm.h>
71198157Srrs#include <netinet/in.h>
72198157Srrs#include <netinet/ip.h>
73198157Srrs
74198157Srrs#include <vm/vm.h>
75198157Srrs#include <vm/pmap.h>
76198157Srrs
77198157Srrs#include <machine/reg.h>
78198157Srrs#include <machine/cpu.h>
79198157Srrs#include <machine/mips_opcode.h>
80198157Srrs#include <machine/asm.h>
81198789Srrs#include <mips/rmi/rmi_mips_exts.h>
82198157Srrs#include <machine/cpuregs.h>
83198157Srrs
84198157Srrs#include <machine/param.h>
85198157Srrs#include <machine/intr_machdep.h>
86198157Srrs#include <machine/clock.h>	/* for DELAY */
87208165Srrs#include <machine/cpuregs.h>
88198626Srrs#include <machine/bus.h>	/* */
89198157Srrs#include <machine/resource.h>
90211994Sjchandra
91211994Sjchandra#include <dev/mii/mii.h>
92211994Sjchandra#include <dev/mii/miivar.h>
93211994Sjchandra#include <dev/mii/brgphyreg.h>
94211994Sjchandra
95198608Srrs#include <mips/rmi/interrupt.h>
96198608Srrs#include <mips/rmi/msgring.h>
97198608Srrs#include <mips/rmi/iomap.h>
98198608Srrs#include <mips/rmi/pic.h>
99211994Sjchandra#include <mips/rmi/rmi_mips_exts.h>
100211994Sjchandra#include <mips/rmi/rmi_boot_info.h>
101198608Srrs#include <mips/rmi/board.h>
102211996Sjchandra
103211996Sjchandra#include <mips/rmi/dev/xlr/debug.h>
104202066Simp#include <mips/rmi/dev/xlr/atx_cpld.h>
105202066Simp#include <mips/rmi/dev/xlr/xgmac_mdio.h>
106202092Simp#include <mips/rmi/dev/xlr/rge.h>
107198157Srrs
108198608Srrs#include "miibus_if.h"
109198608Srrs
110198157SrrsMODULE_DEPEND(rge, ether, 1, 1, 1);
111198157SrrsMODULE_DEPEND(rge, miibus, 1, 1, 1);
112198157Srrs
113198157Srrs/* #define DEBUG */
114198157Srrs
115198157Srrs#define RGE_TX_THRESHOLD 1024
116198157Srrs#define RGE_TX_Q_SIZE 1024
117198157Srrs
118198157Srrs#ifdef DEBUG
119198157Srrs#undef dbg_msg
120198626Srrsint mac_debug = 1;
121198626Srrs
122198157Srrs#define dbg_msg(fmt, args...) \
123198157Srrs        do {\
124198157Srrs            if (mac_debug) {\
125198157Srrs                printf("[%s@%d|%s]: cpu_%d: " fmt, \
126208369Sjchandra                __FILE__, __LINE__, __FUNCTION__,  xlr_cpu_id(), ##args);\
127198157Srrs            }\
128198157Srrs        } while(0);
129198157Srrs
130198157Srrs#define DUMP_PACKETS
131198157Srrs#else
132198157Srrs#undef dbg_msg
133198157Srrs#define dbg_msg(fmt, args...)
134198626Srrsint mac_debug = 0;
135198626Srrs
136198157Srrs#endif
137198157Srrs
138198157Srrs#define MAC_B2B_IPG             88
139198157Srrs
140198157Srrs/* frame sizes need to be cacheline aligned */
141198157Srrs#define MAX_FRAME_SIZE          1536
142198157Srrs#define MAX_FRAME_SIZE_JUMBO    9216
143198157Srrs
144198157Srrs#define MAC_SKB_BACK_PTR_SIZE   SMP_CACHE_BYTES
145198157Srrs#define MAC_PREPAD              0
146198157Srrs#define BYTE_OFFSET             2
147198157Srrs#define XLR_RX_BUF_SIZE (MAX_FRAME_SIZE+BYTE_OFFSET+MAC_PREPAD+MAC_SKB_BACK_PTR_SIZE+SMP_CACHE_BYTES)
148198157Srrs#define MAC_CRC_LEN             4
149198157Srrs#define MAX_NUM_MSGRNG_STN_CC   128
150198157Srrs
151198157Srrs#define MAX_NUM_DESC		1024
152198157Srrs#define MAX_SPILL_SIZE          (MAX_NUM_DESC + 128)
153198157Srrs
154198157Srrs#define MAC_FRIN_TO_BE_SENT_THRESHOLD 16
155198157Srrs
156198157Srrs#define MAX_FRIN_SPILL          (MAX_SPILL_SIZE << 2)
157198157Srrs#define MAX_FROUT_SPILL         (MAX_SPILL_SIZE << 2)
158198157Srrs#define MAX_CLASS_0_SPILL       (MAX_SPILL_SIZE << 2)
159198157Srrs#define MAX_CLASS_1_SPILL       (MAX_SPILL_SIZE << 2)
160198157Srrs#define MAX_CLASS_2_SPILL       (MAX_SPILL_SIZE << 2)
161198157Srrs#define MAX_CLASS_3_SPILL       (MAX_SPILL_SIZE << 2)
162198157Srrs
163198157Srrs/*****************************************************************
164198157Srrs * Phoenix Generic Mac driver
165198157Srrs *****************************************************************/
166198157Srrs
167198157Srrsextern uint32_t cpu_ltop_map[32];
168198157Srrs
169198157Srrs#ifdef ENABLED_DEBUG
170198626Srrsstatic int port_counters[4][8] __aligned(XLR_CACHELINE_SIZE);
171198626Srrs
172198157Srrs#define port_inc_counter(port, counter) 	atomic_add_int(&port_counters[port][(counter)], 1)
173198157Srrs#define port_set_counter(port, counter, value) 	atomic_set_int(&port_counters[port][(counter)], (value))
174198157Srrs#else
175198626Srrs#define port_inc_counter(port, counter)	/* Nothing */
176198626Srrs#define port_set_counter(port, counter, value)	/* Nothing */
177198157Srrs#endif
178198157Srrs
179198157Srrsint xlr_rge_tx_prepend[MAXCPU];
180198157Srrsint xlr_rge_tx_done[MAXCPU];
181198157Srrsint xlr_rge_get_p2d_failed[MAXCPU];
182198157Srrsint xlr_rge_msg_snd_failed[MAXCPU];
183198157Srrsint xlr_rge_tx_ok_done[MAXCPU];
184198157Srrsint xlr_rge_rx_done[MAXCPU];
185198157Srrsint xlr_rge_repl_done[MAXCPU];
186198157Srrs
187198626Srrsstatic __inline__ unsigned int
188198157Srrsldadd_wu(unsigned int value, unsigned long *addr)
189198157Srrs{
190198626Srrs	__asm__ __volatile__(".set push\n"
191198626Srrs	            ".set noreorder\n"
192198626Srrs	            "move $8, %2\n"
193198626Srrs	            "move $9, %3\n"
194198626Srrs	/* "ldaddwu $8, $9\n" */
195198626Srrs	            ".word 0x71280011\n"
196198626Srrs	            "move %0, $8\n"
197198626Srrs	            ".set pop\n"
198198626Srrs	    :       "=&r"(value), "+m"(*addr)
199198626Srrs	    :       "0"(value), "r"((unsigned long)addr)
200198626Srrs	    :       "$8", "$9");
201198626Srrs
202198157Srrs	return value;
203198157Srrs}
204198157Srrs
205208165Srrsstatic __inline__ uint32_t
206208165Srrsxlr_enable_kx(void)
207208165Srrs{
208208165Srrs	uint32_t sr = mips_rd_status();
209208165Srrs
210208165Srrs	mips_wr_status((sr & ~MIPS_SR_INT_IE) | MIPS_SR_KX);
211208165Srrs	return sr;
212208165Srrs}
213208165Srrs
214198157Srrs/* #define mac_stats_add(x, val) ({(x) += (val);}) */
215198157Srrs#define mac_stats_add(x, val) ldadd_wu(val, &x)
216198157Srrs
217198157Srrs#define XLR_MAX_CORE 8
218198157Srrs#define RGE_LOCK_INIT(_sc, _name) \
219198157Srrs  mtx_init(&(_sc)->rge_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF)
220198157Srrs#define RGE_LOCK(_sc)   mtx_lock(&(_sc)->rge_mtx)
221198157Srrs#define RGE_LOCK_ASSERT(_sc)  mtx_assert(&(_sc)->rge_mtx, MA_OWNED)
222198157Srrs#define RGE_UNLOCK(_sc)   mtx_unlock(&(_sc)->rge_mtx)
223198157Srrs#define RGE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->rge_mtx)
224198157Srrs
225198157Srrs#define XLR_MAX_MACS     8
226198157Srrs#define XLR_MAX_TX_FRAGS 14
227198626Srrs#define MAX_P2D_DESC_PER_PORT 512
228198157Srrsstruct p2d_tx_desc {
229198626Srrs	uint64_t frag[XLR_MAX_TX_FRAGS + 2];
230198157Srrs};
231198626Srrs
232198157Srrs#define MAX_TX_RING_SIZE (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT * sizeof(struct p2d_tx_desc))
233198157Srrs
234198157Srrsstruct rge_softc *dev_mac[XLR_MAX_MACS];
235198626Srrsstatic int dev_mac_xgs0;
236198626Srrsstatic int dev_mac_gmac0;
237198157Srrs
238198626Srrsstatic int gmac_common_init_done;
239198157Srrs
240198157Srrs
241198626Srrsstatic int rge_probe(device_t);
242198626Srrsstatic int rge_attach(device_t);
243198626Srrsstatic int rge_detach(device_t);
244198626Srrsstatic int rge_suspend(device_t);
245198626Srrsstatic int rge_resume(device_t);
246198626Srrsstatic void rge_release_resources(struct rge_softc *);
247198626Srrsstatic void rge_rx(struct rge_softc *, vm_paddr_t paddr, int);
248198626Srrsstatic void rge_intr(void *);
249198626Srrsstatic void rge_start_locked(struct ifnet *, int);
250198626Srrsstatic void rge_start(struct ifnet *);
251198626Srrsstatic int rge_ioctl(struct ifnet *, u_long, caddr_t);
252198626Srrsstatic void rge_init(void *);
253198626Srrsstatic void rge_stop(struct rge_softc *);
254198626Srrsstatic int rge_shutdown(device_t);
255198626Srrsstatic void rge_reset(struct rge_softc *);
256198157Srrs
257198157Srrsstatic struct mbuf *get_mbuf(void);
258198626Srrsstatic void free_buf(vm_paddr_t paddr);
259198626Srrsstatic void *get_buf(void);
260198157Srrs
261198626Srrsstatic void xlr_mac_get_hwaddr(struct rge_softc *);
262198626Srrsstatic void xlr_mac_setup_hwaddr(struct driver_data *);
263198626Srrsstatic void rmi_xlr_mac_set_enable(struct driver_data *priv, int flag);
264198626Srrsstatic void rmi_xlr_xgmac_init(struct driver_data *priv);
265198626Srrsstatic void rmi_xlr_gmac_init(struct driver_data *priv);
266198626Srrsstatic void mac_common_init(void);
267198626Srrsstatic int rge_mii_write(device_t, int, int, int);
268198626Srrsstatic int rge_mii_read(device_t, int, int);
269198626Srrsstatic void rmi_xlr_mac_mii_statchg(device_t);
270198626Srrsstatic int rmi_xlr_mac_mediachange(struct ifnet *);
271198626Srrsstatic void rmi_xlr_mac_mediastatus(struct ifnet *, struct ifmediareq *);
272198626Srrsstatic void xlr_mac_set_rx_mode(struct rge_softc *sc);
273198626Srrsvoid
274198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code,
275198626Srrs    int stid, struct msgrng_msg *msg,
276198626Srrs    void *data);
277198626Srrsstatic void mac_frin_replenish(void *);
278198626Srrsstatic int rmi_xlr_mac_open(struct rge_softc *);
279198626Srrsstatic int rmi_xlr_mac_close(struct rge_softc *);
280198626Srrsstatic int
281198157Srrsmac_xmit(struct mbuf *, struct rge_softc *,
282198626Srrs    struct driver_data *, int, struct p2d_tx_desc *);
283198626Srrsstatic int rmi_xlr_mac_xmit(struct mbuf *, struct rge_softc *, int, struct p2d_tx_desc *);
284198157Srrsstatic struct rge_softc_stats *rmi_xlr_mac_get_stats(struct rge_softc *sc);
285198626Srrsstatic void rmi_xlr_mac_set_multicast_list(struct rge_softc *sc);
286198626Srrsstatic int rmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu);
287198626Srrsstatic int rmi_xlr_mac_fill_rxfr(struct rge_softc *sc);
288198626Srrsstatic void rmi_xlr_config_spill_area(struct driver_data *priv);
289198626Srrsstatic int rmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed);
290198626Srrsstatic int
291198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s,
292198626Srrs    xlr_mac_duplex_t duplex, xlr_mac_fc_t fc);
293198157Srrsstatic void serdes_regs_init(struct driver_data *priv);
294198157Srrsstatic int rmi_xlr_gmac_reset(struct driver_data *priv);
295198157Srrs
296198157Srrs/*Statistics...*/
297198157Srrsstatic int get_p2d_desc_failed = 0;
298198626Srrsstatic int msg_snd_failed = 0;
299198157Srrs
300198157SrrsSYSCTL_INT(_hw, OID_AUTO, get_p2d_failed, CTLFLAG_RW,
301198626Srrs    &get_p2d_desc_failed, 0, "p2d desc failed");
302198157SrrsSYSCTL_INT(_hw, OID_AUTO, msg_snd_failed, CTLFLAG_RW,
303198626Srrs    &msg_snd_failed, 0, "msg snd failed");
304198157Srrs
305198626Srrsstruct callout xlr_tx_stop_bkp;
306198157Srrs
307198157Srrsstatic device_method_t rge_methods[] = {
308198157Srrs	/* Device interface */
309198157Srrs	DEVMETHOD(device_probe, rge_probe),
310198157Srrs	DEVMETHOD(device_attach, rge_attach),
311198157Srrs	DEVMETHOD(device_detach, rge_detach),
312198157Srrs	DEVMETHOD(device_shutdown, rge_shutdown),
313198157Srrs	DEVMETHOD(device_suspend, rge_suspend),
314198157Srrs	DEVMETHOD(device_resume, rge_resume),
315198157Srrs
316198157Srrs	/* MII interface */
317198157Srrs	DEVMETHOD(miibus_readreg, rge_mii_read),
318198608Srrs	DEVMETHOD(miibus_statchg, rmi_xlr_mac_mii_statchg),
319198157Srrs	DEVMETHOD(miibus_writereg, rge_mii_write),
320198157Srrs	{0, 0}
321198157Srrs};
322198157Srrs
323198626Srrsstatic driver_t rge_driver = {
324198157Srrs	"rge",
325198157Srrs	rge_methods,
326198157Srrs	sizeof(struct rge_softc)
327198157Srrs};
328198157Srrs
329198157Srrsstatic devclass_t rge_devclass;
330198157Srrs
331198157SrrsDRIVER_MODULE(rge, iodi, rge_driver, rge_devclass, 0, 0);
332198157SrrsDRIVER_MODULE(miibus, rge, miibus_driver, miibus_devclass, 0, 0);
333198157Srrs
334198157Srrs#ifndef __STR
335198157Srrs#define __STR(x) #x
336198157Srrs#endif
337198157Srrs#ifndef STR
338198157Srrs#define STR(x) __STR(x)
339198157Srrs#endif
340198157Srrs
341198626Srrsvoid *xlr_tx_ring_mem;
342198157Srrs
343198157Srrsstruct tx_desc_node {
344198157Srrs	struct p2d_tx_desc *ptr;
345198626Srrs	            TAILQ_ENTRY(tx_desc_node) list;
346198157Srrs};
347198626Srrs
348198157Srrs#define XLR_MAX_TX_DESC_NODES (XLR_MAX_MACS * MAX_P2D_DESC_PER_PORT)
349198157Srrsstruct tx_desc_node tx_desc_nodes[XLR_MAX_TX_DESC_NODES];
350198157Srrsstatic volatile int xlr_tot_avail_p2d[XLR_MAX_CORE];
351198157Srrsstatic int xlr_total_active_core = 0;
352198157Srrs
353198157Srrs/*
354198157Srrs * This should contain the list of all free tx frag desc nodes pointing to tx
355198157Srrs * p2d arrays
356198157Srrs */
357198626Srrsstatic
358198157SrrsTAILQ_HEAD(, tx_desc_node) tx_frag_desc[XLR_MAX_CORE] =
359198626Srrs{
360198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[0]),
361198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[1]),
362198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[2]),
363198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[3]),
364198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[4]),
365198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[5]),
366198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[6]),
367198626Srrs	TAILQ_HEAD_INITIALIZER(tx_frag_desc[7]),
368198626Srrs};
369198157Srrs
370198157Srrs/* This contains a list of free tx frag node descriptors */
371199139Srrsstatic
372198626SrrsTAILQ_HEAD(, tx_desc_node) free_tx_frag_desc[XLR_MAX_CORE] =
373198626Srrs{
374198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[0]),
375198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[1]),
376198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[2]),
377198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[3]),
378198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[4]),
379198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[5]),
380198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[6]),
381198626Srrs	TAILQ_HEAD_INITIALIZER(free_tx_frag_desc[7]),
382198626Srrs};
383198157Srrs
384198157Srrsstatic struct mtx tx_desc_lock[XLR_MAX_CORE];
385198157Srrs
386198157Srrsstatic inline void
387198626Srrsmac_make_desc_rfr(struct msgrng_msg *msg,
388198626Srrs    vm_paddr_t addr)
389198157Srrs{
390198157Srrs	msg->msg0 = (uint64_t) addr & 0xffffffffe0ULL;
391198157Srrs	msg->msg1 = msg->msg2 = msg->msg3 = 0;
392198157Srrs}
393198157Srrs
394198157Srrs#define MAC_TX_DESC_ALIGNMENT (XLR_CACHELINE_SIZE - 1)
395198157Srrs
396198157Srrsstatic void
397198157Srrsinit_p2d_allocation(void)
398198157Srrs{
399198626Srrs	int active_core[8] = {0};
400198626Srrs	int i = 0;
401198157Srrs	uint32_t cpumask;
402198157Srrs	int cpu;
403198157Srrs
404208369Sjchandra	cpumask = xlr_hw_thread_mask;
405198157Srrs
406198157Srrs	for (i = 0; i < 32; i++) {
407198157Srrs		if (cpumask & (1 << i)) {
408208165Srrs			cpu = i;
409198626Srrs			if (!active_core[cpu / 4]) {
410198626Srrs				active_core[cpu / 4] = 1;
411198157Srrs				xlr_total_active_core++;
412198157Srrs			}
413198157Srrs		}
414198157Srrs	}
415198626Srrs	for (i = 0; i < XLR_MAX_CORE; i++) {
416198626Srrs		if (active_core[i])
417198626Srrs			xlr_tot_avail_p2d[i] = XLR_MAX_TX_DESC_NODES / xlr_total_active_core;
418198157Srrs	}
419198626Srrs	printf("Total Active Core %d\n", xlr_total_active_core);
420198157Srrs}
421198157Srrs
422198157Srrs
423198157Srrsstatic void
424198157Srrsinit_tx_ring(void)
425198157Srrs{
426198626Srrs	int i;
427198626Srrs	int j = 0;
428198157Srrs	struct tx_desc_node *start, *node;
429198157Srrs	struct p2d_tx_desc *tx_desc;
430198626Srrs	vm_paddr_t paddr;
431198626Srrs	vm_offset_t unmapped_addr;
432198157Srrs
433198626Srrs	for (i = 0; i < XLR_MAX_CORE; i++)
434198157Srrs		mtx_init(&tx_desc_lock[i], "xlr tx_desc", NULL, MTX_SPIN);
435198157Srrs
436198157Srrs	start = &tx_desc_nodes[0];
437198157Srrs	/* TODO: try to get this from KSEG0 */
438198157Srrs	xlr_tx_ring_mem = contigmalloc((MAX_TX_RING_SIZE + XLR_CACHELINE_SIZE),
439198626Srrs	    M_DEVBUF, M_NOWAIT | M_ZERO, 0,
440198626Srrs	    0x10000000, XLR_CACHELINE_SIZE, 0);
441198157Srrs
442198157Srrs	if (xlr_tx_ring_mem == NULL) {
443198157Srrs		panic("TX ring memory allocation failed");
444198157Srrs	}
445198626Srrs	paddr = vtophys((vm_offset_t)xlr_tx_ring_mem);
446198157Srrs
447198157Srrs	unmapped_addr = MIPS_PHYS_TO_KSEG0(paddr);
448198157Srrs
449198157Srrs
450198157Srrs	tx_desc = (struct p2d_tx_desc *)unmapped_addr;
451198157Srrs
452198157Srrs	for (i = 0; i < XLR_MAX_TX_DESC_NODES; i++) {
453198157Srrs		node = start + i;
454198157Srrs		node->ptr = tx_desc;
455198157Srrs		tx_desc++;
456198157Srrs		TAILQ_INSERT_HEAD(&tx_frag_desc[j], node, list);
457198626Srrs		j = (i / (XLR_MAX_TX_DESC_NODES / xlr_total_active_core));
458198157Srrs	}
459198157Srrs}
460198157Srrs
461198157Srrsstatic inline struct p2d_tx_desc *
462198157Srrsget_p2d_desc(void)
463198157Srrs{
464198157Srrs	struct tx_desc_node *node;
465198157Srrs	struct p2d_tx_desc *tx_desc = NULL;
466208165Srrs	int cpu = xlr_core_id();
467198157Srrs
468198157Srrs	mtx_lock_spin(&tx_desc_lock[cpu]);
469198157Srrs	node = TAILQ_FIRST(&tx_frag_desc[cpu]);
470198157Srrs	if (node) {
471198157Srrs		xlr_tot_avail_p2d[cpu]--;
472198157Srrs		TAILQ_REMOVE(&tx_frag_desc[cpu], node, list);
473198157Srrs		tx_desc = node->ptr;
474198157Srrs		TAILQ_INSERT_HEAD(&free_tx_frag_desc[cpu], node, list);
475198626Srrs	} else {
476198626Srrs		/* Increment p2d desc fail count */
477198157Srrs		get_p2d_desc_failed++;
478198157Srrs	}
479198157Srrs	mtx_unlock_spin(&tx_desc_lock[cpu]);
480198157Srrs	return tx_desc;
481198157Srrs}
482198626Srrsstatic void
483198157Srrsfree_p2d_desc(struct p2d_tx_desc *tx_desc)
484198157Srrs{
485198157Srrs	struct tx_desc_node *node;
486208165Srrs	int cpu = xlr_core_id();
487198157Srrs
488198157Srrs	mtx_lock_spin(&tx_desc_lock[cpu]);
489198157Srrs	node = TAILQ_FIRST(&free_tx_frag_desc[cpu]);
490198157Srrs	KASSERT((node != NULL), ("Free TX frag node list is empty\n"));
491198157Srrs
492198157Srrs	TAILQ_REMOVE(&free_tx_frag_desc[cpu], node, list);
493198157Srrs	node->ptr = tx_desc;
494198157Srrs	TAILQ_INSERT_HEAD(&tx_frag_desc[cpu], node, list);
495198157Srrs	xlr_tot_avail_p2d[cpu]++;
496198157Srrs	mtx_unlock_spin(&tx_desc_lock[cpu]);
497198157Srrs
498198157Srrs}
499198157Srrs
500198626Srrsstatic int
501198157Srrsbuild_frag_list(struct mbuf *m_head, struct msgrng_msg *p2p_msg, struct p2d_tx_desc *tx_desc)
502198157Srrs{
503198626Srrs	struct mbuf *m;
504198626Srrs	vm_paddr_t paddr;
505198626Srrs	uint64_t p2d_len;
506198626Srrs	int nfrag;
507198626Srrs	vm_paddr_t p1, p2;
508198626Srrs	uint32_t len1, len2;
509198626Srrs	vm_offset_t taddr;
510198626Srrs	uint64_t fr_stid;
511198626Srrs
512208165Srrs	fr_stid = (xlr_core_id() << 3) + xlr_thr_id() + 4;
513198157Srrs
514198157Srrs	if (tx_desc == NULL)
515198157Srrs		return 1;
516198157Srrs
517198157Srrs	nfrag = 0;
518198157Srrs	for (m = m_head; m != NULL; m = m->m_next) {
519198157Srrs		if ((nfrag + 1) >= XLR_MAX_TX_FRAGS) {
520198157Srrs			free_p2d_desc(tx_desc);
521198157Srrs			return 1;
522198157Srrs		}
523198157Srrs		if (m->m_len != 0) {
524198157Srrs			paddr = vtophys(mtod(m, vm_offset_t));
525198157Srrs			p1 = paddr + m->m_len;
526198626Srrs			p2 = vtophys(((vm_offset_t)m->m_data + m->m_len));
527198157Srrs			if (p1 != p2) {
528198157Srrs				len1 = (uint32_t)
529198626Srrs				    (PAGE_SIZE - (paddr & PAGE_MASK));
530198157Srrs				tx_desc->frag[nfrag] = (127ULL << 54) |
531198626Srrs				    ((uint64_t) len1 << 40) | paddr;
532198157Srrs				nfrag++;
533198626Srrs				taddr = (vm_offset_t)m->m_data + len1;
534198157Srrs				p2 = vtophys(taddr);
535198157Srrs				len2 = m->m_len - len1;
536203754Srrs				if (len2 == 0)
537203754Srrs					continue;
538198157Srrs				if (nfrag >= XLR_MAX_TX_FRAGS)
539198157Srrs					panic("TX frags exceeded");
540198157Srrs
541198157Srrs				tx_desc->frag[nfrag] = (127ULL << 54) |
542198626Srrs				    ((uint64_t) len2 << 40) | p2;
543198157Srrs
544198157Srrs				taddr += len2;
545198157Srrs				p1 = vtophys(taddr);
546198157Srrs
547198157Srrs				if ((p2 + len2) != p1) {
548198608Srrs					printf("p1 = %p p2 = %p\n", (void *)p1, (void *)p2);
549198157Srrs					printf("len1 = %x len2 = %x\n", len1,
550198626Srrs					    len2);
551198157Srrs					printf("m_data %p\n", m->m_data);
552198157Srrs					DELAY(1000000);
553198157Srrs					panic("Multiple Mbuf segment discontiguous\n");
554198157Srrs				}
555198157Srrs			} else {
556198157Srrs				tx_desc->frag[nfrag] = (127ULL << 54) |
557198626Srrs				    ((uint64_t) m->m_len << 40) | paddr;
558198157Srrs			}
559198157Srrs			nfrag++;
560198157Srrs		}
561198157Srrs	}
562198157Srrs	/* set eop in the last tx p2d desc */
563198157Srrs	tx_desc->frag[nfrag - 1] |= (1ULL << 63);
564198626Srrs	paddr = vtophys((vm_offset_t)tx_desc);
565198157Srrs	tx_desc->frag[nfrag] = (1ULL << 63) | (fr_stid << 54) | paddr;
566198157Srrs	nfrag++;
567210630Sjchandra	tx_desc->frag[XLR_MAX_TX_FRAGS] = (uint64_t)(intptr_t)tx_desc;
568210630Sjchandra	tx_desc->frag[XLR_MAX_TX_FRAGS + 1] = (uint64_t)(intptr_t)m_head;
569198157Srrs
570198157Srrs	p2d_len = (nfrag * 8);
571198157Srrs	p2p_msg->msg0 = (1ULL << 63) | (1ULL << 62) | (127ULL << 54) |
572198626Srrs	    (p2d_len << 40) | paddr;
573198157Srrs
574198157Srrs	return 0;
575198157Srrs}
576198626Srrsstatic void
577198157Srrsrelease_tx_desc(struct msgrng_msg *msg, int rel_buf)
578198157Srrs{
579199139Srrs	struct p2d_tx_desc *tx_desc, *chk_addr;
580198626Srrs	struct mbuf *m;
581198157Srrs
582199139Srrs	tx_desc = (struct p2d_tx_desc *)MIPS_PHYS_TO_KSEG0(msg->msg0);
583209808Sjchandra	chk_addr = (struct p2d_tx_desc *)(intptr_t)tx_desc->frag[XLR_MAX_TX_FRAGS];
584199139Srrs	if (tx_desc != chk_addr) {
585199139Srrs		printf("Address %p does not match with stored addr %p - we leaked a descriptor\n",
586199139Srrs		    tx_desc, chk_addr);
587199139Srrs		return;
588199139Srrs	}
589198157Srrs	if (rel_buf) {
590209808Sjchandra		m = (struct mbuf *)(intptr_t)tx_desc->frag[XLR_MAX_TX_FRAGS + 1];
591198157Srrs		m_freem(m);
592198157Srrs	}
593198157Srrs	free_p2d_desc(tx_desc);
594198157Srrs}
595198157Srrs
596198157Srrs
597198626Srrsstatic struct mbuf *
598198157Srrsget_mbuf(void)
599198157Srrs{
600198626Srrs	struct mbuf *m_new = NULL;
601198157Srrs
602198157Srrs	if ((m_new = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR)) == NULL)
603198157Srrs		return NULL;
604198157Srrs
605198157Srrs	m_new->m_len = MCLBYTES;
606198157Srrs	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
607198157Srrs	return m_new;
608198157Srrs}
609198157Srrs
610198626Srrsstatic void
611198157Srrsfree_buf(vm_paddr_t paddr)
612198157Srrs{
613198626Srrs	struct mbuf *m;
614210630Sjchandra	uint32_t mag;
615210630Sjchandra#ifdef __mips_n64
616210630Sjchandra	uint64_t *vaddr;
617198157Srrs
618210630Sjchandra	vaddr = (uint64_t *)MIPS_PHYS_TO_XKPHYS_CACHED(paddr);
619210630Sjchandra	m = (struct mbuf *)vaddr[0];
620210630Sjchandra	mag = (uint32_t)vaddr[1];
621210630Sjchandra#else
622210630Sjchandra	uint32_t sr;
623210630Sjchandra
624208165Srrs	sr = xlr_enable_kx();
625210630Sjchandra	m = (struct mbuf *)(intptr_t)xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t));
626210630Sjchandra	mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + 3 * sizeof(uint32_t));
627208165Srrs	mips_wr_status(sr);
628210630Sjchandra#endif
629208165Srrs
630199139Srrs	if (mag != 0xf00bad) {
631208165Srrs		printf("Something is wrong kseg:%lx found mag:%x not 0xf00bad\n",
632208165Srrs		    (u_long)paddr, mag);
633199139Srrs		return;
634199139Srrs	}
635198157Srrs	if (m != NULL)
636198157Srrs		m_freem(m);
637198157Srrs}
638198157Srrs
639198157Srrsstatic void *
640198157Srrsget_buf(void)
641198157Srrs{
642198626Srrs	struct mbuf *m_new = NULL;
643210630Sjchandra	uint64_t *md;
644198157Srrs#ifdef INVARIANTS
645198626Srrs	vm_paddr_t temp1, temp2;
646198157Srrs#endif
647198157Srrs
648198157Srrs	m_new = get_mbuf();
649198157Srrs	if (m_new == NULL)
650198157Srrs		return NULL;
651198157Srrs
652209808Sjchandra	m_adj(m_new, XLR_CACHELINE_SIZE - ((uintptr_t)m_new->m_data & 0x1f));
653210630Sjchandra	md = (uint64_t *)m_new->m_data;
654209808Sjchandra	md[0] = (uintptr_t)m_new;	/* Back Ptr */
655198157Srrs	md[1] = 0xf00bad;
656198157Srrs	m_adj(m_new, XLR_CACHELINE_SIZE);
657198157Srrs
658198157Srrs#ifdef INVARIANTS
659198626Srrs	temp1 = vtophys((vm_offset_t)m_new->m_data);
660198626Srrs	temp2 = vtophys((vm_offset_t)m_new->m_data + 1536);
661198157Srrs	if ((temp1 + 1536) != temp2)
662198157Srrs		panic("ALLOCED BUFFER IS NOT CONTIGUOUS\n");
663198157Srrs#endif
664198157Srrs	return (void *)m_new->m_data;
665198157Srrs}
666198157Srrs
667198157Srrs/**********************************************************************
668198157Srrs **********************************************************************/
669198626Srrsstatic void
670198157Srrsrmi_xlr_mac_set_enable(struct driver_data *priv, int flag)
671198157Srrs{
672198626Srrs	uint32_t regval;
673198626Srrs	int tx_threshold = 1518;
674198157Srrs
675198157Srrs	if (flag) {
676198157Srrs		regval = xlr_read_reg(priv->mmio, R_TX_CONTROL);
677198157Srrs		regval |= (1 << O_TX_CONTROL__TxEnable) |
678198626Srrs		    (tx_threshold << O_TX_CONTROL__TxThreshold);
679198157Srrs
680198157Srrs		xlr_write_reg(priv->mmio, R_TX_CONTROL, regval);
681198157Srrs
682198157Srrs		regval = xlr_read_reg(priv->mmio, R_RX_CONTROL);
683198157Srrs		regval |= 1 << O_RX_CONTROL__RxEnable;
684198157Srrs		if (priv->mode == XLR_PORT0_RGMII)
685198157Srrs			regval |= 1 << O_RX_CONTROL__RGMII;
686198157Srrs		xlr_write_reg(priv->mmio, R_RX_CONTROL, regval);
687198157Srrs
688198157Srrs		regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1);
689198157Srrs		regval |= (O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen);
690198157Srrs		xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval);
691198157Srrs	} else {
692198157Srrs		regval = xlr_read_reg(priv->mmio, R_TX_CONTROL);
693198157Srrs		regval &= ~((1 << O_TX_CONTROL__TxEnable) |
694198626Srrs		    (tx_threshold << O_TX_CONTROL__TxThreshold));
695198157Srrs
696198157Srrs		xlr_write_reg(priv->mmio, R_TX_CONTROL, regval);
697198157Srrs
698198157Srrs		regval = xlr_read_reg(priv->mmio, R_RX_CONTROL);
699198157Srrs		regval &= ~(1 << O_RX_CONTROL__RxEnable);
700198157Srrs		xlr_write_reg(priv->mmio, R_RX_CONTROL, regval);
701198157Srrs
702198157Srrs		regval = xlr_read_reg(priv->mmio, R_MAC_CONFIG_1);
703198157Srrs		regval &= ~(O_MAC_CONFIG_1__txen | O_MAC_CONFIG_1__rxen);
704198157Srrs		xlr_write_reg(priv->mmio, R_MAC_CONFIG_1, regval);
705198157Srrs	}
706198157Srrs}
707198157Srrs
708198157Srrs/**********************************************************************
709198157Srrs **********************************************************************/
710198626Srrsstatic __inline__ int
711198157Srrsxlr_mac_send_fr(struct driver_data *priv,
712198626Srrs    vm_paddr_t addr, int len)
713198157Srrs{
714212321Sjchandra	struct msgrng_msg msg;
715198626Srrs	int stid = priv->rfrbucket;
716212409Sjchandra	int code, ret;
717212321Sjchandra	uint32_t msgrng_flags;
718212409Sjchandra#ifdef INVARIANTS
719212409Sjchandra	int i = 0;
720212409Sjchandra#endif
721198157Srrs
722198626Srrs	mac_make_desc_rfr(&msg, addr);
723198157Srrs
724198157Srrs	/* Send the packet to MAC */
725208165Srrs	dbg_msg("mac_%d: Sending free packet %lx to stid %d\n",
726208165Srrs	    priv->instance, (u_long)addr, stid);
727212321Sjchandra	if (priv->type == XLR_XGMAC)
728212321Sjchandra		code = MSGRNG_CODE_XGMAC;        /* WHY? */
729212321Sjchandra	else
730212321Sjchandra		code = MSGRNG_CODE_MAC;
731198157Srrs
732212321Sjchandra	do {
733212321Sjchandra		msgrng_flags = msgrng_access_enable();
734212553Sjchandra		ret = message_send(1, code, stid, &msg);
735212321Sjchandra		msgrng_restore(msgrng_flags);
736212321Sjchandra		KASSERT(i++ < 100000, ("Too many credit fails\n"));
737212321Sjchandra	} while (ret != 0);
738212321Sjchandra
739198157Srrs	return 0;
740198157Srrs}
741198157Srrs
742198157Srrs/**************************************************************/
743198157Srrs
744198626Srrsstatic void
745198157Srrsxgmac_mdio_setup(volatile unsigned int *_mmio)
746198157Srrs{
747198626Srrs	int i;
748198626Srrs	uint32_t rd_data;
749198626Srrs
750198157Srrs	for (i = 0; i < 4; i++) {
751198157Srrs		rd_data = xmdio_read(_mmio, 1, 0x8000 + i);
752198157Srrs		rd_data = rd_data & 0xffffdfff;	/* clear isolate bit */
753198157Srrs		xmdio_write(_mmio, 1, 0x8000 + i, rd_data);
754198157Srrs	}
755198157Srrs}
756198157Srrs
757198157Srrs/**********************************************************************
758198157Srrs *  Init MII interface
759198157Srrs *
760198157Srrs *  Input parameters:
761198157Srrs *  	   s - priv structure
762198157Srrs ********************************************************************* */
763198157Srrs#define PHY_STATUS_RETRIES 25000
764198157Srrs
765198626Srrsstatic void
766198157Srrsrmi_xlr_mac_mii_init(struct driver_data *priv)
767198157Srrs{
768198626Srrs	xlr_reg_t *mii_mmio = priv->mii_mmio;
769198157Srrs
770198157Srrs	/* use the lowest clock divisor - divisor 28 */
771198157Srrs	xlr_write_reg(mii_mmio, R_MII_MGMT_CONFIG, 0x07);
772198157Srrs}
773198157Srrs
774198157Srrs/**********************************************************************
775198157Srrs *  Read a PHY register.
776198157Srrs *
777198157Srrs *  Input parameters:
778198157Srrs *  	   s - priv structure
779198157Srrs *  	   phyaddr - PHY's address
780198157Srrs *  	   regidx = index of register to read
781198157Srrs *
782198157Srrs *  Return value:
783198157Srrs *  	   value read, or 0 if an error occurred.
784198157Srrs ********************************************************************* */
785198157Srrs
786198626Srrsstatic int
787198626Srrsrge_mii_read_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx)
788198157Srrs{
789198626Srrs	int i = 0;
790198157Srrs
791198157Srrs	/* setup the phy reg to be used */
792198157Srrs	xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS,
793198626Srrs	    (phyaddr << 8) | (regidx << 0));
794198157Srrs	/* Issue the read command */
795198157Srrs	xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND,
796198626Srrs	    (1 << O_MII_MGMT_COMMAND__rstat));
797198157Srrs
798198157Srrs	/* poll for the read cycle to complete */
799198157Srrs	for (i = 0; i < PHY_STATUS_RETRIES; i++) {
800198157Srrs		if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0)
801198157Srrs			break;
802198157Srrs	}
803198157Srrs
804198157Srrs	/* clear the read cycle */
805198157Srrs	xlr_write_reg(mii_mmio, R_MII_MGMT_COMMAND, 0);
806198157Srrs
807198157Srrs	if (i == PHY_STATUS_RETRIES) {
808198157Srrs		return 0xffffffff;
809198157Srrs	}
810198157Srrs	/* Read the data back */
811198157Srrs	return xlr_read_reg(mii_mmio, R_MII_MGMT_STATUS);
812198157Srrs}
813198157Srrs
814198626Srrsstatic int
815198608Srrsrge_mii_read(device_t dev, int phyaddr, int regidx)
816198157Srrs{
817198157Srrs	struct rge_softc *sc = device_get_softc(dev);
818198626Srrs
819198157Srrs	return rge_mii_read_internal(sc->priv.mii_mmio, phyaddr, regidx);
820198157Srrs}
821198157Srrs
822198157Srrs/**********************************************************************
823198157Srrs *  Set MII hooks to newly selected media
824198157Srrs *
825198157Srrs *  Input parameters:
826198157Srrs *  	   ifp - Interface Pointer
827198157Srrs *
828198157Srrs *  Return value:
829198157Srrs *  	   nothing
830198157Srrs ********************************************************************* */
831198626Srrsstatic int
832198157Srrsrmi_xlr_mac_mediachange(struct ifnet *ifp)
833198157Srrs{
834198157Srrs	struct rge_softc *sc = ifp->if_softc;
835198157Srrs
836198157Srrs	if (ifp->if_flags & IFF_UP)
837198157Srrs		mii_mediachg(&sc->rge_mii);
838198157Srrs
839198157Srrs	return 0;
840198157Srrs}
841198157Srrs
842198157Srrs/**********************************************************************
843198157Srrs *  Get the current interface media status
844198157Srrs *
845198157Srrs *  Input parameters:
846198157Srrs *  	   ifp  - Interface Pointer
847198157Srrs *  	   ifmr - Interface media request ptr
848198157Srrs *
849198157Srrs *  Return value:
850198157Srrs *  	   nothing
851198157Srrs ********************************************************************* */
852198157Srrsstatic void
853198157Srrsrmi_xlr_mac_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
854198157Srrs{
855198157Srrs	struct rge_softc *sc = ifp->if_softc;
856198157Srrs
857198626Srrs	/* Check whether this is interface is active or not. */
858198157Srrs	ifmr->ifm_status = IFM_AVALID;
859198626Srrs	if (sc->link_up) {
860198157Srrs		ifmr->ifm_status |= IFM_ACTIVE;
861198626Srrs	} else {
862198157Srrs		ifmr->ifm_active = IFM_ETHER;
863198157Srrs	}
864198157Srrs}
865198157Srrs
866198157Srrs/**********************************************************************
867198157Srrs *  Write a value to a PHY register.
868198157Srrs *
869198157Srrs *  Input parameters:
870198157Srrs *  	   s - priv structure
871198157Srrs *  	   phyaddr - PHY to use
872198157Srrs *  	   regidx - register within the PHY
873198157Srrs *  	   regval - data to write to register
874198157Srrs *
875198157Srrs *  Return value:
876198157Srrs *  	   nothing
877198157Srrs ********************************************************************* */
878198608Srrsstatic void
879198626Srrsrge_mii_write_internal(xlr_reg_t * mii_mmio, int phyaddr, int regidx, int regval)
880198157Srrs{
881198626Srrs	int i = 0;
882198157Srrs
883198157Srrs	xlr_write_reg(mii_mmio, R_MII_MGMT_ADDRESS,
884198626Srrs	    (phyaddr << 8) | (regidx << 0));
885198157Srrs
886198157Srrs	/* Write the data which starts the write cycle */
887198157Srrs	xlr_write_reg(mii_mmio, R_MII_MGMT_WRITE_DATA, regval);
888198157Srrs
889198157Srrs	/* poll for the write cycle to complete */
890198157Srrs	for (i = 0; i < PHY_STATUS_RETRIES; i++) {
891198157Srrs		if (xlr_read_reg(mii_mmio, R_MII_MGMT_INDICATORS) == 0)
892198157Srrs			break;
893198157Srrs	}
894198157Srrs
895198157Srrs	return;
896198157Srrs}
897198157Srrs
898198608Srrsstatic int
899198608Srrsrge_mii_write(device_t dev, int phyaddr, int regidx, int regval)
900198157Srrs{
901198157Srrs	struct rge_softc *sc = device_get_softc(dev);
902198157Srrs
903198157Srrs	rge_mii_write_internal(sc->priv.mii_mmio, phyaddr, regidx, regval);
904198608Srrs	return (0);
905198157Srrs}
906198157Srrs
907198626Srrsstatic void
908198608Srrsrmi_xlr_mac_mii_statchg(struct device *dev)
909198157Srrs{
910198157Srrs}
911198157Srrs
912198157Srrsstatic void
913198157Srrsserdes_regs_init(struct driver_data *priv)
914198157Srrs{
915198626Srrs	xlr_reg_t *mmio_gpio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GPIO_OFFSET);
916198157Srrs
917198157Srrs	/* Initialize SERDES CONTROL Registers */
918198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 0, 0x6DB0);
919198626Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 1, 0xFFFF);
920198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 2, 0xB6D0);
921198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 3, 0x00FF);
922198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 4, 0x0000);
923198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 5, 0x0000);
924198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 6, 0x0005);
925198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 7, 0x0001);
926198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 8, 0x0000);
927198157Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 9, 0x0000);
928198626Srrs	rge_mii_write_internal(priv->serdes_mmio, 26, 10, 0x0000);
929198157Srrs
930198626Srrs	/*
931209318Sjchandra	 * GPIO setting which affect the serdes - needs figuring out
932198157Srrs	 */
933209318Sjchandra	DELAY(100);
934209318Sjchandra	xlr_write_reg(mmio_gpio, 0x20, 0x7e6802);
935209318Sjchandra	xlr_write_reg(mmio_gpio, 0x10, 0x7104);
936209318Sjchandra	DELAY(100);
937209318Sjchandra
938209318Sjchandra	/*
939209318Sjchandra	 * This kludge is needed to setup serdes (?) clock correctly on some
940209318Sjchandra	 * XLS boards
941209318Sjchandra	 */
942209318Sjchandra	if ((xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI ||
943209318Sjchandra	    xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XII) &&
944209318Sjchandra	    xlr_boot1_info.board_minor_version == 4) {
945209318Sjchandra		/* use 125 Mhz instead of 156.25Mhz ref clock */
946209318Sjchandra		DELAY(100);
947209318Sjchandra		xlr_write_reg(mmio_gpio, 0x10, 0x7103);
948209318Sjchandra		xlr_write_reg(mmio_gpio, 0x21, 0x7103);
949209318Sjchandra		DELAY(100);
950198626Srrs	}
951209318Sjchandra
952198157Srrs	return;
953198626Srrs}
954198157Srrs
955199139Srrsstatic void
956198626Srrsserdes_autoconfig(struct driver_data *priv)
957198157Srrs{
958198626Srrs	int delay = 100000;
959198157Srrs
960198626Srrs	/* Enable Auto negotiation in the PCS Layer */
961198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x1000);
962198626Srrs	DELAY(delay);
963198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 27, 0, 0x0200);
964198626Srrs	DELAY(delay);
965198157Srrs
966198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x1000);
967198626Srrs	DELAY(delay);
968198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 28, 0, 0x0200);
969198626Srrs	DELAY(delay);
970198157Srrs
971198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x1000);
972198626Srrs	DELAY(delay);
973198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 29, 0, 0x0200);
974198626Srrs	DELAY(delay);
975198157Srrs
976198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x1000);
977198626Srrs	DELAY(delay);
978198626Srrs	rge_mii_write_internal(priv->pcs_mmio, 30, 0, 0x0200);
979198626Srrs	DELAY(delay);
980198157Srrs
981198157Srrs}
982198157Srrs
983198157Srrs/*****************************************************************
984198157Srrs * Initialize GMAC
985198157Srrs *****************************************************************/
986198626Srrsstatic void
987198157Srrsrmi_xlr_config_pde(struct driver_data *priv)
988198157Srrs{
989198626Srrs	int i = 0, cpu = 0, bucket = 0;
990198626Srrs	uint64_t bucket_map = 0;
991198626Srrs
992198157Srrs	/* uint32_t desc_pack_ctrl = 0; */
993198626Srrs	uint32_t cpumask;
994198157Srrs
995208369Sjchandra	cpumask = 0x1;
996208165Srrs#ifdef SMP
997208165Srrs	/*
998208165Srrs         * rge may be called before SMP start in a BOOTP/NFSROOT
999208165Srrs         * setup. we will distribute packets to other cpus only when
1000208165Srrs         * the SMP is started.
1001208165Srrs	 */
1002208165Srrs	if (smp_started)
1003208369Sjchandra		cpumask = xlr_hw_thread_mask;
1004208165Srrs#endif
1005198157Srrs
1006208165Srrs	for (i = 0; i < MAXCPU; i++) {
1007198157Srrs		if (cpumask & (1 << i)) {
1008208165Srrs			cpu = i;
1009198626Srrs			bucket = ((cpu >> 2) << 3);
1010198157Srrs			bucket_map |= (1ULL << bucket);
1011198157Srrs		}
1012198157Srrs	}
1013209808Sjchandra	printf("rmi_xlr_config_pde: bucket_map=%jx\n", (uintmax_t)bucket_map);
1014198157Srrs
1015198157Srrs	/* bucket_map = 0x1; */
1016198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_0, (bucket_map & 0xffffffff));
1017198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_0 + 1,
1018198626Srrs	    ((bucket_map >> 32) & 0xffffffff));
1019198157Srrs
1020198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_1, (bucket_map & 0xffffffff));
1021198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_1 + 1,
1022198626Srrs	    ((bucket_map >> 32) & 0xffffffff));
1023198157Srrs
1024198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_2, (bucket_map & 0xffffffff));
1025198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_2 + 1,
1026198626Srrs	    ((bucket_map >> 32) & 0xffffffff));
1027198157Srrs
1028198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_3, (bucket_map & 0xffffffff));
1029198157Srrs	xlr_write_reg(priv->mmio, R_PDE_CLASS_3 + 1,
1030198626Srrs	    ((bucket_map >> 32) & 0xffffffff));
1031198157Srrs}
1032198157Srrs
1033198626Srrsstatic void
1034208165Srrsrge_smp_update_pde(void *dummy __unused)
1035208165Srrs{
1036208165Srrs	int i;
1037208165Srrs	struct driver_data *priv;
1038208165Srrs	struct rge_softc *sc;
1039208165Srrs
1040208165Srrs	printf("Updating packet distribution for SMP\n");
1041208165Srrs	for (i = 0; i < XLR_MAX_MACS; i++) {
1042208165Srrs		sc = dev_mac[i];
1043208165Srrs		if (!sc)
1044208165Srrs			continue;
1045208165Srrs		priv = &(sc->priv);
1046208165Srrs		rmi_xlr_mac_set_enable(priv, 0);
1047208165Srrs		rmi_xlr_config_pde(priv);
1048208165Srrs		rmi_xlr_mac_set_enable(priv, 1);
1049208165Srrs	}
1050208165Srrs}
1051208165Srrs
1052208165SrrsSYSINIT(rge_smp_update_pde, SI_SUB_SMP, SI_ORDER_ANY, rge_smp_update_pde, NULL);
1053208165Srrs
1054208165Srrs
1055208165Srrsstatic void
1056198157Srrsrmi_xlr_config_parser(struct driver_data *priv)
1057198157Srrs{
1058198157Srrs	/*
1059198157Srrs	 * Mark it as no classification The parser extract is gauranteed to
1060198157Srrs	 * be zero with no classfication
1061198157Srrs	 */
1062198157Srrs	xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x00);
1063198157Srrs
1064198157Srrs	xlr_write_reg(priv->mmio, R_L2TYPE_0, 0x01);
1065198157Srrs
1066198157Srrs	/* configure the parser : L2 Type is configured in the bootloader */
1067198157Srrs	/* extract IP: src, dest protocol */
1068198157Srrs	xlr_write_reg(priv->mmio, R_L3CTABLE,
1069198626Srrs	    (9 << 20) | (1 << 19) | (1 << 18) | (0x01 << 16) |
1070198626Srrs	    (0x0800 << 0));
1071198157Srrs	xlr_write_reg(priv->mmio, R_L3CTABLE + 1,
1072198626Srrs	    (12 << 25) | (4 << 21) | (16 << 14) | (4 << 10));
1073198157Srrs
1074198157Srrs}
1075198157Srrs
1076198626Srrsstatic void
1077198157Srrsrmi_xlr_config_classifier(struct driver_data *priv)
1078198157Srrs{
1079198626Srrs	int i = 0;
1080198157Srrs
1081198157Srrs	if (priv->type == XLR_XGMAC) {
1082198157Srrs		/* xgmac translation table doesn't have sane values on reset */
1083198157Srrs		for (i = 0; i < 64; i++)
1084198157Srrs			xlr_write_reg(priv->mmio, R_TRANSLATETABLE + i, 0x0);
1085198157Srrs
1086198157Srrs		/*
1087198157Srrs		 * use upper 7 bits of the parser extract to index the
1088198157Srrs		 * translate table
1089198157Srrs		 */
1090198157Srrs		xlr_write_reg(priv->mmio, R_PARSERCONFIGREG, 0x0);
1091198157Srrs	}
1092198157Srrs}
1093198157Srrs
1094198157Srrsenum {
1095198626Srrs	SGMII_SPEED_10 = 0x00000000,
1096198626Srrs	SGMII_SPEED_100 = 0x02000000,
1097198626Srrs	SGMII_SPEED_1000 = 0x04000000,
1098198157Srrs};
1099198157Srrs
1100198626Srrsstatic void
1101198157Srrsrmi_xlr_gmac_config_speed(struct driver_data *priv)
1102198157Srrs{
1103198157Srrs	int phy_addr = priv->phy_addr;
1104198626Srrs	xlr_reg_t *mmio = priv->mmio;
1105198157Srrs	struct rge_softc *sc = priv->sc;
1106198157Srrs
1107198157Srrs	priv->speed = rge_mii_read_internal(priv->mii_mmio, phy_addr, 28);
1108198157Srrs	priv->link = rge_mii_read_internal(priv->mii_mmio, phy_addr, 1) & 0x4;
1109198157Srrs	priv->speed = (priv->speed >> 3) & 0x03;
1110198157Srrs
1111198157Srrs	if (priv->speed == xlr_mac_speed_10) {
1112198157Srrs		if (priv->mode != XLR_RGMII)
1113198157Srrs			xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_10);
1114209318Sjchandra		xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117);
1115198157Srrs		xlr_write_reg(mmio, R_CORECONTROL, 0x02);
1116198157Srrs		printf("%s: [10Mbps]\n", device_get_nameunit(sc->rge_dev));
1117198626Srrs		sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX;
1118198157Srrs		sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX;
1119198626Srrs		sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10_T | IFM_FDX;
1120198157Srrs	} else if (priv->speed == xlr_mac_speed_100) {
1121198157Srrs		if (priv->mode != XLR_RGMII)
1122198157Srrs			xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100);
1123209318Sjchandra		xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117);
1124198157Srrs		xlr_write_reg(mmio, R_CORECONTROL, 0x01);
1125198157Srrs		printf("%s: [100Mbps]\n", device_get_nameunit(sc->rge_dev));
1126198157Srrs		sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX;
1127198157Srrs		sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX;
1128198157Srrs		sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX;
1129198157Srrs	} else {
1130198157Srrs		if (priv->speed != xlr_mac_speed_1000) {
1131198157Srrs			if (priv->mode != XLR_RGMII)
1132198157Srrs				xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_100);
1133198157Srrs			printf("PHY reported unknown MAC speed, defaulting to 100Mbps\n");
1134209318Sjchandra			xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7117);
1135198157Srrs			xlr_write_reg(mmio, R_CORECONTROL, 0x01);
1136198157Srrs			sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX;
1137198157Srrs			sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX;
1138198157Srrs			sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_100_TX | IFM_FDX;
1139198157Srrs		} else {
1140198157Srrs			if (priv->mode != XLR_RGMII)
1141198157Srrs				xlr_write_reg(mmio, R_INTERFACE_CONTROL, SGMII_SPEED_1000);
1142209318Sjchandra			xlr_write_reg(mmio, R_MAC_CONFIG_2, 0x7217);
1143198157Srrs			xlr_write_reg(mmio, R_CORECONTROL, 0x00);
1144198157Srrs			printf("%s: [1000Mbps]\n", device_get_nameunit(sc->rge_dev));
1145198157Srrs			sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX;
1146198157Srrs			sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX;
1147198157Srrs			sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_1000_T | IFM_FDX;
1148198157Srrs		}
1149198157Srrs	}
1150198626Srrs
1151198157Srrs	if (!priv->link) {
1152198157Srrs		sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER;
1153198157Srrs		sc->link_up = 0;
1154198157Srrs	} else {
1155198157Srrs		sc->link_up = 1;
1156198157Srrs	}
1157198157Srrs}
1158198157Srrs
1159198157Srrs/*****************************************************************
1160198157Srrs * Initialize XGMAC
1161198157Srrs *****************************************************************/
1162198626Srrsstatic void
1163198157Srrsrmi_xlr_xgmac_init(struct driver_data *priv)
1164198157Srrs{
1165198626Srrs	int i = 0;
1166198626Srrs	xlr_reg_t *mmio = priv->mmio;
1167198626Srrs	int id = priv->instance;
1168198157Srrs	struct rge_softc *sc = priv->sc;
1169198157Srrs	volatile unsigned short *cpld;
1170198157Srrs
1171198157Srrs	cpld = (volatile unsigned short *)0xBD840000;
1172198157Srrs
1173198157Srrs	xlr_write_reg(priv->mmio, R_DESC_PACK_CTRL,
1174198626Srrs	    (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize) | (4 << 20));
1175198157Srrs	xlr_write_reg(priv->mmio, R_BYTEOFFSET0, BYTE_OFFSET);
1176198157Srrs	rmi_xlr_config_pde(priv);
1177198157Srrs	rmi_xlr_config_parser(priv);
1178198157Srrs	rmi_xlr_config_classifier(priv);
1179198157Srrs
1180198157Srrs	xlr_write_reg(priv->mmio, R_MSG_TX_THRESHOLD, 1);
1181198157Srrs
1182198157Srrs	/* configure the XGMAC Registers */
1183198157Srrs	xlr_write_reg(mmio, R_XGMAC_CONFIG_1, 0x50000026);
1184198157Srrs
1185198157Srrs	/* configure the XGMAC_GLUE Registers */
1186198157Srrs	xlr_write_reg(mmio, R_DMACR0, 0xffffffff);
1187198157Srrs	xlr_write_reg(mmio, R_DMACR1, 0xffffffff);
1188198157Srrs	xlr_write_reg(mmio, R_DMACR2, 0xffffffff);
1189198157Srrs	xlr_write_reg(mmio, R_DMACR3, 0xffffffff);
1190198157Srrs	xlr_write_reg(mmio, R_STATCTRL, 0x04);
1191198157Srrs	xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff);
1192198157Srrs
1193198157Srrs	xlr_write_reg(mmio, R_XGMACPADCALIBRATION, 0x030);
1194198157Srrs	xlr_write_reg(mmio, R_EGRESSFIFOCARVINGSLOTS, 0x0f);
1195198157Srrs	xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff);
1196198157Srrs	xlr_write_reg(mmio, R_XGMAC_MIIM_CONFIG, 0x3e);
1197198157Srrs
1198198157Srrs	/*
1199198157Srrs	 * take XGMII phy out of reset
1200198157Srrs	 */
1201198157Srrs	/*
1202198157Srrs	 * we are pulling everything out of reset because writing a 0 would
1203198157Srrs	 * reset other devices on the chip
1204198157Srrs	 */
1205198157Srrs	cpld[ATX_CPLD_RESET_1] = 0xffff;
1206198157Srrs	cpld[ATX_CPLD_MISC_CTRL] = 0xffff;
1207198157Srrs	cpld[ATX_CPLD_RESET_2] = 0xffff;
1208198157Srrs
1209198157Srrs	xgmac_mdio_setup(mmio);
1210198157Srrs
1211198157Srrs	rmi_xlr_config_spill_area(priv);
1212198157Srrs
1213198157Srrs	if (id == 0) {
1214198157Srrs		for (i = 0; i < 16; i++) {
1215198157Srrs			xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i,
1216198626Srrs			    bucket_sizes.
1217198626Srrs			    bucket[MSGRNG_STNID_XGS0_TX + i]);
1218198157Srrs		}
1219198157Srrs
1220198157Srrs		xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE,
1221198626Srrs		    bucket_sizes.bucket[MSGRNG_STNID_XMAC0JFR]);
1222198157Srrs		xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE,
1223198626Srrs		    bucket_sizes.bucket[MSGRNG_STNID_XMAC0RFR]);
1224198157Srrs
1225198157Srrs		for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) {
1226198157Srrs			xlr_write_reg(mmio, R_CC_CPU0_0 + i,
1227198626Srrs			    cc_table_xgs_0.
1228198626Srrs			    counters[i >> 3][i & 0x07]);
1229198157Srrs		}
1230198157Srrs	} else if (id == 1) {
1231198157Srrs		for (i = 0; i < 16; i++) {
1232198157Srrs			xlr_write_reg(mmio, R_XGS_TX0_BUCKET_SIZE + i,
1233198626Srrs			    bucket_sizes.
1234198626Srrs			    bucket[MSGRNG_STNID_XGS1_TX + i]);
1235198157Srrs		}
1236198157Srrs
1237198157Srrs		xlr_write_reg(mmio, R_XGS_JFR_BUCKET_SIZE,
1238198626Srrs		    bucket_sizes.bucket[MSGRNG_STNID_XMAC1JFR]);
1239198157Srrs		xlr_write_reg(mmio, R_XGS_RFR_BUCKET_SIZE,
1240198626Srrs		    bucket_sizes.bucket[MSGRNG_STNID_XMAC1RFR]);
1241198157Srrs
1242198157Srrs		for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) {
1243198157Srrs			xlr_write_reg(mmio, R_CC_CPU0_0 + i,
1244198626Srrs			    cc_table_xgs_1.
1245198626Srrs			    counters[i >> 3][i & 0x07]);
1246198157Srrs		}
1247198157Srrs	}
1248198157Srrs	sc->rge_mii.mii_media.ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX;
1249198157Srrs	sc->rge_mii.mii_media.ifm_media |= (IFM_AVALID | IFM_ACTIVE);
1250198157Srrs	sc->rge_mii.mii_media.ifm_cur->ifm_media = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX;
1251198157Srrs	sc->rge_mii.mii_media_active = IFM_ETHER | IFM_AUTO | IFM_10G_SR | IFM_FDX;
1252198157Srrs	sc->rge_mii.mii_media.ifm_cur->ifm_media |= (IFM_AVALID | IFM_ACTIVE);
1253198157Srrs
1254198157Srrs	priv->init_frin_desc = 1;
1255198157Srrs}
1256198157Srrs
1257198157Srrs/*******************************************************
1258198157Srrs * Initialization gmac
1259198157Srrs *******************************************************/
1260198157Srrsstatic int
1261198157Srrsrmi_xlr_gmac_reset(struct driver_data *priv)
1262198157Srrs{
1263198157Srrs	volatile uint32_t val;
1264198157Srrs	xlr_reg_t *mmio = priv->mmio;
1265198157Srrs	int i, maxloops = 100;
1266198157Srrs
1267198626Srrs	/* Disable MAC RX */
1268198626Srrs	val = xlr_read_reg(mmio, R_MAC_CONFIG_1);
1269198626Srrs	val &= ~0x4;
1270198626Srrs	xlr_write_reg(mmio, R_MAC_CONFIG_1, val);
1271198157Srrs
1272198626Srrs	/* Disable Core RX */
1273198626Srrs	val = xlr_read_reg(mmio, R_RX_CONTROL);
1274198626Srrs	val &= ~0x1;
1275198626Srrs	xlr_write_reg(mmio, R_RX_CONTROL, val);
1276198157Srrs
1277198626Srrs	/* wait for rx to halt */
1278198626Srrs	for (i = 0; i < maxloops; i++) {
1279198626Srrs		val = xlr_read_reg(mmio, R_RX_CONTROL);
1280198626Srrs		if (val & 0x2)
1281198626Srrs			break;
1282198626Srrs		DELAY(1000);
1283198626Srrs	}
1284198157Srrs	if (i == maxloops)
1285198157Srrs		return -1;
1286198157Srrs
1287198626Srrs	/* Issue a soft reset */
1288198626Srrs	val = xlr_read_reg(mmio, R_RX_CONTROL);
1289198626Srrs	val |= 0x4;
1290198626Srrs	xlr_write_reg(mmio, R_RX_CONTROL, val);
1291198626Srrs
1292198626Srrs	/* wait for reset to complete */
1293198626Srrs	for (i = 0; i < maxloops; i++) {
1294198626Srrs		val = xlr_read_reg(mmio, R_RX_CONTROL);
1295198626Srrs		if (val & 0x8)
1296198626Srrs			break;
1297198626Srrs		DELAY(1000);
1298198626Srrs	}
1299198157Srrs	if (i == maxloops)
1300198157Srrs		return -1;
1301198157Srrs
1302198626Srrs	/* Clear the soft reset bit */
1303198626Srrs	val = xlr_read_reg(mmio, R_RX_CONTROL);
1304198626Srrs	val &= ~0x4;
1305198626Srrs	xlr_write_reg(mmio, R_RX_CONTROL, val);
1306198157Srrs	return 0;
1307198157Srrs}
1308198157Srrs
1309198626Srrsstatic void
1310198157Srrsrmi_xlr_gmac_init(struct driver_data *priv)
1311198157Srrs{
1312198626Srrs	int i = 0;
1313198626Srrs	xlr_reg_t *mmio = priv->mmio;
1314198626Srrs	int id = priv->instance;
1315198157Srrs	struct stn_cc *gmac_cc_config;
1316198626Srrs	uint32_t value = 0;
1317198626Srrs	int blk = id / 4, port = id % 4;
1318198157Srrs
1319198157Srrs	rmi_xlr_mac_set_enable(priv, 0);
1320198157Srrs
1321198157Srrs	rmi_xlr_config_spill_area(priv);
1322198157Srrs
1323198157Srrs	xlr_write_reg(mmio, R_DESC_PACK_CTRL,
1324198626Srrs	    (BYTE_OFFSET << O_DESC_PACK_CTRL__ByteOffset) |
1325198626Srrs	    (1 << O_DESC_PACK_CTRL__MaxEntry) |
1326198626Srrs	    (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize));
1327198157Srrs
1328198157Srrs	rmi_xlr_config_pde(priv);
1329198157Srrs	rmi_xlr_config_parser(priv);
1330198157Srrs	rmi_xlr_config_classifier(priv);
1331198157Srrs
1332198157Srrs	xlr_write_reg(mmio, R_MSG_TX_THRESHOLD, 3);
1333198157Srrs	xlr_write_reg(mmio, R_MAC_CONFIG_1, 0x35);
1334198626Srrs	xlr_write_reg(mmio, R_RX_CONTROL, (0x7 << 6));
1335198157Srrs
1336198626Srrs	if (priv->mode == XLR_PORT0_RGMII) {
1337198157Srrs		printf("Port 0 set in RGMII mode\n");
1338198157Srrs		value = xlr_read_reg(mmio, R_RX_CONTROL);
1339198157Srrs		value |= 1 << O_RX_CONTROL__RGMII;
1340198157Srrs		xlr_write_reg(mmio, R_RX_CONTROL, value);
1341198157Srrs	}
1342198157Srrs	rmi_xlr_mac_mii_init(priv);
1343198157Srrs
1344198626Srrs
1345198157Srrs#if 0
1346198157Srrs	priv->advertising = ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half |
1347198626Srrs	    ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half |
1348198626Srrs	    ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg |
1349198626Srrs	    ADVERTISED_MII;
1350198157Srrs#endif
1351198157Srrs
1352198157Srrs	/*
1353198157Srrs	 * Enable all MDIO interrupts in the phy RX_ER bit seems to be get
1354198157Srrs	 * set about every 1 sec in GigE mode, ignore it for now...
1355198157Srrs	 */
1356198157Srrs	rge_mii_write_internal(priv->mii_mmio, priv->phy_addr, 25, 0xfffffffe);
1357198157Srrs
1358198626Srrs	if (priv->mode != XLR_RGMII) {
1359198157Srrs		serdes_regs_init(priv);
1360198157Srrs		serdes_autoconfig(priv);
1361198157Srrs	}
1362198626Srrs	rmi_xlr_gmac_config_speed(priv);
1363198157Srrs
1364198157Srrs	value = xlr_read_reg(mmio, R_IPG_IFG);
1365198157Srrs	xlr_write_reg(mmio, R_IPG_IFG, ((value & ~0x7f) | MAC_B2B_IPG));
1366198157Srrs	xlr_write_reg(mmio, R_DMACR0, 0xffffffff);
1367198157Srrs	xlr_write_reg(mmio, R_DMACR1, 0xffffffff);
1368198157Srrs	xlr_write_reg(mmio, R_DMACR2, 0xffffffff);
1369198157Srrs	xlr_write_reg(mmio, R_DMACR3, 0xffffffff);
1370198157Srrs	xlr_write_reg(mmio, R_STATCTRL, 0x04);
1371198157Srrs	xlr_write_reg(mmio, R_L2ALLOCCTRL, 0xffffffff);
1372198157Srrs	xlr_write_reg(mmio, R_INTMASK, 0);
1373198157Srrs	xlr_write_reg(mmio, R_FREEQCARVE, 0);
1374198157Srrs
1375198157Srrs	xlr_write_reg(mmio, R_GMAC_TX0_BUCKET_SIZE + port,
1376198626Srrs	    xlr_board_info.bucket_sizes->bucket[priv->txbucket]);
1377198157Srrs	xlr_write_reg(mmio, R_GMAC_JFR0_BUCKET_SIZE,
1378198626Srrs	    xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_0]);
1379198157Srrs	xlr_write_reg(mmio, R_GMAC_RFR0_BUCKET_SIZE,
1380198626Srrs	    xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_0]);
1381198157Srrs	xlr_write_reg(mmio, R_GMAC_JFR1_BUCKET_SIZE,
1382198626Srrs	    xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_1]);
1383198157Srrs	xlr_write_reg(mmio, R_GMAC_RFR1_BUCKET_SIZE,
1384198626Srrs	    xlr_board_info.bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_1]);
1385198157Srrs
1386198157Srrs	dbg_msg("Programming credit counter %d : %d -> %d\n", blk, R_GMAC_TX0_BUCKET_SIZE + port,
1387198626Srrs	    xlr_board_info.bucket_sizes->bucket[priv->txbucket]);
1388198157Srrs
1389198157Srrs	gmac_cc_config = xlr_board_info.gmac_block[blk].credit_config;
1390198157Srrs	for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) {
1391198157Srrs		xlr_write_reg(mmio, R_CC_CPU0_0 + i,
1392198626Srrs		    gmac_cc_config->counters[i >> 3][i & 0x07]);
1393198157Srrs		dbg_msg("%d: %d -> %d\n", priv->instance,
1394198626Srrs		    R_CC_CPU0_0 + i, gmac_cc_config->counters[i >> 3][i & 0x07]);
1395198157Srrs	}
1396198157Srrs	priv->init_frin_desc = 1;
1397198157Srrs}
1398198157Srrs
1399198157Srrs/**********************************************************************
1400198157Srrs * Set promiscuous mode
1401198157Srrs **********************************************************************/
1402198626Srrsstatic void
1403198157Srrsxlr_mac_set_rx_mode(struct rge_softc *sc)
1404198157Srrs{
1405198157Srrs	struct driver_data *priv = &(sc->priv);
1406198626Srrs	uint32_t regval;
1407198157Srrs
1408198157Srrs	regval = xlr_read_reg(priv->mmio, R_MAC_FILTER_CONFIG);
1409198626Srrs
1410198157Srrs	if (sc->flags & IFF_PROMISC) {
1411198157Srrs		regval |= (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) |
1412198626Srrs		    (1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) |
1413198626Srrs		    (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) |
1414198626Srrs		    (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN);
1415198157Srrs	} else {
1416198157Srrs		regval &= ~((1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) |
1417198626Srrs		    (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN));
1418198157Srrs	}
1419198157Srrs
1420198157Srrs	xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG, regval);
1421198157Srrs}
1422198157Srrs
1423198157Srrs/**********************************************************************
1424198157Srrs *  Configure LAN speed for the specified MAC.
1425198157Srrs ********************************************************************* */
1426198626Srrsstatic int
1427198157Srrsrmi_xlr_mac_set_speed(struct driver_data *s, xlr_mac_speed_t speed)
1428198157Srrs{
1429198157Srrs	return 0;
1430198157Srrs}
1431198157Srrs
1432198157Srrs/**********************************************************************
1433198157Srrs *  Set Ethernet duplex and flow control options for this MAC
1434198157Srrs ********************************************************************* */
1435198626Srrsstatic int
1436198157Srrsrmi_xlr_mac_set_duplex(struct driver_data *s,
1437198626Srrs    xlr_mac_duplex_t duplex, xlr_mac_fc_t fc)
1438198157Srrs{
1439198157Srrs	return 0;
1440198157Srrs}
1441198157Srrs
1442198157Srrs/*****************************************************************
1443198157Srrs * Kernel Net Stack <-> MAC Driver Interface
1444198157Srrs *****************************************************************/
1445198157Srrs/**********************************************************************
1446198157Srrs **********************************************************************/
1447198157Srrs#define MAC_TX_FAIL 2
1448198157Srrs#define MAC_TX_PASS 0
1449198157Srrs#define MAC_TX_RETRY 1
1450198157Srrs
1451198626Srrsint xlr_dev_queue_xmit_hack = 0;
1452198157Srrs
1453198626Srrsstatic int
1454198157Srrsmac_xmit(struct mbuf *m, struct rge_softc *sc,
1455198626Srrs    struct driver_data *priv, int len, struct p2d_tx_desc *tx_desc)
1456198157Srrs{
1457212321Sjchandra	struct msgrng_msg msg = {0,0,0,0};
1458198626Srrs	int stid = priv->txbucket;
1459198626Srrs	uint32_t tx_cycles = 0;
1460212321Sjchandra	uint32_t mflags;
1461208369Sjchandra	int vcpu = xlr_cpu_id();
1462198157Srrs	int rv;
1463198157Srrs
1464198157Srrs	tx_cycles = mips_rd_count();
1465198157Srrs
1466198157Srrs	if (build_frag_list(m, &msg, tx_desc) != 0)
1467198157Srrs		return MAC_TX_FAIL;
1468198157Srrs
1469198157Srrs	else {
1470212321Sjchandra		mflags = msgrng_access_enable();
1471212553Sjchandra		if ((rv = message_send(1, MSGRNG_CODE_MAC, stid, &msg)) != 0) {
1472198157Srrs			msg_snd_failed++;
1473212321Sjchandra			msgrng_restore(mflags);
1474198157Srrs			release_tx_desc(&msg, 0);
1475198157Srrs			xlr_rge_msg_snd_failed[vcpu]++;
1476209808Sjchandra			dbg_msg("Failed packet to cpu %d, rv = %d, stid %d, msg0=%jx\n",
1477209808Sjchandra			    vcpu, rv, stid, (uintmax_t)msg.msg0);
1478198157Srrs			return MAC_TX_FAIL;
1479198157Srrs		}
1480212321Sjchandra		msgrng_restore(mflags);
1481198157Srrs		port_inc_counter(priv->instance, PORT_TX);
1482198157Srrs	}
1483198157Srrs
1484198157Srrs	/* Send the packet to MAC */
1485209808Sjchandra	dbg_msg("Sent tx packet to stid %d, msg0=%jx, msg1=%jx \n", stid,
1486209808Sjchandra	    (uintmax_t)msg.msg0, (uintmax_t)msg.msg1);
1487198157Srrs#ifdef DUMP_PACKETS
1488198157Srrs	{
1489198626Srrs		int i = 0;
1490198626Srrs		unsigned char *buf = (char *)m->m_data;
1491198626Srrs
1492198157Srrs		printf("Tx Packet: length=%d\n", len);
1493198157Srrs		for (i = 0; i < 64; i++) {
1494198157Srrs			if (i && (i % 16) == 0)
1495198157Srrs				printf("\n");
1496198157Srrs			printf("%02x ", buf[i]);
1497198157Srrs		}
1498198157Srrs		printf("\n");
1499198157Srrs	}
1500198157Srrs#endif
1501198157Srrs	xlr_inc_counter(NETIF_TX);
1502198157Srrs	return MAC_TX_PASS;
1503198157Srrs}
1504198157Srrs
1505198626Srrsstatic int
1506198157Srrsrmi_xlr_mac_xmit(struct mbuf *m, struct rge_softc *sc, int len, struct p2d_tx_desc *tx_desc)
1507198157Srrs{
1508198157Srrs	struct driver_data *priv = &(sc->priv);
1509198626Srrs	int ret = -ENOSPC;
1510198157Srrs
1511198157Srrs	dbg_msg("IN\n");
1512198157Srrs
1513198157Srrs	xlr_inc_counter(NETIF_STACK_TX);
1514198157Srrs
1515198157Srrsretry:
1516198157Srrs	ret = mac_xmit(m, sc, priv, len, tx_desc);
1517198157Srrs
1518198157Srrs	if (ret == MAC_TX_RETRY)
1519198157Srrs		goto retry;
1520198157Srrs
1521198157Srrs	dbg_msg("OUT, ret = %d\n", ret);
1522198157Srrs	if (ret == MAC_TX_FAIL) {
1523198157Srrs		/* FULL */
1524198157Srrs		dbg_msg("Msg Ring Full. Stopping upper layer Q\n");
1525198157Srrs		port_inc_counter(priv->instance, PORT_STOPQ);
1526198157Srrs	}
1527198157Srrs	return ret;
1528198157Srrs}
1529198157Srrs
1530198626Srrsstatic void
1531198157Srrsmac_frin_replenish(void *args /* ignored */ )
1532198157Srrs{
1533208165Srrs	int cpu = xlr_core_id();
1534198626Srrs	int done = 0;
1535198626Srrs	int i = 0;
1536198157Srrs
1537198157Srrs	xlr_inc_counter(REPLENISH_ENTER);
1538198157Srrs	/*
1539198157Srrs	 * xlr_set_counter(REPLENISH_ENTER_COUNT,
1540198157Srrs	 * atomic_read(frin_to_be_sent));
1541198157Srrs	 */
1542198157Srrs	xlr_set_counter(REPLENISH_CPU, PCPU_GET(cpuid));
1543198157Srrs
1544198157Srrs	for (;;) {
1545198157Srrs
1546198157Srrs		done = 0;
1547198157Srrs
1548198157Srrs		for (i = 0; i < XLR_MAX_MACS; i++) {
1549198157Srrs			/* int offset = 0; */
1550198626Srrs			void *m;
1551198626Srrs			uint32_t cycles;
1552198157Srrs			struct rge_softc *sc;
1553198157Srrs			struct driver_data *priv;
1554198626Srrs			int frin_to_be_sent;
1555198157Srrs
1556198157Srrs			sc = dev_mac[i];
1557198157Srrs			if (!sc)
1558198157Srrs				goto skip;
1559198157Srrs
1560198157Srrs			priv = &(sc->priv);
1561198157Srrs			frin_to_be_sent = priv->frin_to_be_sent[cpu];
1562198157Srrs
1563198157Srrs			/* if (atomic_read(frin_to_be_sent) < 0) */
1564198157Srrs			if (frin_to_be_sent < 0) {
1565198626Srrs				panic("BUG?: [%s]: gmac_%d illegal value for frin_to_be_sent=%d\n",
1566198626Srrs				    __FUNCTION__, i,
1567198626Srrs				    frin_to_be_sent);
1568198157Srrs			}
1569198157Srrs			/* if (!atomic_read(frin_to_be_sent)) */
1570198157Srrs			if (!frin_to_be_sent)
1571198157Srrs				goto skip;
1572198157Srrs
1573198157Srrs			cycles = mips_rd_count();
1574198157Srrs			{
1575198157Srrs				m = get_buf();
1576198157Srrs				if (!m) {
1577198157Srrs					device_printf(sc->rge_dev, "No buffer\n");
1578198157Srrs					goto skip;
1579198157Srrs				}
1580198157Srrs			}
1581198157Srrs			xlr_inc_counter(REPLENISH_FRIN);
1582198157Srrs			if (xlr_mac_send_fr(priv, vtophys(m), MAX_FRAME_SIZE)) {
1583198157Srrs				free_buf(vtophys(m));
1584198157Srrs				printf("[%s]: rx free message_send failed!\n", __FUNCTION__);
1585198157Srrs				break;
1586198157Srrs			}
1587198157Srrs			xlr_set_counter(REPLENISH_CYCLES,
1588198626Srrs			    (read_c0_count() - cycles));
1589198157Srrs			atomic_subtract_int((&priv->frin_to_be_sent[cpu]), 1);
1590198157Srrs
1591198157Srrs			continue;
1592198157Srrs	skip:
1593198157Srrs			done++;
1594198157Srrs		}
1595198157Srrs		if (done == XLR_MAX_MACS)
1596198157Srrs			break;
1597198157Srrs	}
1598198157Srrs}
1599198157Srrs
1600203010Srrsstatic volatile uint32_t g_tx_frm_tx_ok=0;
1601198157Srrs
1602198626Srrsstatic void
1603198157Srrsrge_tx_bkp_func(void *arg, int npending)
1604198157Srrs{
1605198626Srrs	int i = 0;
1606198626Srrs
1607198626Srrs	for (i = 0; i < xlr_board_info.gmacports; i++) {
1608198157Srrs		if (!dev_mac[i] || !dev_mac[i]->active)
1609198157Srrs			continue;
1610198157Srrs		rge_start_locked(dev_mac[i]->rge_ifp, RGE_TX_THRESHOLD);
1611198157Srrs	}
1612198157Srrs	atomic_subtract_int(&g_tx_frm_tx_ok, 1);
1613198157Srrs}
1614198157Srrs
1615198157Srrs/* This function is called from an interrupt handler */
1616198626Srrsvoid
1617198157Srrsrmi_xlr_mac_msgring_handler(int bucket, int size, int code,
1618198626Srrs    int stid, struct msgrng_msg *msg,
1619198626Srrs    void *data /* ignored */ )
1620198157Srrs{
1621198626Srrs	uint64_t phys_addr = 0;
1622198626Srrs	unsigned long addr = 0;
1623198626Srrs	uint32_t length = 0;
1624198626Srrs	int ctrl = 0, port = 0;
1625198157Srrs	struct rge_softc *sc = NULL;
1626198157Srrs	struct driver_data *priv = 0;
1627198626Srrs	struct ifnet *ifp;
1628208165Srrs	int vcpu = xlr_cpu_id();
1629208165Srrs	int cpu = xlr_core_id();
1630198157Srrs
1631209808Sjchandra	dbg_msg("mac: bucket=%d, size=%d, code=%d, stid=%d, msg0=%jx msg1=%jx\n",
1632209808Sjchandra	    bucket, size, code, stid, (uintmax_t)msg->msg0, (uintmax_t)msg->msg1);
1633198157Srrs
1634198157Srrs	phys_addr = (uint64_t) (msg->msg0 & 0xffffffffe0ULL);
1635198157Srrs	length = (msg->msg0 >> 40) & 0x3fff;
1636198157Srrs	if (length == 0) {
1637198157Srrs		ctrl = CTRL_REG_FREE;
1638198157Srrs		port = (msg->msg0 >> 54) & 0x0f;
1639198157Srrs		addr = 0;
1640198157Srrs	} else {
1641198157Srrs		ctrl = CTRL_SNGL;
1642198157Srrs		length = length - BYTE_OFFSET - MAC_CRC_LEN;
1643198157Srrs		port = msg->msg0 & 0x0f;
1644198157Srrs		addr = 0;
1645198157Srrs	}
1646198157Srrs
1647198157Srrs	if (xlr_board_info.is_xls) {
1648198157Srrs		if (stid == MSGRNG_STNID_GMAC1)
1649198157Srrs			port += 4;
1650198157Srrs		sc = dev_mac[dev_mac_gmac0 + port];
1651198157Srrs	} else {
1652198157Srrs		if (stid == MSGRNG_STNID_XGS0FR)
1653198157Srrs			sc = dev_mac[dev_mac_xgs0];
1654198157Srrs		else if (stid == MSGRNG_STNID_XGS1FR)
1655198157Srrs			sc = dev_mac[dev_mac_xgs0 + 1];
1656198626Srrs		else
1657198157Srrs			sc = dev_mac[dev_mac_gmac0 + port];
1658198157Srrs	}
1659198157Srrs	if (sc == NULL)
1660198157Srrs		return;
1661198157Srrs	priv = &(sc->priv);
1662198157Srrs
1663209808Sjchandra	dbg_msg("msg0 = %jx, stid = %d, port = %d, addr=%lx, length=%d, ctrl=%d\n",
1664209808Sjchandra	    (uintmax_t)msg->msg0, stid, port, addr, length, ctrl);
1665198157Srrs
1666198157Srrs	if (ctrl == CTRL_REG_FREE || ctrl == CTRL_JUMBO_FREE) {
1667198157Srrs		xlr_rge_tx_ok_done[vcpu]++;
1668198157Srrs		release_tx_desc(msg, 1);
1669198157Srrs		ifp = sc->rge_ifp;
1670198626Srrs		if (ifp->if_drv_flags & IFF_DRV_OACTIVE) {
1671198157Srrs			ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1672198157Srrs		}
1673198626Srrs		if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1))
1674198626Srrs			rge_tx_bkp_func(NULL, 0);
1675198157Srrs		xlr_set_counter(NETIF_TX_COMPLETE_CYCLES,
1676198626Srrs		    (read_c0_count() - msgrng_msg_cycles));
1677198157Srrs	} else if (ctrl == CTRL_SNGL || ctrl == CTRL_START) {
1678198157Srrs		/* Rx Packet */
1679198157Srrs		/* struct mbuf *m = 0; */
1680198157Srrs		/* int logical_cpu = 0; */
1681198157Srrs
1682198157Srrs		dbg_msg("Received packet, port = %d\n", port);
1683198157Srrs		/*
1684198157Srrs		 * if num frins to be sent exceeds threshold, wake up the
1685198157Srrs		 * helper thread
1686198157Srrs		 */
1687198157Srrs		atomic_add_int(&(priv->frin_to_be_sent[cpu]), 1);
1688198157Srrs		if ((priv->frin_to_be_sent[cpu]) > MAC_FRIN_TO_BE_SENT_THRESHOLD) {
1689198157Srrs			mac_frin_replenish(NULL);
1690198157Srrs		}
1691209808Sjchandra		dbg_msg("gmac_%d: rx packet: phys_addr = %jx, length = %x\n",
1692209808Sjchandra		    priv->instance, (uintmax_t)phys_addr, length);
1693198157Srrs		mac_stats_add(priv->stats.rx_packets, 1);
1694198157Srrs		mac_stats_add(priv->stats.rx_bytes, length);
1695198157Srrs		xlr_inc_counter(NETIF_RX);
1696198157Srrs		xlr_set_counter(NETIF_RX_CYCLES,
1697198626Srrs		    (read_c0_count() - msgrng_msg_cycles));
1698198157Srrs		rge_rx(sc, phys_addr, length);
1699198157Srrs		xlr_rge_rx_done[vcpu]++;
1700198157Srrs	} else {
1701198157Srrs		printf("[%s]: unrecognized ctrl=%d!\n", __FUNCTION__, ctrl);
1702198157Srrs	}
1703198157Srrs
1704198157Srrs}
1705198157Srrs
1706198157Srrs/**********************************************************************
1707198157Srrs **********************************************************************/
1708198157Srrsstatic int
1709198157Srrsrge_probe(dev)
1710198626Srrs	device_t dev;
1711198157Srrs{
1712208265Srpaulo	device_set_desc(dev, "RMI Gigabit Ethernet");
1713208265Srpaulo
1714198157Srrs	/* Always return 0 */
1715198157Srrs	return 0;
1716198157Srrs}
1717198157Srrs
1718198157Srrsvolatile unsigned long xlr_debug_enabled;
1719198626Srrsstruct callout rge_dbg_count;
1720199139Srrsstatic void
1721198626Srrsxlr_debug_count(void *addr)
1722198157Srrs{
1723198157Srrs	struct driver_data *priv = &dev_mac[0]->priv;
1724198626Srrs
1725198626Srrs	/* uint32_t crdt; */
1726198626Srrs	if (xlr_debug_enabled) {
1727198626Srrs		printf("\nAvailRxIn %#x\n", xlr_read_reg(priv->mmio, 0x23e));
1728198157Srrs	}
1729198157Srrs	callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL);
1730198157Srrs}
1731198157Srrs
1732198157Srrs
1733199139Srrsstatic void
1734198626Srrsxlr_tx_q_wakeup(void *addr)
1735198157Srrs{
1736198626Srrs	int i = 0;
1737198626Srrs	int j = 0;
1738198626Srrs
1739198626Srrs	for (i = 0; i < xlr_board_info.gmacports; i++) {
1740198157Srrs		if (!dev_mac[i] || !dev_mac[i]->active)
1741198157Srrs			continue;
1742198626Srrs		if ((dev_mac[i]->rge_ifp->if_drv_flags) & IFF_DRV_OACTIVE) {
1743198626Srrs			for (j = 0; j < XLR_MAX_CORE; j++) {
1744198626Srrs				if (xlr_tot_avail_p2d[j]) {
1745198157Srrs					dev_mac[i]->rge_ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1746198157Srrs					break;
1747198157Srrs				}
1748198157Srrs			}
1749198157Srrs		}
1750198157Srrs	}
1751203010Srrs	if (atomic_cmpset_int(&g_tx_frm_tx_ok, 0, 1))
1752203010Srrs		rge_tx_bkp_func(NULL, 0);
1753198626Srrs	callout_reset(&xlr_tx_stop_bkp, 5 * hz, xlr_tx_q_wakeup, NULL);
1754198157Srrs}
1755198157Srrs
1756198157Srrsstatic int
1757198608Srrsrge_attach(device_t dev)
1758198157Srrs{
1759198626Srrs	struct ifnet *ifp;
1760198157Srrs	struct rge_softc *sc;
1761198157Srrs	struct driver_data *priv = 0;
1762198626Srrs	int ret = 0;
1763198157Srrs	struct xlr_gmac_block_t *gmac_conf = device_get_ivars(dev);
1764198157Srrs
1765198157Srrs	sc = device_get_softc(dev);
1766198157Srrs	sc->rge_dev = dev;
1767198157Srrs
1768198157Srrs	/* Initialize mac's */
1769198157Srrs	sc->unit = device_get_unit(dev);
1770198157Srrs
1771198157Srrs	if (sc->unit > XLR_MAX_MACS) {
1772198157Srrs		ret = ENXIO;
1773198157Srrs		goto out;
1774198157Srrs	}
1775198157Srrs	RGE_LOCK_INIT(sc, device_get_nameunit(dev));
1776198157Srrs
1777198157Srrs	priv = &(sc->priv);
1778198157Srrs	priv->sc = sc;
1779198157Srrs
1780198157Srrs	sc->flags = 0;		/* TODO : fix me up later */
1781198157Srrs
1782198157Srrs	priv->id = sc->unit;
1783198157Srrs	if (gmac_conf->type == XLR_GMAC) {
1784198157Srrs		priv->instance = priv->id;
1785198626Srrs		priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr +
1786198626Srrs		    0x1000 * (sc->unit % 4));
1787198157Srrs		if ((ret = rmi_xlr_gmac_reset(priv)) == -1)
1788198157Srrs			goto out;
1789198157Srrs	} else if (gmac_conf->type == XLR_XGMAC) {
1790198157Srrs		priv->instance = priv->id - xlr_board_info.gmacports;
1791198157Srrs		priv->mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr);
1792198157Srrs	}
1793209318Sjchandra	if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_VI ||
1794209318Sjchandra	    (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI &&
1795209318Sjchandra	     priv->instance >=4)) {
1796198157Srrs		dbg_msg("Arizona board - offset 4 \n");
1797198626Srrs		priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_4_OFFSET);
1798198157Srrs	} else
1799198626Srrs		priv->mii_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET);
1800198157Srrs
1801198626Srrs	priv->pcs_mmio = (xlr_reg_t *) (xlr_io_base + gmac_conf->baseaddr);
1802198626Srrs	priv->serdes_mmio = (xlr_reg_t *) (xlr_io_base + XLR_IO_GMAC_0_OFFSET);
1803198157Srrs
1804198626Srrs	sc->base_addr = (unsigned long)priv->mmio;
1805198626Srrs	sc->mem_end = (unsigned long)priv->mmio + XLR_IO_SIZE - 1;
1806198157Srrs
1807198157Srrs	sc->xmit = rge_start;
1808198157Srrs	sc->stop = rge_stop;
1809198157Srrs	sc->get_stats = rmi_xlr_mac_get_stats;
1810198157Srrs	sc->ioctl = rge_ioctl;
1811198157Srrs
1812198157Srrs	/* Initialize the device specific driver data */
1813198157Srrs	mtx_init(&priv->lock, "rge", NULL, MTX_SPIN);
1814198157Srrs
1815198157Srrs	priv->type = gmac_conf->type;
1816198157Srrs
1817198157Srrs	priv->mode = gmac_conf->mode;
1818198157Srrs	if (xlr_board_info.is_xls == 0) {
1819209318Sjchandra		/* TODO - check II and IIB boards */
1820209318Sjchandra		if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_II &&
1821209318Sjchandra		    xlr_boot1_info.board_minor_version != 1)
1822198157Srrs			priv->phy_addr = priv->instance - 2;
1823198157Srrs		else
1824198157Srrs			priv->phy_addr = priv->instance;
1825198157Srrs		priv->mode = XLR_RGMII;
1826198626Srrs	} else {
1827198157Srrs		if (gmac_conf->mode == XLR_PORT0_RGMII &&
1828198626Srrs		    priv->instance == 0) {
1829198626Srrs			priv->mode = XLR_PORT0_RGMII;
1830198157Srrs			priv->phy_addr = 0;
1831198626Srrs		} else {
1832198626Srrs			priv->mode = XLR_SGMII;
1833209318Sjchandra			/* Board 11 has SGMII daughter cards with the XLS chips, in this case
1834209318Sjchandra			   the phy number is 0-3 for both GMAC blocks */
1835209318Sjchandra			if (xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI)
1836209318Sjchandra				priv->phy_addr = priv->instance % 4 + 16;
1837209318Sjchandra			else
1838209318Sjchandra				priv->phy_addr = priv->instance + 16;
1839198157Srrs		}
1840198157Srrs	}
1841198157Srrs
1842198157Srrs	priv->txbucket = gmac_conf->station_txbase + priv->instance % 4;
1843198626Srrs	priv->rfrbucket = gmac_conf->station_rfr;
1844198157Srrs	priv->spill_configured = 0;
1845198157Srrs
1846198157Srrs	dbg_msg("priv->mmio=%p\n", priv->mmio);
1847198157Srrs
1848198157Srrs	/* Set up ifnet structure */
1849198157Srrs	ifp = sc->rge_ifp = if_alloc(IFT_ETHER);
1850198157Srrs	if (ifp == NULL) {
1851198157Srrs		device_printf(sc->rge_dev, "failed to if_alloc()\n");
1852198157Srrs		rge_release_resources(sc);
1853198157Srrs		ret = ENXIO;
1854198157Srrs		RGE_LOCK_DESTROY(sc);
1855198157Srrs		goto out;
1856198157Srrs	}
1857198157Srrs	ifp->if_softc = sc;
1858198157Srrs	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1859198157Srrs	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1860198157Srrs	ifp->if_ioctl = rge_ioctl;
1861198157Srrs	ifp->if_start = rge_start;
1862198157Srrs	ifp->if_init = rge_init;
1863198157Srrs	ifp->if_mtu = ETHERMTU;
1864198157Srrs	ifp->if_snd.ifq_drv_maxlen = RGE_TX_Q_SIZE;
1865198157Srrs	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
1866198157Srrs	IFQ_SET_READY(&ifp->if_snd);
1867198157Srrs	sc->active = 1;
1868198626Srrs	ifp->if_hwassist = 0;
1869198626Srrs	ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_VLAN_HWTAGGING;
1870198157Srrs	ifp->if_capenable = ifp->if_capabilities;
1871198157Srrs
1872198157Srrs	/* Initialize the rge_softc */
1873198157Srrs	sc->irq = gmac_conf->baseirq + priv->instance % 4;
1874198157Srrs
1875198608Srrs	/* Set the IRQ into the rid field */
1876199139Srrs	/*
1877199139Srrs	 * note this is a hack to pass the irq to the iodi interrupt setup
1878199139Srrs	 * routines
1879199139Srrs	 */
1880209808Sjchandra	sc->rge_irq.__r_i = (struct resource_i *)(intptr_t)sc->irq;
1881198608Srrs
1882198157Srrs	ret = bus_setup_intr(dev, &sc->rge_irq, INTR_FAST | INTR_TYPE_NET | INTR_MPSAFE,
1883198626Srrs	    NULL, rge_intr, sc, &sc->rge_intrhand);
1884198157Srrs
1885198157Srrs	if (ret) {
1886198157Srrs		rge_detach(dev);
1887198157Srrs		device_printf(sc->rge_dev, "couldn't set up irq\n");
1888198157Srrs		RGE_LOCK_DESTROY(sc);
1889198157Srrs		goto out;
1890198157Srrs	}
1891198157Srrs	xlr_mac_get_hwaddr(sc);
1892198157Srrs	xlr_mac_setup_hwaddr(priv);
1893198157Srrs
1894198157Srrs	dbg_msg("MMIO %08lx, MII %08lx, PCS %08lx, base %08lx PHY %d IRQ %d\n",
1895198626Srrs	    (u_long)priv->mmio, (u_long)priv->mii_mmio, (u_long)priv->pcs_mmio,
1896198626Srrs	    (u_long)sc->base_addr, priv->phy_addr, sc->irq);
1897198626Srrs	dbg_msg("HWADDR %02x:%02x tx %d rfr %d\n", (u_int)sc->dev_addr[4],
1898198626Srrs	    (u_int)sc->dev_addr[5], priv->txbucket, priv->rfrbucket);
1899198157Srrs
1900198157Srrs	/*
1901198157Srrs	 * Set up ifmedia support.
1902198157Srrs	 */
1903198157Srrs	/*
1904198157Srrs	 * Initialize MII/media info.
1905198157Srrs	 */
1906198157Srrs	sc->rge_mii.mii_ifp = ifp;
1907198157Srrs	sc->rge_mii.mii_readreg = rge_mii_read;
1908198626Srrs	sc->rge_mii.mii_writereg = (mii_writereg_t) rge_mii_write;
1909198157Srrs	sc->rge_mii.mii_statchg = rmi_xlr_mac_mii_statchg;
1910198157Srrs	ifmedia_init(&sc->rge_mii.mii_media, 0, rmi_xlr_mac_mediachange,
1911198626Srrs	    rmi_xlr_mac_mediastatus);
1912198157Srrs	ifmedia_add(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL);
1913198157Srrs	ifmedia_set(&sc->rge_mii.mii_media, IFM_ETHER | IFM_AUTO);
1914198157Srrs	sc->rge_mii.mii_media.ifm_media = sc->rge_mii.mii_media.ifm_cur->ifm_media;
1915198157Srrs
1916198157Srrs	/*
1917198157Srrs	 * Call MI attach routine.
1918198157Srrs	 */
1919198157Srrs	ether_ifattach(ifp, sc->dev_addr);
1920198157Srrs
1921198157Srrs	if (priv->type == XLR_GMAC) {
1922198157Srrs		rmi_xlr_gmac_init(priv);
1923198157Srrs	} else if (priv->type == XLR_XGMAC) {
1924198157Srrs		rmi_xlr_xgmac_init(priv);
1925198157Srrs	}
1926198157Srrs	dbg_msg("rge_%d: Phoenix Mac at 0x%p (mtu=%d)\n",
1927198626Srrs	    sc->unit, priv->mmio, sc->mtu);
1928198157Srrs	dev_mac[sc->unit] = sc;
1929198157Srrs	if (priv->type == XLR_XGMAC && priv->instance == 0)
1930198157Srrs		dev_mac_xgs0 = sc->unit;
1931198157Srrs	if (priv->type == XLR_GMAC && priv->instance == 0)
1932198157Srrs		dev_mac_gmac0 = sc->unit;
1933198157Srrs
1934198626Srrs	if (!gmac_common_init_done) {
1935198157Srrs		mac_common_init();
1936198157Srrs		gmac_common_init_done = 1;
1937198157Srrs		callout_init(&xlr_tx_stop_bkp, CALLOUT_MPSAFE);
1938198157Srrs		callout_reset(&xlr_tx_stop_bkp, hz, xlr_tx_q_wakeup, NULL);
1939198157Srrs		callout_init(&rge_dbg_count, CALLOUT_MPSAFE);
1940198626Srrs		//callout_reset(&rge_dbg_count, hz, xlr_debug_count, NULL);
1941198157Srrs	}
1942198157Srrs	if ((ret = rmi_xlr_mac_open(sc)) == -1) {
1943198157Srrs		RGE_LOCK_DESTROY(sc);
1944198157Srrs		goto out;
1945198157Srrs	}
1946198157Srrsout:
1947198157Srrs	if (ret < 0) {
1948198157Srrs		device_printf(dev, "error - skipping\n");
1949198157Srrs	}
1950198157Srrs	return ret;
1951198157Srrs}
1952198157Srrs
1953198626Srrsstatic void
1954198157Srrsrge_reset(struct rge_softc *sc)
1955198157Srrs{
1956198157Srrs}
1957198157Srrs
1958198157Srrsstatic int
1959198157Srrsrge_detach(dev)
1960198626Srrs	device_t dev;
1961198157Srrs{
1962198157Srrs#ifdef FREEBSD_MAC_NOT_YET
1963198157Srrs	struct rge_softc *sc;
1964198626Srrs	struct ifnet *ifp;
1965198157Srrs
1966198157Srrs	sc = device_get_softc(dev);
1967198157Srrs	ifp = sc->rge_ifp;
1968198157Srrs
1969198157Srrs	RGE_LOCK(sc);
1970198157Srrs	rge_stop(sc);
1971198157Srrs	rge_reset(sc);
1972198157Srrs	RGE_UNLOCK(sc);
1973198157Srrs
1974198157Srrs	ether_ifdetach(ifp);
1975198157Srrs
1976198157Srrs	if (sc->rge_tbi) {
1977198157Srrs		ifmedia_removeall(&sc->rge_ifmedia);
1978198157Srrs	} else {
1979198157Srrs		bus_generic_detach(dev);
1980198157Srrs		device_delete_child(dev, sc->rge_miibus);
1981198157Srrs	}
1982198157Srrs
1983198157Srrs	rge_release_resources(sc);
1984198157Srrs
1985198157Srrs#endif				/* FREEBSD_MAC_NOT_YET */
1986198157Srrs	return (0);
1987198157Srrs}
1988198626Srrsstatic int
1989198157Srrsrge_suspend(device_t dev)
1990198157Srrs{
1991198157Srrs	struct rge_softc *sc;
1992198157Srrs
1993198157Srrs	sc = device_get_softc(dev);
1994198157Srrs	RGE_LOCK(sc);
1995198157Srrs	rge_stop(sc);
1996198157Srrs	RGE_UNLOCK(sc);
1997198157Srrs
1998198157Srrs	return 0;
1999198157Srrs}
2000198157Srrs
2001198626Srrsstatic int
2002198157Srrsrge_resume(device_t dev)
2003198157Srrs{
2004198157Srrs	panic("rge_resume(): unimplemented\n");
2005198157Srrs	return 0;
2006198157Srrs}
2007198157Srrs
2008198626Srrsstatic void
2009198157Srrsrge_release_resources(struct rge_softc *sc)
2010198157Srrs{
2011198157Srrs
2012198157Srrs	if (sc->rge_ifp != NULL)
2013198157Srrs		if_free(sc->rge_ifp);
2014198157Srrs
2015198157Srrs	if (mtx_initialized(&sc->rge_mtx))	/* XXX */
2016198157Srrs		RGE_LOCK_DESTROY(sc);
2017198157Srrs}
2018198626Srrsuint32_t gmac_rx_fail[32];
2019198626Srrsuint32_t gmac_rx_pass[32];
2020198157Srrs
2021198626Srrsstatic void
2022198157Srrsrge_rx(struct rge_softc *sc, vm_paddr_t paddr, int len)
2023198157Srrs{
2024198626Srrs	struct mbuf *m;
2025210630Sjchandra	uint32_t mag;
2026198626Srrs	struct ifnet *ifp = sc->rge_ifp;
2027210630Sjchandra#ifdef __mips_n64
2028210630Sjchandra	uint64_t *vaddr;
2029198157Srrs
2030210630Sjchandra	vaddr =(uint64_t *)MIPS_PHYS_TO_XKPHYS_CACHED(paddr - XLR_CACHELINE_SIZE);
2031210630Sjchandra	m = (struct mbuf *)vaddr[0];
2032210630Sjchandra	mag = (uint32_t)vaddr[1];
2033210630Sjchandra#else
2034210630Sjchandra	uint32_t sr;
2035210630Sjchandra	/*
2036210630Sjchandra	 * On 32 bit machines we use XKPHYS to get the values stores with
2037210630Sjchandra	 * the mbuf, need to explicitly enable KX. Disable interrupts while
2038210630Sjchandra	 * KX is enabled to prevent this setting leaking to other code.
2039210630Sjchandra	 */
2040208165Srrs	sr = xlr_enable_kx();
2041210630Sjchandra	m = (struct mbuf *)(intptr_t)xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + sizeof(uint32_t));
2042210630Sjchandra	mag = xlr_paddr_lw(paddr - XLR_CACHELINE_SIZE + 3 * sizeof(uint32_t));
2043208165Srrs	mips_wr_status(sr);
2044210630Sjchandra#endif
2045198157Srrs	if (mag != 0xf00bad) {
2046198157Srrs		/* somebody else packet Error - FIXME in intialization */
2047210630Sjchandra		printf("cpu %d: *ERROR* Not my packet paddr %p\n",
2048210630Sjchandra		    xlr_cpu_id(), (void *)paddr);
2049198157Srrs		return;
2050198157Srrs	}
2051198157Srrs	/* align the data */
2052198157Srrs	m->m_data += BYTE_OFFSET;
2053198157Srrs	m->m_pkthdr.len = m->m_len = len;
2054198157Srrs	m->m_pkthdr.rcvif = ifp;
2055198157Srrs
2056198157Srrs#ifdef DUMP_PACKETS
2057198157Srrs	{
2058198626Srrs		int i = 0;
2059198626Srrs		unsigned char *buf = (char *)m->m_data;
2060198626Srrs
2061198157Srrs		printf("Rx Packet: length=%d\n", len);
2062198157Srrs		for (i = 0; i < 64; i++) {
2063198157Srrs			if (i && (i % 16) == 0)
2064198157Srrs				printf("\n");
2065198157Srrs			printf("%02x ", buf[i]);
2066198157Srrs		}
2067198157Srrs		printf("\n");
2068198157Srrs	}
2069198157Srrs#endif
2070198157Srrs	ifp->if_ipackets++;
2071198157Srrs	(*ifp->if_input) (ifp, m);
2072198157Srrs}
2073198626Srrs
2074198626Srrsstatic void
2075198157Srrsrge_intr(void *arg)
2076198157Srrs{
2077198157Srrs	struct rge_softc *sc = (struct rge_softc *)arg;
2078198157Srrs	struct driver_data *priv = &(sc->priv);
2079198626Srrs	xlr_reg_t *mmio = priv->mmio;
2080198626Srrs	uint32_t intreg = xlr_read_reg(mmio, R_INTREG);
2081198157Srrs
2082198157Srrs	if (intreg & (1 << O_INTREG__MDInt)) {
2083198626Srrs		uint32_t phy_int_status = 0;
2084198626Srrs		int i = 0;
2085198157Srrs
2086198157Srrs		for (i = 0; i < XLR_MAX_MACS; i++) {
2087198157Srrs			struct rge_softc *phy_dev = 0;
2088198157Srrs			struct driver_data *phy_priv = 0;
2089198157Srrs
2090198157Srrs			phy_dev = dev_mac[i];
2091198157Srrs			if (phy_dev == NULL)
2092198157Srrs				continue;
2093198157Srrs
2094198157Srrs			phy_priv = &phy_dev->priv;
2095198157Srrs
2096198157Srrs			if (phy_priv->type == XLR_XGMAC)
2097198157Srrs				continue;
2098198157Srrs
2099198157Srrs			phy_int_status = rge_mii_read_internal(phy_priv->mii_mmio,
2100198626Srrs			    phy_priv->phy_addr, 26);
2101198157Srrs			printf("rge%d: Phy addr %d, MII MMIO %lx status %x\n", phy_priv->instance,
2102198626Srrs			    (int)phy_priv->phy_addr, (u_long)phy_priv->mii_mmio, phy_int_status);
2103198157Srrs			rmi_xlr_gmac_config_speed(phy_priv);
2104198157Srrs		}
2105198157Srrs	} else {
2106198157Srrs		printf("[%s]: mac type = %d, instance %d error "
2107198626Srrs		    "interrupt: INTREG = 0x%08x\n",
2108198626Srrs		    __FUNCTION__, priv->type, priv->instance, intreg);
2109198157Srrs	}
2110198157Srrs
2111198157Srrs	/* clear all interrupts and hope to make progress */
2112198157Srrs	xlr_write_reg(mmio, R_INTREG, 0xffffffff);
2113198157Srrs
2114209318Sjchandra	/* (not yet) on A0 and B0, xgmac interrupts are routed only to xgs_1 irq */
2115209318Sjchandra	if ((xlr_revision() < 2) && (priv->type == XLR_XGMAC)) {
2116198157Srrs		struct rge_softc *xgs0_dev = dev_mac[dev_mac_xgs0];
2117198157Srrs		struct driver_data *xgs0_priv = &xgs0_dev->priv;
2118198626Srrs		xlr_reg_t *xgs0_mmio = xgs0_priv->mmio;
2119198626Srrs		uint32_t xgs0_intreg = xlr_read_reg(xgs0_mmio, R_INTREG);
2120198157Srrs
2121198157Srrs		if (xgs0_intreg) {
2122198157Srrs			printf("[%s]: mac type = %d, instance %d error "
2123198626Srrs			    "interrupt: INTREG = 0x%08x\n",
2124198626Srrs			    __FUNCTION__, xgs0_priv->type, xgs0_priv->instance, xgs0_intreg);
2125198157Srrs
2126198157Srrs			xlr_write_reg(xgs0_mmio, R_INTREG, 0xffffffff);
2127198157Srrs		}
2128198157Srrs	}
2129198157Srrs}
2130198157Srrs
2131198626Srrsstatic void
2132198157Srrsrge_start_locked(struct ifnet *ifp, int threshold)
2133198157Srrs{
2134198157Srrs	struct rge_softc *sc = ifp->if_softc;
2135198626Srrs	struct mbuf *m = NULL;
2136198626Srrs	int prepend_pkt = 0;
2137198626Srrs	int i = 0;
2138198626Srrs	struct p2d_tx_desc *tx_desc = NULL;
2139208165Srrs	int cpu = xlr_core_id();
2140208165Srrs	uint32_t vcpu = xlr_cpu_id();
2141198157Srrs
2142198157Srrs	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
2143198157Srrs		return;
2144198157Srrs
2145198626Srrs	for (i = 0; i < xlr_tot_avail_p2d[cpu]; i++) {
2146198157Srrs		if (IFQ_DRV_IS_EMPTY(&ifp->if_snd))
2147198157Srrs			return;
2148198157Srrs		tx_desc = get_p2d_desc();
2149198626Srrs		if (!tx_desc) {
2150198157Srrs			xlr_rge_get_p2d_failed[vcpu]++;
2151198157Srrs			return;
2152198157Srrs		}
2153198157Srrs		/* Grab a packet off the queue. */
2154198157Srrs		IFQ_DEQUEUE(&ifp->if_snd, m);
2155198626Srrs		if (m == NULL) {
2156198157Srrs			free_p2d_desc(tx_desc);
2157198157Srrs			return;
2158198157Srrs		}
2159198157Srrs		prepend_pkt = rmi_xlr_mac_xmit(m, sc, 0, tx_desc);
2160198157Srrs
2161198157Srrs		if (prepend_pkt) {
2162198157Srrs			xlr_rge_tx_prepend[vcpu]++;
2163198157Srrs			IF_PREPEND(&ifp->if_snd, m);
2164198157Srrs			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
2165198157Srrs			return;
2166198157Srrs		} else {
2167198157Srrs			ifp->if_opackets++;
2168198157Srrs			xlr_rge_tx_done[vcpu]++;
2169198157Srrs		}
2170198157Srrs	}
2171198157Srrs}
2172198157Srrs
2173198626Srrsstatic void
2174198157Srrsrge_start(struct ifnet *ifp)
2175198157Srrs{
2176198157Srrs	rge_start_locked(ifp, RGE_TX_Q_SIZE);
2177198157Srrs}
2178198157Srrs
2179198626Srrsstatic int
2180198157Srrsrge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
2181198157Srrs{
2182198157Srrs	struct rge_softc *sc = ifp->if_softc;
2183198626Srrs	struct ifreq *ifr = (struct ifreq *)data;
2184198626Srrs	int mask, error = 0;
2185198626Srrs
2186198157Srrs	/* struct mii_data *mii; */
2187198157Srrs	switch (command) {
2188198157Srrs	case SIOCSIFMTU:
2189198157Srrs		ifp->if_mtu = ifr->ifr_mtu;
2190198157Srrs		error = rmi_xlr_mac_change_mtu(sc, ifr->ifr_mtu);
2191198157Srrs		break;
2192198157Srrs	case SIOCSIFFLAGS:
2193198157Srrs
2194198157Srrs		RGE_LOCK(sc);
2195198157Srrs		if (ifp->if_flags & IFF_UP) {
2196198157Srrs			/*
2197198157Srrs			 * If only the state of the PROMISC flag changed,
2198198157Srrs			 * then just use the 'set promisc mode' command
2199198157Srrs			 * instead of reinitializing the entire NIC. Doing a
2200198157Srrs			 * full re-init means reloading the firmware and
2201198157Srrs			 * waiting for it to start up, which may take a
2202198157Srrs			 * second or two.  Similarly for ALLMULTI.
2203198157Srrs			 */
2204198157Srrs			if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2205198157Srrs			    ifp->if_flags & IFF_PROMISC &&
2206198157Srrs			    !(sc->flags & IFF_PROMISC)) {
2207198157Srrs				sc->flags |= IFF_PROMISC;
2208198157Srrs				xlr_mac_set_rx_mode(sc);
2209198157Srrs			} else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2210198626Srrs				    !(ifp->if_flags & IFF_PROMISC) &&
2211198626Srrs			    sc->flags & IFF_PROMISC) {
2212198157Srrs				sc->flags &= IFF_PROMISC;
2213198157Srrs				xlr_mac_set_rx_mode(sc);
2214198157Srrs			} else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
2215198626Srrs			    (ifp->if_flags ^ sc->flags) & IFF_ALLMULTI) {
2216198157Srrs				rmi_xlr_mac_set_multicast_list(sc);
2217198157Srrs			} else
2218198157Srrs				xlr_mac_set_rx_mode(sc);
2219198157Srrs		} else {
2220198157Srrs			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2221198157Srrs				xlr_mac_set_rx_mode(sc);
2222198157Srrs			}
2223198157Srrs		}
2224198157Srrs		sc->flags = ifp->if_flags;
2225198157Srrs		RGE_UNLOCK(sc);
2226198157Srrs		error = 0;
2227198157Srrs		break;
2228198157Srrs	case SIOCADDMULTI:
2229198157Srrs	case SIOCDELMULTI:
2230198157Srrs		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2231198157Srrs			RGE_LOCK(sc);
2232198157Srrs			rmi_xlr_mac_set_multicast_list(sc);
2233198157Srrs			RGE_UNLOCK(sc);
2234198157Srrs			error = 0;
2235198157Srrs		}
2236198157Srrs		break;
2237198157Srrs	case SIOCSIFMEDIA:
2238198157Srrs	case SIOCGIFMEDIA:
2239198157Srrs		error = ifmedia_ioctl(ifp, ifr,
2240198626Srrs		    &sc->rge_mii.mii_media, command);
2241198157Srrs		break;
2242198157Srrs	case SIOCSIFCAP:
2243198157Srrs		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
2244198157Srrs		ifp->if_hwassist = 0;
2245198157Srrs		break;
2246198157Srrs	default:
2247198157Srrs		error = ether_ioctl(ifp, command, data);
2248198157Srrs		break;
2249198157Srrs	}
2250198157Srrs
2251198157Srrs	return (error);
2252198157Srrs}
2253198157Srrs
2254198626Srrsstatic void
2255198157Srrsrge_init(void *addr)
2256198157Srrs{
2257198157Srrs	struct rge_softc *sc = (struct rge_softc *)addr;
2258198626Srrs	struct ifnet *ifp;
2259198157Srrs	struct driver_data *priv = &(sc->priv);
2260198157Srrs
2261198157Srrs	ifp = sc->rge_ifp;
2262198157Srrs
2263198157Srrs	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
2264198157Srrs		return;
2265198157Srrs	ifp->if_drv_flags |= IFF_DRV_RUNNING;
2266198157Srrs	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2267198157Srrs
2268198157Srrs	rmi_xlr_mac_set_enable(priv, 1);
2269198157Srrs}
2270198157Srrs
2271198626Srrsstatic void
2272198157Srrsrge_stop(struct rge_softc *sc)
2273198157Srrs{
2274198157Srrs	rmi_xlr_mac_close(sc);
2275198157Srrs}
2276198157Srrs
2277198608Srrsstatic int
2278198157Srrsrge_shutdown(device_t dev)
2279198157Srrs{
2280198157Srrs	struct rge_softc *sc;
2281198626Srrs
2282198157Srrs	sc = device_get_softc(dev);
2283198157Srrs
2284198157Srrs	RGE_LOCK(sc);
2285198157Srrs	rge_stop(sc);
2286198157Srrs	rge_reset(sc);
2287198157Srrs	RGE_UNLOCK(sc);
2288198157Srrs
2289198626Srrs	return (0);
2290198157Srrs}
2291198157Srrs
2292198626Srrsstatic int
2293198157Srrsrmi_xlr_mac_open(struct rge_softc *sc)
2294198157Srrs{
2295198157Srrs	struct driver_data *priv = &(sc->priv);
2296198157Srrs	int i;
2297198157Srrs
2298198157Srrs	dbg_msg("IN\n");
2299198157Srrs
2300198157Srrs	if (rmi_xlr_mac_fill_rxfr(sc)) {
2301198157Srrs		return -1;
2302198157Srrs	}
2303198157Srrs	mtx_lock_spin(&priv->lock);
2304198157Srrs
2305198157Srrs	xlr_mac_set_rx_mode(sc);
2306198157Srrs
2307198157Srrs	if (sc->unit == xlr_board_info.gmacports - 1) {
2308198157Srrs		printf("Enabling MDIO interrupts\n");
2309198157Srrs		struct rge_softc *tmp = NULL;
2310198626Srrs
2311198157Srrs		for (i = 0; i < xlr_board_info.gmacports; i++) {
2312198157Srrs			tmp = dev_mac[i];
2313198157Srrs			if (tmp)
2314198157Srrs				xlr_write_reg(tmp->priv.mmio, R_INTMASK,
2315198626Srrs				    ((tmp->priv.instance == 0) << O_INTMASK__MDInt));
2316198157Srrs		}
2317198157Srrs	}
2318198157Srrs	/*
2319198157Srrs	 * Configure the speed, duplex, and flow control
2320198157Srrs	 */
2321198157Srrs	rmi_xlr_mac_set_speed(priv, priv->speed);
2322198157Srrs	rmi_xlr_mac_set_duplex(priv, priv->duplex, priv->flow_ctrl);
2323198157Srrs	rmi_xlr_mac_set_enable(priv, 0);
2324198157Srrs
2325198157Srrs	mtx_unlock_spin(&priv->lock);
2326198157Srrs
2327198157Srrs	for (i = 0; i < 8; i++) {
2328198157Srrs		atomic_set_int(&(priv->frin_to_be_sent[i]), 0);
2329198157Srrs	}
2330198157Srrs
2331198157Srrs	return 0;
2332198157Srrs}
2333198157Srrs
2334198157Srrs/**********************************************************************
2335198157Srrs **********************************************************************/
2336198626Srrsstatic int
2337198157Srrsrmi_xlr_mac_close(struct rge_softc *sc)
2338198157Srrs{
2339198157Srrs	struct driver_data *priv = &(sc->priv);
2340198157Srrs
2341198157Srrs	mtx_lock_spin(&priv->lock);
2342198157Srrs
2343198157Srrs	/*
2344198157Srrs	 * There may have left over mbufs in the ring as well as in free in
2345198157Srrs	 * they will be reused next time open is called
2346198157Srrs	 */
2347198157Srrs
2348198157Srrs	rmi_xlr_mac_set_enable(priv, 0);
2349198157Srrs
2350198157Srrs	xlr_inc_counter(NETIF_STOP_Q);
2351198157Srrs	port_inc_counter(priv->instance, PORT_STOPQ);
2352198157Srrs
2353198157Srrs	mtx_unlock_spin(&priv->lock);
2354198157Srrs
2355198157Srrs	return 0;
2356198157Srrs}
2357198157Srrs
2358198157Srrs/**********************************************************************
2359198157Srrs **********************************************************************/
2360198157Srrsstatic struct rge_softc_stats *
2361198157Srrsrmi_xlr_mac_get_stats(struct rge_softc *sc)
2362198157Srrs{
2363198157Srrs	struct driver_data *priv = &(sc->priv);
2364198626Srrs
2365198157Srrs	/* unsigned long flags; */
2366198157Srrs
2367198157Srrs	mtx_lock_spin(&priv->lock);
2368198157Srrs
2369198157Srrs	/* XXX update other stats here */
2370198157Srrs
2371198157Srrs	mtx_unlock_spin(&priv->lock);
2372198157Srrs
2373198157Srrs	return &priv->stats;
2374198157Srrs}
2375198157Srrs
2376198157Srrs/**********************************************************************
2377198157Srrs **********************************************************************/
2378198626Srrsstatic void
2379198157Srrsrmi_xlr_mac_set_multicast_list(struct rge_softc *sc)
2380198157Srrs{
2381198157Srrs}
2382198157Srrs
2383198157Srrs/**********************************************************************
2384198157Srrs **********************************************************************/
2385198626Srrsstatic int
2386198157Srrsrmi_xlr_mac_change_mtu(struct rge_softc *sc, int new_mtu)
2387198157Srrs{
2388198157Srrs	struct driver_data *priv = &(sc->priv);
2389198157Srrs
2390198157Srrs	if ((new_mtu > 9500) || (new_mtu < 64)) {
2391198157Srrs		return -EINVAL;
2392198157Srrs	}
2393198157Srrs	mtx_lock_spin(&priv->lock);
2394198157Srrs
2395198157Srrs	sc->mtu = new_mtu;
2396198157Srrs
2397198157Srrs	/* Disable MAC TX/RX */
2398198157Srrs	rmi_xlr_mac_set_enable(priv, 0);
2399198157Srrs
2400198157Srrs	/* Flush RX FR IN */
2401198157Srrs	/* Flush TX IN */
2402198157Srrs	rmi_xlr_mac_set_enable(priv, 1);
2403198157Srrs
2404198157Srrs	mtx_unlock_spin(&priv->lock);
2405198157Srrs	return 0;
2406198157Srrs}
2407198157Srrs
2408198157Srrs/**********************************************************************
2409198157Srrs **********************************************************************/
2410198626Srrsstatic int
2411198157Srrsrmi_xlr_mac_fill_rxfr(struct rge_softc *sc)
2412198157Srrs{
2413198157Srrs	struct driver_data *priv = &(sc->priv);
2414198626Srrs	int i;
2415198626Srrs	int ret = 0;
2416198626Srrs	void *ptr;
2417198157Srrs
2418198157Srrs	dbg_msg("\n");
2419198157Srrs	if (!priv->init_frin_desc)
2420198157Srrs		return ret;
2421198157Srrs	priv->init_frin_desc = 0;
2422198157Srrs
2423198157Srrs	dbg_msg("\n");
2424198157Srrs	for (i = 0; i < MAX_NUM_DESC; i++) {
2425198157Srrs		ptr = get_buf();
2426198157Srrs		if (!ptr) {
2427198157Srrs			ret = -ENOMEM;
2428198157Srrs			break;
2429198157Srrs		}
2430198157Srrs		/* Send the free Rx desc to the MAC */
2431198157Srrs		xlr_mac_send_fr(priv, vtophys(ptr), MAX_FRAME_SIZE);
2432198157Srrs	}
2433198157Srrs
2434198157Srrs	return ret;
2435198157Srrs}
2436198157Srrs
2437198157Srrs/**********************************************************************
2438198157Srrs **********************************************************************/
2439198157Srrsstatic __inline__ void *
2440198157Srrsrmi_xlr_config_spill(xlr_reg_t * mmio,
2441198626Srrs    int reg_start_0, int reg_start_1,
2442198626Srrs    int reg_size, int size)
2443198157Srrs{
2444198626Srrs	uint32_t spill_size = size;
2445198626Srrs	void *spill = NULL;
2446198626Srrs	uint64_t phys_addr = 0;
2447198157Srrs
2448198157Srrs
2449198157Srrs	spill = contigmalloc((spill_size + XLR_CACHELINE_SIZE), M_DEVBUF,
2450198626Srrs	    M_NOWAIT | M_ZERO, 0, 0xffffffff, XLR_CACHELINE_SIZE, 0);
2451198626Srrs	if (!spill || ((vm_offset_t)spill & (XLR_CACHELINE_SIZE - 1))) {
2452198157Srrs		panic("Unable to allocate memory for spill area!\n");
2453198157Srrs	}
2454198157Srrs	phys_addr = vtophys(spill);
2455209808Sjchandra	dbg_msg("Allocate spill %d bytes at %jx\n", size, (uintmax_t)phys_addr);
2456198157Srrs	xlr_write_reg(mmio, reg_start_0, (phys_addr >> 5) & 0xffffffff);
2457198157Srrs	xlr_write_reg(mmio, reg_start_1, (phys_addr >> 37) & 0x07);
2458198157Srrs	xlr_write_reg(mmio, reg_size, spill_size);
2459198157Srrs
2460198157Srrs	return spill;
2461198157Srrs}
2462198157Srrs
2463198626Srrsstatic void
2464198157Srrsrmi_xlr_config_spill_area(struct driver_data *priv)
2465198157Srrs{
2466198157Srrs	/*
2467198157Srrs	 * if driver initialization is done parallely on multiple cpus
2468198157Srrs	 * spill_configured needs synchronization
2469198157Srrs	 */
2470198157Srrs	if (priv->spill_configured)
2471198157Srrs		return;
2472198157Srrs
2473198157Srrs	if (priv->type == XLR_GMAC && priv->instance % 4 != 0) {
2474198157Srrs		priv->spill_configured = 1;
2475198157Srrs		return;
2476198157Srrs	}
2477198157Srrs	priv->spill_configured = 1;
2478198157Srrs
2479198157Srrs	priv->frin_spill =
2480198626Srrs	    rmi_xlr_config_spill(priv->mmio,
2481198626Srrs	    R_REG_FRIN_SPILL_MEM_START_0,
2482198626Srrs	    R_REG_FRIN_SPILL_MEM_START_1,
2483198626Srrs	    R_REG_FRIN_SPILL_MEM_SIZE,
2484198626Srrs	    MAX_FRIN_SPILL *
2485198626Srrs	    sizeof(struct fr_desc));
2486198157Srrs
2487198157Srrs	priv->class_0_spill =
2488198626Srrs	    rmi_xlr_config_spill(priv->mmio,
2489198626Srrs	    R_CLASS0_SPILL_MEM_START_0,
2490198626Srrs	    R_CLASS0_SPILL_MEM_START_1,
2491198626Srrs	    R_CLASS0_SPILL_MEM_SIZE,
2492198626Srrs	    MAX_CLASS_0_SPILL *
2493198626Srrs	    sizeof(union rx_tx_desc));
2494198157Srrs	priv->class_1_spill =
2495198626Srrs	    rmi_xlr_config_spill(priv->mmio,
2496198626Srrs	    R_CLASS1_SPILL_MEM_START_0,
2497198626Srrs	    R_CLASS1_SPILL_MEM_START_1,
2498198626Srrs	    R_CLASS1_SPILL_MEM_SIZE,
2499198626Srrs	    MAX_CLASS_1_SPILL *
2500198626Srrs	    sizeof(union rx_tx_desc));
2501198157Srrs
2502198157Srrs	priv->frout_spill =
2503198626Srrs	    rmi_xlr_config_spill(priv->mmio, R_FROUT_SPILL_MEM_START_0,
2504198626Srrs	    R_FROUT_SPILL_MEM_START_1,
2505198626Srrs	    R_FROUT_SPILL_MEM_SIZE,
2506198626Srrs	    MAX_FROUT_SPILL *
2507198626Srrs	    sizeof(struct fr_desc));
2508198157Srrs
2509198157Srrs	priv->class_2_spill =
2510198626Srrs	    rmi_xlr_config_spill(priv->mmio,
2511198626Srrs	    R_CLASS2_SPILL_MEM_START_0,
2512198626Srrs	    R_CLASS2_SPILL_MEM_START_1,
2513198626Srrs	    R_CLASS2_SPILL_MEM_SIZE,
2514198626Srrs	    MAX_CLASS_2_SPILL *
2515198626Srrs	    sizeof(union rx_tx_desc));
2516198157Srrs	priv->class_3_spill =
2517198626Srrs	    rmi_xlr_config_spill(priv->mmio,
2518198626Srrs	    R_CLASS3_SPILL_MEM_START_0,
2519198626Srrs	    R_CLASS3_SPILL_MEM_START_1,
2520198626Srrs	    R_CLASS3_SPILL_MEM_SIZE,
2521198626Srrs	    MAX_CLASS_3_SPILL *
2522198626Srrs	    sizeof(union rx_tx_desc));
2523198157Srrs	priv->spill_configured = 1;
2524198157Srrs}
2525198157Srrs
2526198157Srrs/*****************************************************************
2527198157Srrs * Write the MAC address to the XLR registers
2528198157Srrs * All 4 addresses are the same for now
2529198157Srrs *****************************************************************/
2530198626Srrsstatic void
2531198157Srrsxlr_mac_setup_hwaddr(struct driver_data *priv)
2532198157Srrs{
2533198157Srrs	struct rge_softc *sc = priv->sc;
2534198157Srrs
2535198157Srrs	xlr_write_reg(priv->mmio, R_MAC_ADDR0,
2536198626Srrs	    ((sc->dev_addr[5] << 24) | (sc->dev_addr[4] << 16)
2537198626Srrs	    | (sc->dev_addr[3] << 8) | (sc->dev_addr[2]))
2538198626Srrs	    );
2539198157Srrs
2540198157Srrs	xlr_write_reg(priv->mmio, R_MAC_ADDR0 + 1,
2541198626Srrs	    ((sc->dev_addr[1] << 24) | (sc->
2542198626Srrs	    dev_addr[0] << 16)));
2543198157Srrs
2544198157Srrs	xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2, 0xffffffff);
2545198157Srrs
2546198157Srrs	xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK2 + 1, 0xffffffff);
2547198157Srrs
2548198157Srrs	xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3, 0xffffffff);
2549198157Srrs
2550198157Srrs	xlr_write_reg(priv->mmio, R_MAC_ADDR_MASK3 + 1, 0xffffffff);
2551198157Srrs
2552198157Srrs	xlr_write_reg(priv->mmio, R_MAC_FILTER_CONFIG,
2553198626Srrs	    (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) |
2554198626Srrs	    (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) |
2555198626Srrs	    (1 << O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID)
2556198626Srrs	    );
2557198157Srrs}
2558198157Srrs
2559198157Srrs/*****************************************************************
2560198157Srrs * Read the MAC address from the XLR registers
2561198157Srrs * All 4 addresses are the same for now
2562198157Srrs *****************************************************************/
2563198626Srrsstatic void
2564198157Srrsxlr_mac_get_hwaddr(struct rge_softc *sc)
2565198157Srrs{
2566198157Srrs	struct driver_data *priv = &(sc->priv);
2567198157Srrs
2568198157Srrs	sc->dev_addr[0] = (xlr_boot1_info.mac_addr >> 40) & 0xff;
2569198157Srrs	sc->dev_addr[1] = (xlr_boot1_info.mac_addr >> 32) & 0xff;
2570198157Srrs	sc->dev_addr[2] = (xlr_boot1_info.mac_addr >> 24) & 0xff;
2571198157Srrs	sc->dev_addr[3] = (xlr_boot1_info.mac_addr >> 16) & 0xff;
2572198157Srrs	sc->dev_addr[4] = (xlr_boot1_info.mac_addr >> 8) & 0xff;
2573198157Srrs	sc->dev_addr[5] = ((xlr_boot1_info.mac_addr >> 0) & 0xff) + priv->instance;
2574198157Srrs}
2575198157Srrs
2576198157Srrs/*****************************************************************
2577198157Srrs * Mac Module Initialization
2578198157Srrs *****************************************************************/
2579198626Srrsstatic void
2580198157Srrsmac_common_init(void)
2581198157Srrs{
2582198157Srrs	init_p2d_allocation();
2583198157Srrs	init_tx_ring();
2584198157Srrs
2585198157Srrs	if (xlr_board_info.is_xls) {
2586198626Srrs		if (register_msgring_handler(TX_STN_GMAC0,
2587198626Srrs		    rmi_xlr_mac_msgring_handler, NULL)) {
2588198157Srrs			panic("Couldn't register msgring handler\n");
2589198157Srrs		}
2590198626Srrs		if (register_msgring_handler(TX_STN_GMAC1,
2591198626Srrs		    rmi_xlr_mac_msgring_handler, NULL)) {
2592198157Srrs			panic("Couldn't register msgring handler\n");
2593198157Srrs		}
2594198157Srrs	} else {
2595198626Srrs		if (register_msgring_handler(TX_STN_GMAC,
2596198626Srrs		    rmi_xlr_mac_msgring_handler, NULL)) {
2597198157Srrs			panic("Couldn't register msgring handler\n");
2598198157Srrs		}
2599198157Srrs	}
2600198157Srrs
2601198626Srrs	/*
2602198626Srrs	 * Not yet if (xlr_board_atx_ii()) { if (register_msgring_handler
2603198626Srrs	 * (TX_STN_XGS_0, rmi_xlr_mac_msgring_handler, NULL)) {
2604198626Srrs	 * panic("Couldn't register msgring handler for TX_STN_XGS_0\n"); }
2605198626Srrs	 * if (register_msgring_handler (TX_STN_XGS_1,
2606198626Srrs	 * rmi_xlr_mac_msgring_handler, NULL)) { panic("Couldn't register
2607198626Srrs	 * msgring handler for TX_STN_XGS_1\n"); } }
2608198626Srrs	 */
2609198157Srrs}
2610