1211946Sjchandra/*-
2211946Sjchandra * Copyright (c) 2003-2009 RMI Corporation
3211946Sjchandra * All rights reserved.
4211946Sjchandra *
5211946Sjchandra * Redistribution and use in source and binary forms, with or without
6211946Sjchandra * modification, are permitted provided that the following conditions
7211946Sjchandra * are met:
8211946Sjchandra * 1. Redistributions of source code must retain the above copyright
9211946Sjchandra *    notice, this list of conditions and the following disclaimer.
10211946Sjchandra * 2. Redistributions in binary form must reproduce the above copyright
11211946Sjchandra *    notice, this list of conditions and the following disclaimer in the
12211946Sjchandra *    documentation and/or other materials provided with the distribution.
13211946Sjchandra * 3. Neither the name of RMI Corporation, nor the names of its contributors,
14211946Sjchandra *    may be used to endorse or promote products derived from this software
15211946Sjchandra *    without specific prior written permission.
16211946Sjchandra *
17211946Sjchandra * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18211946Sjchandra * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19211946Sjchandra * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20211946Sjchandra * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21211946Sjchandra * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22211946Sjchandra * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23211946Sjchandra * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24211946Sjchandra * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25211946Sjchandra * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26211946Sjchandra * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27211946Sjchandra * SUCH DAMAGE.
28211946Sjchandra *
29211946Sjchandra * RMI_BSD */
30211946Sjchandra
31211946Sjchandra/*
32211946Sjchandra * The XLR device supports upto four 10/100/1000 Ethernet MACs and upto
33211946Sjchandra * two 10G Ethernet MACs (of XGMII). Alternatively, each 10G port can used
34211946Sjchandra * as a SPI-4 interface, with 8 ports per such interface. The MACs are
35211946Sjchandra * encapsulated in another hardware block referred to as network accelerator,
36211946Sjchandra * such that there are three instances of these in a XLR. One of them controls
37211946Sjchandra * the four 1G RGMII ports while one each of the others controls an XGMII port.
38211946Sjchandra * Enabling MACs requires configuring the corresponding network accelerator
39211946Sjchandra * and the individual port.
40211946Sjchandra * The XLS device supports upto 8 10/100/1000 Ethernet MACs or max 2 10G
41211946Sjchandra * Ethernet MACs. The 1G MACs are of SGMII and 10G MACs are of XAUI
42211946Sjchandra * interface. These ports are part of two network accelerators.
43211946Sjchandra * The nlge driver configures and initializes non-SPI4 Ethernet ports in the
44211946Sjchandra * XLR/XLS devices and enables data transfer on them.
45211946Sjchandra */
46211946Sjchandra
47211946Sjchandra#include <sys/cdefs.h>
48211946Sjchandra__FBSDID("$FreeBSD$");
49211946Sjchandra
50211946Sjchandra#ifdef HAVE_KERNEL_OPTION_HEADERS
51211946Sjchandra#include "opt_device_polling.h"
52211946Sjchandra#endif
53211946Sjchandra
54211946Sjchandra#include <sys/endian.h>
55211946Sjchandra#include <sys/systm.h>
56211946Sjchandra#include <sys/sockio.h>
57211946Sjchandra#include <sys/param.h>
58211946Sjchandra#include <sys/lock.h>
59211946Sjchandra#include <sys/mutex.h>
60211946Sjchandra#include <sys/proc.h>
61211946Sjchandra#include <sys/limits.h>
62211946Sjchandra#include <sys/bus.h>
63211946Sjchandra#include <sys/mbuf.h>
64211946Sjchandra#include <sys/malloc.h>
65211946Sjchandra#include <sys/kernel.h>
66211946Sjchandra#include <sys/module.h>
67211946Sjchandra#include <sys/socket.h>
68211946Sjchandra#define __RMAN_RESOURCE_VISIBLE
69211946Sjchandra#include <sys/rman.h>
70211946Sjchandra#include <sys/taskqueue.h>
71211946Sjchandra#include <sys/smp.h>
72211946Sjchandra#include <sys/sysctl.h>
73211946Sjchandra
74211946Sjchandra#include <net/if.h>
75211946Sjchandra#include <net/if_arp.h>
76211946Sjchandra#include <net/ethernet.h>
77211946Sjchandra#include <net/if_dl.h>
78211946Sjchandra#include <net/if_media.h>
79211946Sjchandra#include <net/bpf.h>
80211946Sjchandra#include <net/if_types.h>
81211946Sjchandra#include <net/if_vlan_var.h>
82211946Sjchandra
83211946Sjchandra#include <netinet/in_systm.h>
84211946Sjchandra#include <netinet/in.h>
85211946Sjchandra#include <netinet/ip.h>
86211946Sjchandra
87211946Sjchandra#include <vm/vm.h>
88211946Sjchandra#include <vm/pmap.h>
89211946Sjchandra#include <vm/uma.h>
90211946Sjchandra
91211946Sjchandra#include <machine/reg.h>
92211946Sjchandra#include <machine/cpu.h>
93211946Sjchandra#include <machine/mips_opcode.h>
94211946Sjchandra#include <machine/asm.h>
95211946Sjchandra#include <machine/cpuregs.h>
96211946Sjchandra#include <machine/param.h>
97211946Sjchandra#include <machine/intr_machdep.h>
98211946Sjchandra#include <machine/clock.h>	/* for DELAY */
99211946Sjchandra#include <machine/bus.h>
100211946Sjchandra#include <machine/resource.h>
101211946Sjchandra
102211946Sjchandra#include <mips/rmi/interrupt.h>
103211946Sjchandra#include <mips/rmi/msgring.h>
104211946Sjchandra#include <mips/rmi/iomap.h>
105211946Sjchandra#include <mips/rmi/pic.h>
106211946Sjchandra#include <mips/rmi/board.h>
107211946Sjchandra#include <mips/rmi/rmi_mips_exts.h>
108211994Sjchandra#include <mips/rmi/rmi_boot_info.h>
109211946Sjchandra#include <mips/rmi/dev/xlr/atx_cpld.h>
110211946Sjchandra#include <mips/rmi/dev/xlr/xgmac_mdio.h>
111211946Sjchandra
112211946Sjchandra#include <dev/mii/mii.h>
113211946Sjchandra#include <dev/mii/miivar.h>
114211946Sjchandra#include "miidevs.h"
115211946Sjchandra#include <dev/mii/brgphyreg.h>
116211946Sjchandra#include "miibus_if.h"
117211946Sjchandra
118211946Sjchandra#include <mips/rmi/dev/nlge/if_nlge.h>
119211946Sjchandra
120211946SjchandraMODULE_DEPEND(nlna, nlge, 1, 1, 1);
121211946SjchandraMODULE_DEPEND(nlge, ether, 1, 1, 1);
122211946SjchandraMODULE_DEPEND(nlge, miibus, 1, 1, 1);
123211946Sjchandra
124211946Sjchandra/* Network accelarator entry points */
125211946Sjchandrastatic int      nlna_probe(device_t);
126211946Sjchandrastatic int      nlna_attach(device_t);
127211946Sjchandrastatic int      nlna_detach(device_t);
128211946Sjchandrastatic int      nlna_suspend(device_t);
129211946Sjchandrastatic int      nlna_resume(device_t);
130211946Sjchandrastatic int 	nlna_shutdown(device_t);
131211946Sjchandra
132211946Sjchandra/* GMAC port entry points */
133211946Sjchandrastatic int	nlge_probe(device_t);
134211946Sjchandrastatic int	nlge_attach(device_t);
135211946Sjchandrastatic int	nlge_detach(device_t);
136211946Sjchandrastatic int	nlge_suspend(device_t);
137211946Sjchandrastatic int	nlge_resume(device_t);
138211946Sjchandrastatic void	nlge_init(void *);
139211946Sjchandrastatic int	nlge_ioctl(struct ifnet *, u_long, caddr_t);
140215939Sjchandrastatic int	nlge_tx(struct ifnet *ifp, struct mbuf *m);
141211946Sjchandrastatic void 	nlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len);
142211946Sjchandra
143211946Sjchandrastatic int	nlge_mii_write(struct device *, int, int, int);
144211946Sjchandrastatic int	nlge_mii_read(struct device *, int, int);
145211946Sjchandrastatic void	nlge_mac_mii_statchg(device_t);
146211946Sjchandrastatic int	nlge_mediachange(struct ifnet *ifp);
147211946Sjchandrastatic void	nlge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr);
148211946Sjchandra
149211946Sjchandra/* Other internal/helper functions */
150211946Sjchandrastatic void 	*get_buf(void);
151211946Sjchandra
152211946Sjchandrastatic void	nlna_add_to_port_set(struct nlge_port_set *pset,
153211946Sjchandra    struct nlge_softc *sc);
154211946Sjchandrastatic void	nlna_config_pde(struct nlna_softc *);
155211946Sjchandrastatic void	nlna_config_parser(struct nlna_softc *);
156211946Sjchandrastatic void	nlna_config_classifier(struct nlna_softc *);
157211946Sjchandrastatic void	nlna_config_fifo_spill_area(struct nlna_softc *sc);
158213475Sjchandrastatic void	nlna_config_translate_table(struct nlna_softc *sc);
159211946Sjchandrastatic void	nlna_config_common(struct nlna_softc *);
160211946Sjchandrastatic void	nlna_disable_ports(struct nlna_softc *sc);
161211946Sjchandrastatic void	nlna_enable_intr(struct nlna_softc *sc);
162211946Sjchandrastatic void	nlna_disable_intr(struct nlna_softc *sc);
163211946Sjchandrastatic void	nlna_enable_ports(struct nlna_softc *sc);
164211946Sjchandrastatic void	nlna_get_all_softc(device_t iodi_dev,
165211946Sjchandra    struct nlna_softc **sc_vec, uint32_t vec_sz);
166211946Sjchandrastatic void 	nlna_hw_init(struct nlna_softc *sc);
167211946Sjchandrastatic int 	nlna_is_last_active_na(struct nlna_softc *sc);
168211946Sjchandrastatic void	nlna_media_specific_config(struct nlna_softc *sc);
169211946Sjchandrastatic void 	nlna_reset_ports(struct nlna_softc *sc,
170211946Sjchandra    struct xlr_gmac_block_t *blk);
171211946Sjchandrastatic struct nlna_softc *nlna_sc_init(device_t dev,
172211946Sjchandra    struct xlr_gmac_block_t *blk);
173211946Sjchandrastatic void	nlna_setup_intr(struct nlna_softc *sc);
174211946Sjchandrastatic void	nlna_smp_update_pde(void *dummy __unused);
175211946Sjchandrastatic void	nlna_submit_rx_free_desc(struct nlna_softc *sc,
176211946Sjchandra    uint32_t n_desc);
177211946Sjchandra
178211946Sjchandrastatic int	nlge_gmac_config_speed(struct nlge_softc *, int quick);
179211946Sjchandrastatic void	nlge_hw_init(struct nlge_softc *sc);
180211946Sjchandrastatic int	nlge_if_init(struct nlge_softc *sc);
181211946Sjchandrastatic void	nlge_intr(void *arg);
182211946Sjchandrastatic int	nlge_irq_init(struct nlge_softc *sc);
183211946Sjchandrastatic void	nlge_irq_fini(struct nlge_softc *sc);
184211946Sjchandrastatic void	nlge_media_specific_init(struct nlge_softc *sc);
185211946Sjchandrastatic void	nlge_mii_init(device_t dev, struct nlge_softc *sc);
186211946Sjchandrastatic int	nlge_mii_read_internal(xlr_reg_t *mii_base, int phyaddr,
187211946Sjchandra    int regidx);
188211946Sjchandrastatic void 	nlge_mii_write_internal(xlr_reg_t *mii_base, int phyaddr,
189211946Sjchandra    int regidx, int regval);
190211946Sjchandravoid 		nlge_msgring_handler(int bucket, int size, int code,
191211946Sjchandra    int stid, struct msgrng_msg *msg, void *data);
192213475Sjchandrastatic void 	nlge_port_disable(struct nlge_softc *sc);
193211946Sjchandrastatic void 	nlge_port_enable(struct nlge_softc *sc);
194211946Sjchandrastatic void 	nlge_read_mac_addr(struct nlge_softc *sc);
195211946Sjchandrastatic void	nlge_sc_init(struct nlge_softc *sc, device_t dev,
196211946Sjchandra    struct xlr_gmac_port *port_info);
197211946Sjchandrastatic void 	nlge_set_mac_addr(struct nlge_softc *sc);
198211946Sjchandrastatic void	nlge_set_port_attribs(struct nlge_softc *,
199211946Sjchandra    struct xlr_gmac_port *);
200213475Sjchandrastatic void	nlge_mac_set_rx_mode(struct nlge_softc *sc);
201211946Sjchandrastatic void 	nlge_sgmii_init(struct nlge_softc *sc);
202215939Sjchandrastatic int 	nlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc,
203215939Sjchandra    struct mbuf *m);
204211946Sjchandra
205211946Sjchandrastatic int	prepare_fmn_message(struct nlge_softc *sc,
206211946Sjchandra    struct msgrng_msg *msg, uint32_t *n_entries, struct mbuf *m_head,
207211946Sjchandra    uint64_t fr_stid, struct nlge_tx_desc **tx_desc);
208211946Sjchandra
209212324Sjchandrastatic void 	release_tx_desc(vm_paddr_t phy_addr);
210211946Sjchandrastatic int	send_fmn_msg_tx(struct nlge_softc *, struct msgrng_msg *,
211211946Sjchandra    uint32_t n_entries);
212211946Sjchandra
213211946Sjchandra//#define DEBUG
214211946Sjchandra#ifdef DEBUG
215211946Sjchandrastatic int	mac_debug = 1;
216211946Sjchandra#undef PDEBUG
217211946Sjchandra#define PDEBUG(fmt, args...) \
218211946Sjchandra        do {\
219211946Sjchandra            if (mac_debug) {\
220211946Sjchandra                printf("[%s@%d|%s]: cpu_%d: " fmt, \
221211946Sjchandra                __FILE__, __LINE__, __FUNCTION__,  PCPU_GET(cpuid), ##args);\
222211946Sjchandra            }\
223211946Sjchandra        } while(0);
224211946Sjchandra
225211946Sjchandra/* Debug/dump functions */
226211946Sjchandrastatic void 	dump_reg(xlr_reg_t *addr, uint32_t offset, char *name);
227211946Sjchandrastatic void	dump_gmac_registers(struct nlge_softc *);
228211946Sjchandrastatic void	dump_na_registers(xlr_reg_t *base, int port_id);
229211946Sjchandrastatic void	dump_mac_stats(struct nlge_softc *sc);
230211946Sjchandrastatic void 	dump_mii_regs(struct nlge_softc *sc) __attribute__((used));
231211946Sjchandrastatic void 	dump_mii_data(struct mii_data *mii) __attribute__((used));
232211946Sjchandrastatic void	dump_board_info(struct xlr_board_info *);
233211946Sjchandrastatic void	dump_pcs_regs(struct nlge_softc *sc, int phy);
234211946Sjchandra
235211946Sjchandra#else
236211946Sjchandra#undef PDEBUG
237211946Sjchandra#define PDEBUG(fmt, args...)
238211946Sjchandra#define dump_reg(a, o, n)		/* nop */
239211946Sjchandra#define dump_gmac_registers(a)		/* nop */
240211946Sjchandra#define dump_na_registers(a, p)	/* nop */
241211946Sjchandra#define dump_board_info(b)		/* nop */
242211946Sjchandra#define dump_mac_stats(sc)		/* nop */
243211946Sjchandra#define dump_mii_regs(sc)		/* nop */
244211946Sjchandra#define dump_mii_data(mii)		/* nop */
245211946Sjchandra#define dump_pcs_regs(sc, phy)		/* nop */
246211946Sjchandra#endif
247211946Sjchandra
248211946Sjchandra/* Wrappers etc. to export the driver entry points. */
249211946Sjchandrastatic device_method_t nlna_methods[] = {
250211946Sjchandra	/* Device interface */
251211946Sjchandra	DEVMETHOD(device_probe,         nlna_probe),
252211946Sjchandra	DEVMETHOD(device_attach,        nlna_attach),
253211946Sjchandra	DEVMETHOD(device_detach,        nlna_detach),
254211946Sjchandra	DEVMETHOD(device_shutdown,      nlna_shutdown),
255211946Sjchandra	DEVMETHOD(device_suspend,       nlna_suspend),
256211946Sjchandra	DEVMETHOD(device_resume,        nlna_resume),
257211946Sjchandra
258211946Sjchandra	/* bus interface : TBD : what are these for ? */
259211946Sjchandra	DEVMETHOD(bus_setup_intr,       bus_generic_setup_intr),
260211946Sjchandra
261227843Smarius	DEVMETHOD_END
262211946Sjchandra};
263211946Sjchandra
264211946Sjchandrastatic driver_t	nlna_driver = {
265211946Sjchandra	"nlna",
266211946Sjchandra	nlna_methods,
267211946Sjchandra	sizeof(struct nlna_softc)
268211946Sjchandra};
269211946Sjchandra
270211946Sjchandrastatic devclass_t nlna_devclass;
271211946Sjchandra
272211946Sjchandrastatic device_method_t nlge_methods[] = {
273211946Sjchandra	/* Device interface */
274211946Sjchandra	DEVMETHOD(device_probe,         nlge_probe),
275211946Sjchandra	DEVMETHOD(device_attach,        nlge_attach),
276211946Sjchandra	DEVMETHOD(device_detach,        nlge_detach),
277211946Sjchandra	DEVMETHOD(device_shutdown,      bus_generic_shutdown),
278211946Sjchandra	DEVMETHOD(device_suspend,       nlge_suspend),
279211946Sjchandra	DEVMETHOD(device_resume,        nlge_resume),
280211946Sjchandra
281211946Sjchandra	/* MII interface */
282211946Sjchandra	DEVMETHOD(miibus_readreg, nlge_mii_read),
283211946Sjchandra	DEVMETHOD(miibus_writereg, nlge_mii_write),
284211946Sjchandra	DEVMETHOD(miibus_statchg, nlge_mac_mii_statchg),
285211946Sjchandra
286211946Sjchandra	{0, 0}
287211946Sjchandra};
288211946Sjchandra
289211946Sjchandrastatic driver_t	nlge_driver = {
290211946Sjchandra	"nlge",
291211946Sjchandra	nlge_methods,
292211946Sjchandra	sizeof(struct nlge_softc)
293211946Sjchandra};
294211946Sjchandra
295211946Sjchandrastatic devclass_t nlge_devclass;
296211946Sjchandra
297211946SjchandraDRIVER_MODULE(nlna, iodi, nlna_driver, nlna_devclass, 0, 0);
298211946SjchandraDRIVER_MODULE(nlge, nlna,  nlge_driver, nlge_devclass, 0, 0);
299211946SjchandraDRIVER_MODULE(miibus, nlge, miibus_driver, miibus_devclass, 0, 0);
300211946Sjchandra
301211946Sjchandrastatic uma_zone_t nl_tx_desc_zone;
302211946Sjchandra
303213475Sjchandra/* Tunables. */
304213475Sjchandrastatic int flow_classification = 0;
305213475SjchandraTUNABLE_INT("hw.nlge.flow_classification", &flow_classification);
306213475Sjchandra
307215939Sjchandra#define	NLGE_HW_CHKSUM		1
308215939Sjchandra
309212758Sjchandrastatic __inline void
310212758Sjchandraatomic_incr_long(unsigned long *addr)
311211946Sjchandra{
312212758Sjchandra	/* XXX: fix for 64 bit */
313212758Sjchandra	unsigned int *iaddr = (unsigned int *)addr;
314211946Sjchandra
315212758Sjchandra	xlr_ldaddwu(1, iaddr);
316211946Sjchandra}
317211946Sjchandra
318211946Sjchandrastatic int
319211946Sjchandranlna_probe(device_t dev)
320211946Sjchandra{
321211946Sjchandra	return (BUS_PROBE_DEFAULT);
322211946Sjchandra}
323211946Sjchandra
324211946Sjchandra/*
325211946Sjchandra * Add all attached GMAC/XGMAC ports to the device tree. Port
326211946Sjchandra * configuration is spread in two regions - common configuration
327211946Sjchandra * for all ports in the NA and per-port configuration in MAC-specific
328211946Sjchandra * region. This function does the following:
329211946Sjchandra *  - adds the ports to the device tree
330211946Sjchandra *  - reset the ports
331211946Sjchandra *  - do all the common initialization
332211946Sjchandra *  - invoke bus_generic_attach for per-port configuration
333211946Sjchandra *  - supply initial free rx descriptors to ports
334211946Sjchandra *  - initialize s/w data structures
335211946Sjchandra *  - finally, enable interrupts (only in the last NA).
336211946Sjchandra *
337211946Sjchandra * For reference, sample address space for common and per-port
338211946Sjchandra * registers is given below.
339211946Sjchandra *
340211946Sjchandra * The address map for RNA0 is:                           (typical value)
341211946Sjchandra *
342211946Sjchandra * XLR_IO_BASE +--------------------------------------+   0xbef0_0000
343211946Sjchandra *             |                                      |
344211946Sjchandra *             |                                      |
345211946Sjchandra *             |                                      |
346211946Sjchandra *             |                                      |
347211946Sjchandra *             |                                      |
348211946Sjchandra *             |                                      |
349211946Sjchandra * GMAC0  ---> +--------------------------------------+   0xbef0_c000
350211946Sjchandra *             |                                      |
351211946Sjchandra *             |                                      |
352211946Sjchandra * (common) -> |......................................|   0xbef0_c400
353211946Sjchandra *             |                                      |
354211946Sjchandra *             |   (RGMII/SGMII: common registers)    |
355211946Sjchandra *             |                                      |
356211946Sjchandra * GMAC1  ---> |--------------------------------------|   0xbef0_d000
357211946Sjchandra *             |                                      |
358211946Sjchandra *             |                                      |
359211946Sjchandra * (common) -> |......................................|   0xbef0_d400
360211946Sjchandra *             |                                      |
361211946Sjchandra *             |   (RGMII/SGMII: common registers)    |
362211946Sjchandra *             |                                      |
363211946Sjchandra *             |......................................|
364211946Sjchandra *       and so on ....
365211946Sjchandra *
366211946Sjchandra * Ref: Figure 14-3 and Table 14-1 of XLR PRM
367211946Sjchandra */
368211946Sjchandrastatic int
369211946Sjchandranlna_attach(device_t dev)
370211946Sjchandra{
371211946Sjchandra	struct xlr_gmac_block_t *block_info;
372211946Sjchandra	device_t		 gmac_dev;
373211946Sjchandra	struct nlna_softc	*sc;
374211946Sjchandra	int			 error;
375211946Sjchandra	int			 i;
376211946Sjchandra	int			 id;
377211946Sjchandra
378211946Sjchandra	id = device_get_unit(dev);
379211946Sjchandra	block_info = device_get_ivars(dev);
380211946Sjchandra	if (!block_info->enabled) {
381211946Sjchandra		return 0;
382211946Sjchandra	}
383211946Sjchandra
384211946Sjchandra#ifdef DEBUG
385211946Sjchandra	dump_board_info(&xlr_board_info);
386211946Sjchandra#endif
387211946Sjchandra	/* Initialize nlna state in softc structure */
388211946Sjchandra	sc = nlna_sc_init(dev, block_info);
389211946Sjchandra
390211946Sjchandra	/* Add device's for the ports controlled by this NA. */
391211946Sjchandra	if (block_info->type == XLR_GMAC) {
392211946Sjchandra		KASSERT(id < 2, ("No GMACs supported with this network"
393211946Sjchandra		    "accelerator: %d", id));
394211946Sjchandra		for (i = 0; i < sc->num_ports; i++) {
395211946Sjchandra			gmac_dev = device_add_child(dev, "nlge", -1);
396211946Sjchandra			device_set_ivars(gmac_dev, &block_info->gmac_port[i]);
397211946Sjchandra		}
398211946Sjchandra	} else if (block_info->type == XLR_XGMAC) {
399211946Sjchandra		KASSERT(id > 0 && id <= 2, ("No XGMACs supported with this"
400211946Sjchandra		    "network accelerator: %d", id));
401211946Sjchandra		gmac_dev = device_add_child(dev, "nlge", -1);
402211946Sjchandra		device_set_ivars(gmac_dev, &block_info->gmac_port[0]);
403211946Sjchandra	} else if (block_info->type == XLR_SPI4) {
404211946Sjchandra		/* SPI4 is not supported here */
405211946Sjchandra		device_printf(dev, "Unsupported: NA with SPI4 type");
406211946Sjchandra		return (ENOTSUP);
407211946Sjchandra	}
408211946Sjchandra
409211946Sjchandra	nlna_reset_ports(sc, block_info);
410211946Sjchandra
411211946Sjchandra	/* Initialize Network Accelarator registers. */
412211946Sjchandra	nlna_hw_init(sc);
413211946Sjchandra
414211946Sjchandra	error = bus_generic_attach(dev);
415211946Sjchandra	if (error) {
416211946Sjchandra		device_printf(dev, "failed to attach port(s)\n");
417211946Sjchandra		goto fail;
418211946Sjchandra	}
419211946Sjchandra
420211946Sjchandra	/* Send out the initial pool of free-descriptors for the rx path */
421211946Sjchandra	nlna_submit_rx_free_desc(sc, MAX_FRIN_SPILL);
422211946Sjchandra
423211946Sjchandra	/* S/w data structure initializations shared by all NA's. */
424211946Sjchandra	if (nl_tx_desc_zone == NULL) {
425211946Sjchandra		/* Create a zone for allocating tx descriptors */
426211946Sjchandra		nl_tx_desc_zone = uma_zcreate("NL Tx Desc",
427211946Sjchandra		    sizeof(struct nlge_tx_desc), NULL, NULL, NULL, NULL,
428211946Sjchandra		    XLR_CACHELINE_SIZE, 0);
429211946Sjchandra	}
430211946Sjchandra
431211946Sjchandra	/* Enable NA interrupts */
432211946Sjchandra	nlna_setup_intr(sc);
433211946Sjchandra
434211946Sjchandra	return (0);
435211946Sjchandra
436211946Sjchandrafail:
437211946Sjchandra	return (error);
438211946Sjchandra}
439211946Sjchandra
440211946Sjchandrastatic int
441211946Sjchandranlna_detach(device_t dev)
442211946Sjchandra{
443211946Sjchandra	struct nlna_softc *sc;
444211946Sjchandra
445211946Sjchandra	sc = device_get_softc(dev);
446211946Sjchandra	if (device_is_alive(dev)) {
447211946Sjchandra		nlna_disable_intr(sc);
448211946Sjchandra		/* This will make sure that per-port detach is complete
449211946Sjchandra		 * and all traffic on the ports has been stopped. */
450211946Sjchandra		bus_generic_detach(dev);
451211946Sjchandra		uma_zdestroy(nl_tx_desc_zone);
452211946Sjchandra	}
453211946Sjchandra
454211946Sjchandra	return (0);
455211946Sjchandra}
456211946Sjchandra
457211946Sjchandrastatic int
458211946Sjchandranlna_suspend(device_t dev)
459211946Sjchandra{
460211946Sjchandra
461211946Sjchandra	return (0);
462211946Sjchandra}
463211946Sjchandra
464211946Sjchandrastatic int
465211946Sjchandranlna_resume(device_t dev)
466211946Sjchandra{
467211946Sjchandra
468211946Sjchandra	return (0);
469211946Sjchandra}
470211946Sjchandra
471211946Sjchandrastatic int
472211946Sjchandranlna_shutdown(device_t dev)
473211946Sjchandra{
474211946Sjchandra	return (0);
475211946Sjchandra}
476211946Sjchandra
477211946Sjchandra
478211946Sjchandra/* GMAC port entry points */
479211946Sjchandrastatic int
480211946Sjchandranlge_probe(device_t dev)
481211946Sjchandra{
482211946Sjchandra	struct nlge_softc	*sc;
483211946Sjchandra	struct xlr_gmac_port	*port_info;
484211946Sjchandra	int index;
485211946Sjchandra	char *desc[] = { "RGMII", "SGMII", "RGMII/SGMII", "XGMAC", "XAUI",
486211946Sjchandra	    "Unknown"};
487211946Sjchandra
488211946Sjchandra	port_info = device_get_ivars(dev);
489211946Sjchandra	index = (port_info->type < XLR_RGMII || port_info->type > XLR_XAUI) ?
490211946Sjchandra	    5 : port_info->type;
491211946Sjchandra	device_set_desc_copy(dev, desc[index]);
492211946Sjchandra
493211946Sjchandra	sc = device_get_softc(dev);
494211946Sjchandra	nlge_sc_init(sc, dev, port_info);
495211946Sjchandra
496213475Sjchandra	nlge_port_disable(sc);
497211946Sjchandra
498211946Sjchandra	return (0);
499211946Sjchandra}
500211946Sjchandra
501211946Sjchandrastatic int
502211946Sjchandranlge_attach(device_t dev)
503211946Sjchandra{
504211946Sjchandra	struct nlge_softc *sc;
505211946Sjchandra	struct nlna_softc *nsc;
506211946Sjchandra	int error;
507211946Sjchandra
508211946Sjchandra	sc = device_get_softc(dev);
509211946Sjchandra
510211946Sjchandra	nlge_if_init(sc);
511211946Sjchandra	nlge_mii_init(dev, sc);
512211946Sjchandra	error = nlge_irq_init(sc);
513211946Sjchandra	if (error)
514211946Sjchandra		return error;
515211946Sjchandra	nlge_hw_init(sc);
516211946Sjchandra
517211946Sjchandra	nsc = (struct nlna_softc *)device_get_softc(device_get_parent(dev));
518211946Sjchandra	nsc->child_sc[sc->instance] = sc;
519211946Sjchandra
520211946Sjchandra	return (0);
521211946Sjchandra}
522211946Sjchandra
523211946Sjchandrastatic int
524211946Sjchandranlge_detach(device_t dev)
525211946Sjchandra{
526211946Sjchandra	struct nlge_softc *sc;
527211946Sjchandra	struct ifnet   *ifp;
528211946Sjchandra
529211946Sjchandra	sc = device_get_softc(dev);
530211946Sjchandra	ifp = sc->nlge_if;
531211946Sjchandra
532211946Sjchandra	if (device_is_attached(dev)) {
533213475Sjchandra		nlge_port_disable(sc);
534211946Sjchandra		nlge_irq_fini(sc);
535211946Sjchandra		ether_ifdetach(ifp);
536211946Sjchandra		bus_generic_detach(dev);
537211946Sjchandra	}
538211946Sjchandra	if (ifp)
539211946Sjchandra		if_free(ifp);
540211946Sjchandra
541211946Sjchandra	return (0);
542211946Sjchandra}
543211946Sjchandra
544211946Sjchandrastatic int
545211946Sjchandranlge_suspend(device_t dev)
546211946Sjchandra{
547211946Sjchandra	return (0);
548211946Sjchandra}
549211946Sjchandra
550211946Sjchandrastatic int
551211946Sjchandranlge_resume(device_t dev)
552211946Sjchandra{
553211946Sjchandra	return (0);
554211946Sjchandra}
555211946Sjchandra
556211946Sjchandrastatic void
557211946Sjchandranlge_init(void *addr)
558211946Sjchandra{
559211946Sjchandra	struct nlge_softc *sc;
560211946Sjchandra	struct ifnet   *ifp;
561211946Sjchandra
562211946Sjchandra	sc = (struct nlge_softc *)addr;
563211946Sjchandra	ifp = sc->nlge_if;
564211946Sjchandra
565211946Sjchandra	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
566211946Sjchandra		return;
567211946Sjchandra
568213475Sjchandra	nlge_gmac_config_speed(sc, 1);
569211946Sjchandra	ifp->if_drv_flags |= IFF_DRV_RUNNING;
570211946Sjchandra	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
571211946Sjchandra	nlge_port_enable(sc);
572211946Sjchandra
573211946Sjchandra	if (sc->port_type == XLR_SGMII) {
574211946Sjchandra		dump_pcs_regs(sc, 27);
575211946Sjchandra	}
576211946Sjchandra	dump_gmac_registers(sc);
577211946Sjchandra	dump_mac_stats(sc);
578211946Sjchandra}
579211946Sjchandra
580211946Sjchandrastatic int
581211946Sjchandranlge_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
582211946Sjchandra{
583211946Sjchandra	struct mii_data 	*mii;
584211946Sjchandra	struct nlge_softc 	*sc;
585211946Sjchandra	struct ifreq 		*ifr;
586211946Sjchandra	int 			error;
587211946Sjchandra
588211946Sjchandra	sc = ifp->if_softc;
589211946Sjchandra	error = 0;
590211946Sjchandra	ifr = (struct ifreq *)data;
591213475Sjchandra
592211946Sjchandra	switch(command) {
593211946Sjchandra	case SIOCSIFFLAGS:
594213475Sjchandra		NLGE_LOCK(sc);
595213475Sjchandra		if (ifp->if_flags & IFF_UP) {
596213475Sjchandra			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
597213475Sjchandra				nlge_init(sc);
598213475Sjchandra			}
599213475Sjchandra			if (ifp->if_flags & IFF_PROMISC &&
600213475Sjchandra			    !(sc->if_flags & IFF_PROMISC)) {
601213475Sjchandra				sc->if_flags |= IFF_PROMISC;
602213475Sjchandra				nlge_mac_set_rx_mode(sc);
603213475Sjchandra			} else if (!(ifp->if_flags & IFF_PROMISC) &&
604213475Sjchandra			    sc->if_flags & IFF_PROMISC) {
605213475Sjchandra				sc->if_flags &= IFF_PROMISC;
606213475Sjchandra				nlge_mac_set_rx_mode(sc);
607213475Sjchandra			}
608213475Sjchandra		} else {
609213475Sjchandra			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
610213475Sjchandra				nlge_port_disable(sc);
611213475Sjchandra			}
612213475Sjchandra		}
613213475Sjchandra		sc->if_flags = ifp->if_flags;
614213475Sjchandra		NLGE_UNLOCK(sc);
615213475Sjchandra		error = 0;
616211946Sjchandra		break;
617213475Sjchandra
618211946Sjchandra	case SIOCSIFMEDIA:
619211946Sjchandra	case SIOCGIFMEDIA:
620211946Sjchandra		if (sc->mii_bus != NULL) {
621211946Sjchandra			mii = (struct mii_data *)device_get_softc(sc->mii_bus);
622211946Sjchandra			error = ifmedia_ioctl(ifp, ifr, &mii->mii_media,
623211946Sjchandra			    command);
624211946Sjchandra		}
625211946Sjchandra		break;
626213475Sjchandra
627211946Sjchandra	default:
628211946Sjchandra		error = ether_ioctl(ifp, command, data);
629211946Sjchandra		break;
630211946Sjchandra	}
631211946Sjchandra
632211946Sjchandra	return (error);
633211946Sjchandra}
634211946Sjchandra
635211946Sjchandra/* This function is called from an interrupt handler */
636211946Sjchandravoid
637211946Sjchandranlge_msgring_handler(int bucket, int size, int code, int stid,
638211946Sjchandra		    struct msgrng_msg *msg, void *data)
639211946Sjchandra{
640211946Sjchandra	struct nlna_softc *na_sc;
641211946Sjchandra	struct nlge_softc *sc;
642212896Sjchandra	struct ifnet	*ifp;
643212896Sjchandra	struct mbuf	*m;
644212324Sjchandra	vm_paddr_t	phys_addr;
645211946Sjchandra	uint32_t	length;
646211946Sjchandra	int		ctrl;
647211946Sjchandra	int		tx_error;
648211946Sjchandra	int		port;
649211946Sjchandra	int		is_p2p;
650211946Sjchandra
651211946Sjchandra	is_p2p = 0;
652211946Sjchandra	tx_error = 0;
653211946Sjchandra	length = (msg->msg0 >> 40) & 0x3fff;
654211946Sjchandra	na_sc = (struct nlna_softc *)data;
655211946Sjchandra	if (length == 0) {
656211946Sjchandra		ctrl = CTRL_REG_FREE;
657212324Sjchandra		phys_addr = msg->msg0 & 0xffffffffffULL;
658211946Sjchandra		port = (msg->msg0 >> 54) & 0x0f;
659211946Sjchandra		is_p2p = (msg->msg0 >> 62) & 0x1;
660211946Sjchandra		tx_error = (msg->msg0 >> 58) & 0xf;
661211946Sjchandra	} else {
662211946Sjchandra		ctrl = CTRL_SNGL;
663212324Sjchandra		phys_addr = msg->msg0 & 0xffffffffe0ULL;
664211946Sjchandra		length = length - BYTE_OFFSET - MAC_CRC_LEN;
665211946Sjchandra		port = msg->msg0 & 0x0f;
666211946Sjchandra	}
667211946Sjchandra
668211946Sjchandra	sc = na_sc->child_sc[port];
669211946Sjchandra	if (sc == NULL) {
670211946Sjchandra		printf("Message (of %d len) with softc=NULL on %d port (type=%s)\n",
671211946Sjchandra		    length, port, (ctrl == CTRL_SNGL ? "Pkt rx" :
672211946Sjchandra		    "Freeback for tx packet"));
673211946Sjchandra		return;
674211946Sjchandra	}
675211946Sjchandra
676211946Sjchandra	if (ctrl == CTRL_REG_FREE || ctrl == CTRL_JUMBO_FREE) {
677212790Sjchandra		ifp = sc->nlge_if;
678212790Sjchandra		if (!tx_error) {
679212790Sjchandra			if (is_p2p) {
680212790Sjchandra				release_tx_desc(phys_addr);
681212790Sjchandra			} else {
682212957Sjchandra#ifdef __mips_n64
683212896Sjchandra				m = (struct mbuf *)(uintptr_t)xlr_paddr_ld(phys_addr);
684212896Sjchandra				m->m_nextpkt = NULL;
685212896Sjchandra#else
686212896Sjchandra				m = (struct mbuf *)(uintptr_t)phys_addr;
687212896Sjchandra#endif
688212896Sjchandra				m_freem(m);
689212790Sjchandra			}
690212790Sjchandra			NLGE_LOCK(sc);
691212790Sjchandra			if (ifp->if_drv_flags & IFF_DRV_OACTIVE){
692212790Sjchandra				ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
693212790Sjchandra			}
694212790Sjchandra			NLGE_UNLOCK(sc);
695212324Sjchandra		} else {
696212790Sjchandra			printf("ERROR: Tx fb error (%d) on port %d\n", tx_error,
697212790Sjchandra			    port);
698211946Sjchandra		}
699212758Sjchandra		atomic_incr_long((tx_error) ? &ifp->if_oerrors: &ifp->if_opackets);
700211946Sjchandra	} else if (ctrl == CTRL_SNGL || ctrl == CTRL_START) {
701211946Sjchandra		/* Rx Packet */
702211946Sjchandra
703211946Sjchandra		nlge_rx(sc, phys_addr, length);
704211946Sjchandra		nlna_submit_rx_free_desc(na_sc, 1);	/* return free descr to NA */
705211946Sjchandra	} else {
706212896Sjchandra		printf("[%s]: unrecognized ctrl=%d!\n", __func__, ctrl);
707211946Sjchandra	}
708211946Sjchandra
709211946Sjchandra}
710211946Sjchandra
711215939Sjchandrastatic int
712215939Sjchandranlge_tx(struct ifnet *ifp, struct mbuf *m)
713211946Sjchandra{
714215939Sjchandra	return (nlge_start_locked(ifp, ifp->if_softc, m));
715211946Sjchandra}
716212790Sjchandra
717215939Sjchandrastatic int
718215939Sjchandranlge_start_locked(struct ifnet *ifp, struct nlge_softc *sc, struct mbuf *m)
719212790Sjchandra{
720211946Sjchandra	struct msgrng_msg 	msg;
721211946Sjchandra	struct nlge_tx_desc 	*tx_desc;
722211946Sjchandra	uint64_t		fr_stid;
723211946Sjchandra	uint32_t		cpu;
724212790Sjchandra	uint32_t		n_entries;
725211946Sjchandra	uint32_t		tid;
726215939Sjchandra	int 			error, ret;
727211946Sjchandra
728215939Sjchandra	if (m == NULL)
729215939Sjchandra		return (0);
730215939Sjchandra
731215939Sjchandra	tx_desc = NULL;
732215939Sjchandra	error = 0;
733215939Sjchandra	if (!(ifp->if_drv_flags & IFF_DRV_RUNNING) ||
734215939Sjchandra	    ifp->if_drv_flags & IFF_DRV_OACTIVE) {
735215939Sjchandra	    	error = ENXIO;
736215939Sjchandra		goto fail;	// note: mbuf will get free'd
737215939Sjchandra	}
738215939Sjchandra
739211946Sjchandra	cpu = xlr_core_id();
740211946Sjchandra	tid = xlr_thr_id();
741212790Sjchandra	/* H/w threads [0, 2] --> bucket 6 and [1, 3] --> bucket 7 */
742212790Sjchandra	fr_stid = cpu * 8 + 6 + (tid % 2);
743211946Sjchandra
744215939Sjchandra	/*
745215939Sjchandra	 * First, remove some freeback messages before transmitting
746215939Sjchandra	 * any new packets. However, cap the number of messages
747215939Sjchandra	 * drained to permit this thread to continue with its
748215939Sjchandra	 * transmission.
749215939Sjchandra	 *
750215939Sjchandra	 * Mask for buckets {6, 7} is 0xc0
751215939Sjchandra	 */
752215939Sjchandra	xlr_msgring_handler(0xc0, 4);
753215939Sjchandra
754215939Sjchandra	ret = prepare_fmn_message(sc, &msg, &n_entries, m, fr_stid, &tx_desc);
755215939Sjchandra	if (ret) {
756215939Sjchandra		error = (ret == 2) ? ENOBUFS : ENOTSUP;
757215939Sjchandra		goto fail;
758211946Sjchandra	}
759215939Sjchandra	ret = send_fmn_msg_tx(sc, &msg, n_entries);
760215939Sjchandra	if (ret != 0) {
761215939Sjchandra		error = EBUSY;
762215939Sjchandra		goto fail;
763215939Sjchandra	}
764211946Sjchandra
765215939Sjchandra	return (0);
766212790Sjchandra
767211946Sjchandrafail:
768211946Sjchandra	if (tx_desc != NULL) {
769211946Sjchandra		uma_zfree(nl_tx_desc_zone, tx_desc);
770211946Sjchandra	}
771211946Sjchandra	if (m != NULL) {
772215939Sjchandra		if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
773215939Sjchandra			NLGE_LOCK(sc);
774215939Sjchandra			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
775215939Sjchandra			NLGE_UNLOCK(sc);
776215939Sjchandra		}
777215939Sjchandra		m_freem(m);
778212758Sjchandra		atomic_incr_long(&ifp->if_iqdrops);
779211946Sjchandra	}
780215939Sjchandra	return (error);
781211946Sjchandra}
782211946Sjchandra
783211946Sjchandrastatic void
784211946Sjchandranlge_rx(struct nlge_softc *sc, vm_paddr_t paddr, int len)
785211946Sjchandra{
786212758Sjchandra	struct ifnet	*ifp;
787212758Sjchandra	struct mbuf	*m;
788212758Sjchandra	uint64_t	tm, mag;
789212758Sjchandra	uint32_t	sr;
790211946Sjchandra
791211946Sjchandra	sr = xlr_enable_kx();
792212758Sjchandra	tm = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE);
793212758Sjchandra	mag = xlr_paddr_ld(paddr - XLR_CACHELINE_SIZE + sizeof(uint64_t));
794212758Sjchandra	xlr_restore_kx(sr);
795211946Sjchandra
796211946Sjchandra	m = (struct mbuf *)(intptr_t)tm;
797211946Sjchandra	if (mag != 0xf00bad) {
798211946Sjchandra		/* somebody else's packet. Error - FIXME in intialization */
799212896Sjchandra		printf("cpu %d: *ERROR* Not my packet paddr %jx\n",
800212896Sjchandra		    xlr_core_id(), (uintmax_t)paddr);
801211946Sjchandra		return;
802211946Sjchandra	}
803211946Sjchandra
804211946Sjchandra	ifp = sc->nlge_if;
805213475Sjchandra
806215939Sjchandra#ifdef NLGE_HW_CHKSUM
807215939Sjchandra	m->m_pkthdr.csum_flags = CSUM_IP_CHECKED;
808215939Sjchandra	if (m->m_data[10] & 0x2) {
809215939Sjchandra		m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
810215939Sjchandra		if (m->m_data[10] & 0x1) {
811215939Sjchandra			m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID |
812215939Sjchandra			    CSUM_PSEUDO_HDR);
813215939Sjchandra			m->m_pkthdr.csum_data = htons(0xffff);
814215939Sjchandra		}
815215939Sjchandra	}
816215939Sjchandra	m->m_data += NLGE_PREPAD_LEN;
817215939Sjchandra	len -= NLGE_PREPAD_LEN;
818215939Sjchandra#else
819215939Sjchandra	m->m_pkthdr.csum_flags = 0;
820215939Sjchandra#endif
821215939Sjchandra
822211946Sjchandra	/* align the data */
823215939Sjchandra	m->m_data += BYTE_OFFSET ;
824211946Sjchandra	m->m_pkthdr.len = m->m_len = len;
825211946Sjchandra	m->m_pkthdr.rcvif = ifp;
826211946Sjchandra
827212758Sjchandra	atomic_incr_long(&ifp->if_ipackets);
828211946Sjchandra	(*ifp->if_input)(ifp, m);
829211946Sjchandra}
830211946Sjchandra
831211946Sjchandrastatic int
832211946Sjchandranlge_mii_write(struct device *dev, int phyaddr, int regidx, int regval)
833211946Sjchandra{
834211946Sjchandra	struct nlge_softc *sc;
835211946Sjchandra
836211946Sjchandra	sc = device_get_softc(dev);
837213893Smarius	if (sc->port_type != XLR_XGMII)
838211946Sjchandra		nlge_mii_write_internal(sc->mii_base, phyaddr, regidx, regval);
839211946Sjchandra
840211946Sjchandra	return (0);
841211946Sjchandra}
842211946Sjchandra
843211946Sjchandrastatic int
844211946Sjchandranlge_mii_read(struct device *dev, int phyaddr, int regidx)
845211946Sjchandra{
846211946Sjchandra	struct nlge_softc *sc;
847211946Sjchandra	int val;
848211946Sjchandra
849211946Sjchandra	sc = device_get_softc(dev);
850214107Sjchandra	val = (sc->port_type == XLR_XGMII) ? (0xffff) :
851211946Sjchandra	    nlge_mii_read_internal(sc->mii_base, phyaddr, regidx);
852211946Sjchandra
853211946Sjchandra	return (val);
854211946Sjchandra}
855211946Sjchandra
856211946Sjchandrastatic void
857211946Sjchandranlge_mac_mii_statchg(device_t dev)
858211946Sjchandra{
859211946Sjchandra}
860211946Sjchandra
861211946Sjchandrastatic int
862211946Sjchandranlge_mediachange(struct ifnet *ifp)
863211946Sjchandra{
864211946Sjchandra	return 0;
865211946Sjchandra}
866211946Sjchandra
867211946Sjchandrastatic void
868211946Sjchandranlge_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
869211946Sjchandra{
870211946Sjchandra	struct nlge_softc *sc;
871211946Sjchandra	struct mii_data *md;
872211946Sjchandra
873211946Sjchandra	md = NULL;
874211946Sjchandra	sc = ifp->if_softc;
875211946Sjchandra	if (sc->mii_bus)
876211946Sjchandra		md = device_get_softc(sc->mii_bus);
877211946Sjchandra
878211946Sjchandra	ifmr->ifm_status = IFM_AVALID;
879211946Sjchandra	ifmr->ifm_active = IFM_ETHER;
880211946Sjchandra
881211946Sjchandra	if (sc->link == xlr_mac_link_down)
882211946Sjchandra		return;
883211946Sjchandra
884211946Sjchandra	if (md != NULL)
885211946Sjchandra		ifmr->ifm_active = md->mii_media.ifm_cur->ifm_media;
886211946Sjchandra	ifmr->ifm_status |= IFM_ACTIVE;
887211946Sjchandra}
888211946Sjchandra
889211946Sjchandrastatic struct nlna_softc *
890211946Sjchandranlna_sc_init(device_t dev, struct xlr_gmac_block_t *blk)
891211946Sjchandra{
892211946Sjchandra	struct nlna_softc	*sc;
893211946Sjchandra
894211946Sjchandra	sc = device_get_softc(dev);
895211946Sjchandra	memset(sc, 0, sizeof(*sc));
896211946Sjchandra	sc->nlna_dev = dev;
897212896Sjchandra	sc->base = xlr_io_mmio(blk->baseaddr);
898211946Sjchandra	sc->rfrbucket = blk->station_rfr;
899211946Sjchandra	sc->station_id = blk->station_id;
900211946Sjchandra	sc->na_type = blk->type;
901211946Sjchandra	sc->mac_type = blk->mode;
902211946Sjchandra	sc->num_ports = blk->num_ports;
903211946Sjchandra
904211946Sjchandra	sc->mdio_set.port_vec 	= sc->mdio_sc;
905211946Sjchandra	sc->mdio_set.vec_sz   	= XLR_MAX_MACS;
906211946Sjchandra
907211946Sjchandra	return (sc);
908211946Sjchandra}
909211946Sjchandra
910211946Sjchandra/*
911211946Sjchandra * Do:
912211946Sjchandra *     - Initialize common GMAC registers (index range 0x100-0x3ff).
913211946Sjchandra */
914211946Sjchandrastatic void
915211946Sjchandranlna_hw_init(struct nlna_softc *sc)
916211946Sjchandra{
917211946Sjchandra
918211946Sjchandra	/*
919213377Sjchandra	 * Register message ring handler for the NA block, messages from
920213443Sjchandra	 * the GMAC will have source station id to the first bucket of the
921213377Sjchandra	 * NA FMN station, so register just that station id.
922213377Sjchandra	 */
923213377Sjchandra	if (register_msgring_handler(sc->station_id, sc->station_id + 1,
924213377Sjchandra	    nlge_msgring_handler, sc)) {
925211946Sjchandra		panic("Couldn't register msgring handler\n");
926211946Sjchandra	}
927211946Sjchandra	nlna_config_fifo_spill_area(sc);
928211946Sjchandra	nlna_config_pde(sc);
929211946Sjchandra	nlna_config_common(sc);
930211946Sjchandra	nlna_config_parser(sc);
931211946Sjchandra	nlna_config_classifier(sc);
932211946Sjchandra}
933211946Sjchandra
934211946Sjchandra/*
935211946Sjchandra * Enable interrupts on all the ports controlled by this NA. For now, we
936211946Sjchandra * only care about the MII interrupt and this has to be enabled only
937211946Sjchandra * on the port id0.
938211946Sjchandra *
939211946Sjchandra * This function is not in-sync with the regular way of doing things - it
940211946Sjchandra * executes only in the context of the last active network accelerator (and
941211946Sjchandra * thereby has some ugly accesses in the device tree). Though inelegant, it
942211946Sjchandra * is necessary to do it this way as the per-port interrupts can be
943211946Sjchandra * setup/enabled only after all the network accelerators have been
944211946Sjchandra * initialized.
945211946Sjchandra */
946211946Sjchandrastatic void
947211946Sjchandranlna_setup_intr(struct nlna_softc *sc)
948211946Sjchandra{
949211946Sjchandra	struct nlna_softc *na_sc[XLR_MAX_NLNA];
950211946Sjchandra	struct nlge_port_set *pset;
951211946Sjchandra	struct xlr_gmac_port *port_info;
952211946Sjchandra	device_t	iodi_dev;
953211946Sjchandra	int 		i, j;
954211946Sjchandra
955211946Sjchandra	if (!nlna_is_last_active_na(sc))
956211946Sjchandra		return ;
957211946Sjchandra
958211946Sjchandra	/* Collect all nlna softc pointers */
959211946Sjchandra	memset(na_sc, 0, sizeof(*na_sc) * XLR_MAX_NLNA);
960211946Sjchandra	iodi_dev = device_get_parent(sc->nlna_dev);
961211946Sjchandra	nlna_get_all_softc(iodi_dev, na_sc, XLR_MAX_NLNA);
962211946Sjchandra
963211946Sjchandra	/* Setup the MDIO interrupt lists. */
964211946Sjchandra	/*
965211946Sjchandra	 * MDIO interrupts are coarse - a single interrupt line provides
966211946Sjchandra	 * information about one of many possible ports. To figure out the
967211946Sjchandra	 * exact port on which action is to be taken, all of the ports
968211946Sjchandra	 * linked to an MDIO interrupt should be read. To enable this,
969211946Sjchandra	 * ports need to add themselves to port sets.
970211946Sjchandra	 */
971211946Sjchandra	for (i = 0; i < XLR_MAX_NLNA; i++) {
972211946Sjchandra		if (na_sc[i] == NULL)
973211946Sjchandra			continue;
974211946Sjchandra		for (j = 0; j < na_sc[i]->num_ports; j++) {
975211946Sjchandra			/* processing j-th port on i-th NA */
976211946Sjchandra			port_info = device_get_ivars(
977211946Sjchandra			    na_sc[i]->child_sc[j]->nlge_dev);
978211946Sjchandra			pset = &na_sc[port_info->mdint_id]->mdio_set;
979211946Sjchandra			nlna_add_to_port_set(pset, na_sc[i]->child_sc[j]);
980211946Sjchandra		}
981211946Sjchandra	}
982211946Sjchandra
983211946Sjchandra	/* Enable interrupts */
984211946Sjchandra	for (i = 0; i < XLR_MAX_NLNA; i++) {
985211946Sjchandra		if (na_sc[i] != NULL && na_sc[i]->na_type != XLR_XGMAC) {
986211946Sjchandra			nlna_enable_intr(na_sc[i]);
987211946Sjchandra		}
988211946Sjchandra	}
989211946Sjchandra}
990211946Sjchandra
991211946Sjchandrastatic void
992211946Sjchandranlna_add_to_port_set(struct nlge_port_set *pset, struct nlge_softc *sc)
993211946Sjchandra{
994211946Sjchandra	int i;
995211946Sjchandra
996211946Sjchandra	/* step past the non-NULL elements */
997211946Sjchandra	for (i = 0; i < pset->vec_sz && pset->port_vec[i] != NULL; i++) ;
998211946Sjchandra	if (i < pset->vec_sz)
999211946Sjchandra		pset->port_vec[i] = sc;
1000211946Sjchandra	else
1001211946Sjchandra		printf("warning: internal error: out-of-bounds for MDIO array");
1002211946Sjchandra}
1003211946Sjchandra
1004211946Sjchandrastatic void
1005211946Sjchandranlna_enable_intr(struct nlna_softc *sc)
1006211946Sjchandra{
1007211946Sjchandra	int i;
1008211946Sjchandra
1009211946Sjchandra	for (i = 0; i < sc->num_ports; i++) {
1010211946Sjchandra		if (sc->child_sc[i]->instance == 0)
1011211946Sjchandra			NLGE_WRITE(sc->child_sc[i]->base, R_INTMASK,
1012211946Sjchandra			    (1 << O_INTMASK__MDInt));
1013211946Sjchandra	}
1014211946Sjchandra}
1015211946Sjchandra
1016211946Sjchandrastatic void
1017211946Sjchandranlna_disable_intr(struct nlna_softc *sc)
1018211946Sjchandra{
1019211946Sjchandra	int i;
1020211946Sjchandra
1021211946Sjchandra	for (i = 0; i < sc->num_ports; i++) {
1022211946Sjchandra		if (sc->child_sc[i]->instance == 0)
1023211946Sjchandra			NLGE_WRITE(sc->child_sc[i]->base, R_INTMASK, 0);
1024211946Sjchandra	}
1025211946Sjchandra}
1026211946Sjchandra
1027211946Sjchandrastatic int
1028211946Sjchandranlna_is_last_active_na(struct nlna_softc *sc)
1029211946Sjchandra{
1030211946Sjchandra	int id;
1031211946Sjchandra
1032211946Sjchandra	id = device_get_unit(sc->nlna_dev);
1033211946Sjchandra	return (id == 2 || xlr_board_info.gmac_block[id + 1].enabled == 0);
1034211946Sjchandra}
1035211946Sjchandra
1036211946Sjchandrastatic void
1037211946Sjchandranlna_submit_rx_free_desc(struct nlna_softc *sc, uint32_t n_desc)
1038211946Sjchandra{
1039212347Sjchandra	struct msgrng_msg msg;
1040211946Sjchandra	void           *ptr;
1041212347Sjchandra	uint32_t	msgrng_flags;
1042212347Sjchandra	int		i, n, stid, ret, code;
1043211946Sjchandra
1044211946Sjchandra	if (n_desc > 1) {
1045211946Sjchandra		PDEBUG("Sending %d free-in descriptors to station=%d\n", n_desc,
1046211946Sjchandra		    sc->rfrbucket);
1047211946Sjchandra	}
1048211946Sjchandra
1049212347Sjchandra	stid = sc->rfrbucket;
1050212347Sjchandra	code = (sc->na_type == XLR_XGMAC) ? MSGRNG_CODE_XGMAC : MSGRNG_CODE_MAC;
1051212347Sjchandra	memset(&msg, 0, sizeof(msg));
1052212347Sjchandra
1053211946Sjchandra	for (i = 0; i < n_desc; i++) {
1054211946Sjchandra		ptr = get_buf();
1055211946Sjchandra		if (!ptr) {
1056211946Sjchandra			ret = -ENOMEM;
1057211946Sjchandra			device_printf(sc->nlna_dev, "Cannot allocate mbuf\n");
1058211946Sjchandra			break;
1059211946Sjchandra		}
1060211946Sjchandra
1061211946Sjchandra		/* Send the free Rx desc to the MAC */
1062212347Sjchandra		msg.msg0 = vtophys(ptr) & 0xffffffffe0ULL;
1063212347Sjchandra		n = 0;
1064212347Sjchandra		do {
1065212347Sjchandra			msgrng_flags = msgrng_access_enable();
1066212553Sjchandra			ret = message_send(1, code, stid, &msg);
1067212347Sjchandra			msgrng_restore(msgrng_flags);
1068212790Sjchandra			KASSERT(n++ < 100000, ("Too many credit fails in rx path\n"));
1069212347Sjchandra		} while (ret != 0);
1070211946Sjchandra	}
1071211946Sjchandra}
1072211946Sjchandra
1073211946Sjchandrastatic __inline__ void *
1074211946Sjchandranlna_config_spill(xlr_reg_t *base, int reg_start_0, int reg_start_1,
1075211946Sjchandra    int reg_size, int size)
1076211946Sjchandra{
1077211946Sjchandra	void	*spill;
1078211946Sjchandra	uint64_t phys_addr;
1079211946Sjchandra	uint32_t spill_size;
1080211946Sjchandra
1081211946Sjchandra	spill_size = size;
1082211946Sjchandra	spill = contigmalloc((spill_size + XLR_CACHELINE_SIZE), M_DEVBUF,
1083211946Sjchandra	    M_NOWAIT | M_ZERO, 0, 0xffffffff, XLR_CACHELINE_SIZE, 0);
1084211946Sjchandra	if (spill == NULL || ((vm_offset_t) spill & (XLR_CACHELINE_SIZE - 1))) {
1085211946Sjchandra		panic("Unable to allocate memory for spill area!\n");
1086211946Sjchandra	}
1087211946Sjchandra	phys_addr = vtophys(spill);
1088211946Sjchandra	PDEBUG("Allocated spill %d bytes at %llx\n", size, phys_addr);
1089211946Sjchandra	NLGE_WRITE(base, reg_start_0, (phys_addr >> 5) & 0xffffffff);
1090211946Sjchandra	NLGE_WRITE(base, reg_start_1, (phys_addr >> 37) & 0x07);
1091211946Sjchandra	NLGE_WRITE(base, reg_size, spill_size);
1092211946Sjchandra
1093211946Sjchandra	return (spill);
1094211946Sjchandra}
1095211946Sjchandra
1096211946Sjchandra/*
1097211946Sjchandra * Configure the 6 FIFO's that are used by the network accelarator to
1098211946Sjchandra * communicate with the rest of the XLx device. 4 of the FIFO's are for
1099211946Sjchandra * packets from NA --> cpu (called Class FIFO's) and 2 are for feeding
1100211946Sjchandra * the NA with free descriptors.
1101211946Sjchandra */
1102211946Sjchandrastatic void
1103211946Sjchandranlna_config_fifo_spill_area(struct nlna_softc *sc)
1104211946Sjchandra{
1105211946Sjchandra	sc->frin_spill = nlna_config_spill(sc->base,
1106211946Sjchandra				     	R_REG_FRIN_SPILL_MEM_START_0,
1107211946Sjchandra				     	R_REG_FRIN_SPILL_MEM_START_1,
1108211946Sjchandra				     	R_REG_FRIN_SPILL_MEM_SIZE,
1109211946Sjchandra				     	MAX_FRIN_SPILL *
1110211946Sjchandra				     	sizeof(struct fr_desc));
1111211946Sjchandra	sc->frout_spill = nlna_config_spill(sc->base,
1112211946Sjchandra				     	R_FROUT_SPILL_MEM_START_0,
1113211946Sjchandra				     	R_FROUT_SPILL_MEM_START_1,
1114211946Sjchandra				     	R_FROUT_SPILL_MEM_SIZE,
1115211946Sjchandra				     	MAX_FROUT_SPILL *
1116211946Sjchandra				     	sizeof(struct fr_desc));
1117211946Sjchandra	sc->class_0_spill = nlna_config_spill(sc->base,
1118211946Sjchandra				     	R_CLASS0_SPILL_MEM_START_0,
1119211946Sjchandra				     	R_CLASS0_SPILL_MEM_START_1,
1120211946Sjchandra				     	R_CLASS0_SPILL_MEM_SIZE,
1121211946Sjchandra				     	MAX_CLASS_0_SPILL *
1122211946Sjchandra				     	sizeof(union rx_tx_desc));
1123211946Sjchandra	sc->class_1_spill = nlna_config_spill(sc->base,
1124211946Sjchandra				     	R_CLASS1_SPILL_MEM_START_0,
1125211946Sjchandra				     	R_CLASS1_SPILL_MEM_START_1,
1126211946Sjchandra				     	R_CLASS1_SPILL_MEM_SIZE,
1127211946Sjchandra				     	MAX_CLASS_1_SPILL *
1128211946Sjchandra				     	sizeof(union rx_tx_desc));
1129211946Sjchandra	sc->class_2_spill = nlna_config_spill(sc->base,
1130211946Sjchandra				     	R_CLASS2_SPILL_MEM_START_0,
1131211946Sjchandra				     	R_CLASS2_SPILL_MEM_START_1,
1132211946Sjchandra				     	R_CLASS2_SPILL_MEM_SIZE,
1133211946Sjchandra				     	MAX_CLASS_2_SPILL *
1134211946Sjchandra				     	sizeof(union rx_tx_desc));
1135211946Sjchandra	sc->class_3_spill = nlna_config_spill(sc->base,
1136211946Sjchandra				     	R_CLASS3_SPILL_MEM_START_0,
1137211946Sjchandra				     	R_CLASS3_SPILL_MEM_START_1,
1138211946Sjchandra				     	R_CLASS3_SPILL_MEM_SIZE,
1139211946Sjchandra				     	MAX_CLASS_3_SPILL *
1140211946Sjchandra				     	sizeof(union rx_tx_desc));
1141211946Sjchandra}
1142211946Sjchandra
1143211946Sjchandra/* Set the CPU buckets that receive packets from the NA class FIFOs. */
1144211946Sjchandrastatic void
1145211946Sjchandranlna_config_pde(struct nlna_softc *sc)
1146211946Sjchandra{
1147211946Sjchandra	uint64_t	bucket_map;
1148211946Sjchandra	uint32_t	cpumask;
1149211946Sjchandra	int		i, cpu, bucket;
1150211946Sjchandra
1151211946Sjchandra	cpumask = 0x1;
1152211946Sjchandra#ifdef SMP
1153211946Sjchandra	/*
1154211946Sjchandra         * rge may be called before SMP start in a BOOTP/NFSROOT
1155211946Sjchandra         * setup. we will distribute packets to other cpus only when
1156211946Sjchandra         * the SMP is started.
1157211946Sjchandra	 */
1158211946Sjchandra	if (smp_started)
1159211946Sjchandra		cpumask = xlr_hw_thread_mask;
1160211946Sjchandra#endif
1161211946Sjchandra	bucket_map = 0;
1162211946Sjchandra	for (i = 0; i < 32; i++) {
1163211946Sjchandra		if (cpumask & (1 << i)) {
1164211946Sjchandra			cpu = i;
1165213377Sjchandra			/* use bucket 0 and 1 on every core for NA msgs */
1166213377Sjchandra			bucket = cpu/4 * 8;
1167213377Sjchandra			bucket_map |= (3ULL << bucket);
1168211946Sjchandra		}
1169211946Sjchandra	}
1170213475Sjchandra
1171211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_0, (bucket_map & 0xffffffff));
1172211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_0 + 1, ((bucket_map >> 32) & 0xffffffff));
1173211946Sjchandra
1174211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_1, (bucket_map & 0xffffffff));
1175211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_1 + 1, ((bucket_map >> 32) & 0xffffffff));
1176211946Sjchandra
1177211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_2, (bucket_map & 0xffffffff));
1178211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_2 + 1, ((bucket_map >> 32) & 0xffffffff));
1179211946Sjchandra
1180211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_3, (bucket_map & 0xffffffff));
1181211946Sjchandra	NLGE_WRITE(sc->base, R_PDE_CLASS_3 + 1, ((bucket_map >> 32) & 0xffffffff));
1182211946Sjchandra}
1183211946Sjchandra
1184213377Sjchandra/*
1185213377Sjchandra * Update the network accelerator packet distribution engine for SMP.
1186213377Sjchandra * On bootup, we have just the boot hw thread handling all packets, on SMP
1187213377Sjchandra * start, we can start distributing packets across all the cores which are up.
1188213377Sjchandra */
1189211946Sjchandrastatic void
1190211946Sjchandranlna_smp_update_pde(void *dummy __unused)
1191211946Sjchandra{
1192211946Sjchandra	device_t	   iodi_dev;
1193211946Sjchandra	struct nlna_softc *na_sc[XLR_MAX_NLNA];
1194211946Sjchandra	int i;
1195211946Sjchandra
1196211946Sjchandra	printf("Updating packet distribution for SMP\n");
1197211946Sjchandra
1198211946Sjchandra	iodi_dev = devclass_get_device(devclass_find("iodi"), 0);
1199211946Sjchandra	nlna_get_all_softc(iodi_dev, na_sc, XLR_MAX_NLNA);
1200211946Sjchandra
1201211946Sjchandra	for (i = 0; i < XLR_MAX_NLNA; i++) {
1202211946Sjchandra		if (na_sc[i] == NULL)
1203211946Sjchandra			continue;
1204211946Sjchandra		nlna_disable_ports(na_sc[i]);
1205211946Sjchandra		nlna_config_pde(na_sc[i]);
1206213475Sjchandra		nlna_config_translate_table(na_sc[i]);
1207211946Sjchandra		nlna_enable_ports(na_sc[i]);
1208211946Sjchandra	}
1209211946Sjchandra}
1210211946Sjchandra
1211211946SjchandraSYSINIT(nlna_smp_update_pde, SI_SUB_SMP, SI_ORDER_ANY, nlna_smp_update_pde,
1212211946Sjchandra    NULL);
1213211946Sjchandra
1214211946Sjchandrastatic void
1215213475Sjchandranlna_config_translate_table(struct nlna_softc *sc)
1216213475Sjchandra{
1217213475Sjchandra	uint32_t cpu_mask;
1218213475Sjchandra	uint32_t val;
1219213475Sjchandra	int bkts[32]; /* one bucket is assumed for each cpu */
1220213475Sjchandra	int b1, b2, c1, c2, i, j, k;
1221213475Sjchandra	int use_bkt;
1222213475Sjchandra
1223213475Sjchandra	if (!flow_classification)
1224213475Sjchandra		return;
1225213475Sjchandra
1226213475Sjchandra	use_bkt = 1;
1227213475Sjchandra	if (smp_started)
1228213475Sjchandra		cpu_mask = xlr_hw_thread_mask;
1229213475Sjchandra	else
1230213475Sjchandra		return;
1231213475Sjchandra
1232213475Sjchandra	printf("Using %s-based distribution\n", (use_bkt) ? "bucket" : "class");
1233213475Sjchandra
1234213475Sjchandra	j = 0;
1235213475Sjchandra	for(i = 0; i < 32; i++) {
1236213475Sjchandra		if ((1 << i) & cpu_mask){
1237213475Sjchandra		/* for each cpu, mark the 4+threadid bucket */
1238213475Sjchandra			bkts[j] = ((i / 4) * 8) + (i % 4);
1239213475Sjchandra			j++;
1240213475Sjchandra		}
1241213475Sjchandra	}
1242213475Sjchandra
1243213475Sjchandra	/*configure the 128 * 9 Translation table to send to available buckets*/
1244213475Sjchandra	k = 0;
1245213475Sjchandra	c1 = 3;
1246213475Sjchandra	c2 = 0;
1247213475Sjchandra	for(i = 0; i < 64; i++) {
1248213475Sjchandra		/* Get the next 2 pairs of (class, bucket):
1249213475Sjchandra		   (c1, b1), (c2, b2).
1250213475Sjchandra
1251213475Sjchandra		   c1, c2 limited to {0, 1, 2, 3}
1252213475Sjchandra		       i.e, the 4 classes defined by h/w
1253213475Sjchandra		   b1, b2 limited to { bkts[i], where 0 <= i < j}
1254213475Sjchandra		       i.e, the set of buckets computed in the
1255213475Sjchandra		       above loop.
1256213475Sjchandra		*/
1257213475Sjchandra
1258213475Sjchandra		c1 = (c1 + 1) & 3;
1259213475Sjchandra		c2 = (c1 + 1) & 3;
1260213475Sjchandra		b1 = bkts[k];
1261213475Sjchandra		k = (k + 1) % j;
1262213475Sjchandra		b2 = bkts[k];
1263213475Sjchandra		k = (k + 1) % j;
1264213475Sjchandra		PDEBUG("Translation table[%d] b1=%d b2=%d c1=%d c2=%d\n",
1265213475Sjchandra		    i, b1, b2, c1, c2);
1266213475Sjchandra		val = ((c1 << 23) | (b1 << 17) | (use_bkt << 16) |
1267213475Sjchandra		    (c2 << 7) | (b2 << 1) | (use_bkt << 0));
1268213475Sjchandra		NLGE_WRITE(sc->base, R_TRANSLATETABLE + i, val);
1269213475Sjchandra		c1 = c2;
1270213475Sjchandra	}
1271213475Sjchandra}
1272213475Sjchandra
1273213475Sjchandrastatic void
1274211946Sjchandranlna_config_parser(struct nlna_softc *sc)
1275211946Sjchandra{
1276213475Sjchandra	uint32_t val;
1277213475Sjchandra
1278211946Sjchandra	/*
1279213475Sjchandra	 * Mark it as ETHERNET type.
1280211946Sjchandra	 */
1281211946Sjchandra	NLGE_WRITE(sc->base, R_L2TYPE_0, 0x01);
1282211946Sjchandra
1283215939Sjchandra#ifndef NLGE_HW_CHKSUM
1284213475Sjchandra	if (!flow_classification)
1285213475Sjchandra		return;
1286215939Sjchandra#endif
1287213475Sjchandra
1288213475Sjchandra	/* Use 7bit CRChash for flow classification with 127 as CRC polynomial*/
1289213475Sjchandra	NLGE_WRITE(sc->base, R_PARSERCONFIGREG, ((0x7f << 8) | (1 << 1)));
1290213475Sjchandra
1291211946Sjchandra	/* configure the parser : L2 Type is configured in the bootloader */
1292211946Sjchandra	/* extract IP: src, dest protocol */
1293211946Sjchandra	NLGE_WRITE(sc->base, R_L3CTABLE,
1294211946Sjchandra	    (9 << 20) | (1 << 19) | (1 << 18) | (0x01 << 16) |
1295211946Sjchandra	    (0x0800 << 0));
1296211946Sjchandra	NLGE_WRITE(sc->base, R_L3CTABLE + 1,
1297213475Sjchandra	    (9 << 25) | (1 << 21) | (12 << 14) | (4 << 10) | (16 << 4) | 4);
1298215939Sjchandra#ifdef NLGE_HW_CHKSUM
1299215939Sjchandra	device_printf(sc->nlna_dev, "Enabled h/w support to compute TCP/IP"
1300215939Sjchandra	    " checksum\n");
1301215939Sjchandra#endif
1302213475Sjchandra
1303213475Sjchandra	/* Configure to extract SRC port and Dest port for TCP and UDP pkts */
1304213475Sjchandra	NLGE_WRITE(sc->base, R_L4CTABLE, 6);
1305215939Sjchandra	NLGE_WRITE(sc->base, R_L4CTABLE + 2, 17);
1306213475Sjchandra	val = ((0 << 21) | (2 << 17) | (2 << 11) | (2 << 7));
1307215939Sjchandra	NLGE_WRITE(sc->base, R_L4CTABLE + 1, val);
1308215939Sjchandra	NLGE_WRITE(sc->base, R_L4CTABLE + 3, val);
1309211946Sjchandra}
1310211946Sjchandra
1311211946Sjchandrastatic void
1312211946Sjchandranlna_config_classifier(struct nlna_softc *sc)
1313211946Sjchandra{
1314211946Sjchandra	int i;
1315211946Sjchandra
1316211946Sjchandra	if (sc->mac_type == XLR_XGMII) {	/* TBD: XGMII init sequence */
1317211946Sjchandra		/* xgmac translation table doesn't have sane values on reset */
1318211946Sjchandra		for (i = 0; i < 64; i++)
1319211946Sjchandra			NLGE_WRITE(sc->base, R_TRANSLATETABLE + i, 0x0);
1320211946Sjchandra
1321211946Sjchandra		/*
1322211946Sjchandra		 * use upper 7 bits of the parser extract to index the
1323211946Sjchandra		 * translate table
1324211946Sjchandra		 */
1325211946Sjchandra		NLGE_WRITE(sc->base, R_PARSERCONFIGREG, 0x0);
1326211946Sjchandra	}
1327211946Sjchandra}
1328211946Sjchandra
1329211946Sjchandra/*
1330211946Sjchandra * Complete a bunch of h/w register initializations that are common for all the
1331211946Sjchandra * ports controlled by a NA.
1332211946Sjchandra */
1333211946Sjchandrastatic void
1334211946Sjchandranlna_config_common(struct nlna_softc *sc)
1335211946Sjchandra{
1336211946Sjchandra	struct xlr_gmac_block_t *block_info;
1337211946Sjchandra	struct stn_cc 		*gmac_cc_config;
1338213377Sjchandra	int			i;
1339211946Sjchandra
1340211946Sjchandra	block_info = device_get_ivars(sc->nlna_dev);
1341211946Sjchandra	gmac_cc_config = block_info->credit_config;
1342211946Sjchandra	for (i = 0; i < MAX_NUM_MSGRNG_STN_CC; i++) {
1343211946Sjchandra		NLGE_WRITE(sc->base, R_CC_CPU0_0 + i,
1344211946Sjchandra		    gmac_cc_config->counters[i >> 3][i & 0x07]);
1345211946Sjchandra	}
1346211946Sjchandra
1347211946Sjchandra	NLGE_WRITE(sc->base, R_MSG_TX_THRESHOLD, 3);
1348211946Sjchandra
1349211946Sjchandra	NLGE_WRITE(sc->base, R_DMACR0, 0xffffffff);
1350211946Sjchandra	NLGE_WRITE(sc->base, R_DMACR1, 0xffffffff);
1351211946Sjchandra	NLGE_WRITE(sc->base, R_DMACR2, 0xffffffff);
1352211946Sjchandra	NLGE_WRITE(sc->base, R_DMACR3, 0xffffffff);
1353211946Sjchandra	NLGE_WRITE(sc->base, R_FREEQCARVE, 0);
1354211946Sjchandra
1355211946Sjchandra	nlna_media_specific_config(sc);
1356211946Sjchandra}
1357211946Sjchandra
1358211946Sjchandrastatic void
1359211946Sjchandranlna_media_specific_config(struct nlna_softc *sc)
1360211946Sjchandra{
1361211946Sjchandra	struct bucket_size *bucket_sizes;
1362211946Sjchandra
1363211946Sjchandra	bucket_sizes = xlr_board_info.bucket_sizes;
1364211946Sjchandra	switch (sc->mac_type) {
1365211946Sjchandra	case XLR_RGMII:
1366211946Sjchandra	case XLR_SGMII:
1367211946Sjchandra	case XLR_XAUI:
1368211946Sjchandra		NLGE_WRITE(sc->base, R_GMAC_JFR0_BUCKET_SIZE,
1369211946Sjchandra		    bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_0]);
1370211946Sjchandra		NLGE_WRITE(sc->base, R_GMAC_RFR0_BUCKET_SIZE,
1371211946Sjchandra		    bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_0]);
1372211946Sjchandra		NLGE_WRITE(sc->base, R_GMAC_JFR1_BUCKET_SIZE,
1373211946Sjchandra		    bucket_sizes->bucket[MSGRNG_STNID_GMACJFR_1]);
1374211946Sjchandra		NLGE_WRITE(sc->base, R_GMAC_RFR1_BUCKET_SIZE,
1375211946Sjchandra		    bucket_sizes->bucket[MSGRNG_STNID_GMACRFR_1]);
1376211946Sjchandra
1377211946Sjchandra		if (sc->mac_type == XLR_XAUI) {
1378211946Sjchandra			NLGE_WRITE(sc->base, R_TXDATAFIFO0, (224 << 16));
1379211946Sjchandra		}
1380211946Sjchandra		break;
1381211946Sjchandra
1382211946Sjchandra	case XLR_XGMII:
1383211946Sjchandra		NLGE_WRITE(sc->base, R_XGS_RFR_BUCKET_SIZE,
1384211946Sjchandra		    bucket_sizes->bucket[sc->rfrbucket]);
1385211946Sjchandra
1386211946Sjchandra	default:
1387211946Sjchandra		break;
1388211946Sjchandra	}
1389211946Sjchandra}
1390211946Sjchandra
1391211946Sjchandrastatic void
1392211946Sjchandranlna_reset_ports(struct nlna_softc *sc, struct xlr_gmac_block_t *blk)
1393211946Sjchandra{
1394211946Sjchandra	xlr_reg_t *addr;
1395211946Sjchandra	int i;
1396211946Sjchandra	uint32_t   rx_ctrl;
1397211946Sjchandra
1398211946Sjchandra	/* Refer Section 13.9.3 in the PRM for the reset sequence */
1399211946Sjchandra
1400211946Sjchandra	for (i = 0; i < sc->num_ports; i++) {
1401212896Sjchandra		addr = xlr_io_mmio(blk->gmac_port[i].base_addr);
1402211946Sjchandra
1403211946Sjchandra		/* 1. Reset RxEnable in MAC_CONFIG */
1404211946Sjchandra		switch (sc->mac_type) {
1405211946Sjchandra		case XLR_RGMII:
1406211946Sjchandra		case XLR_SGMII:
1407211946Sjchandra			NLGE_UPDATE(addr, R_MAC_CONFIG_1, 0,
1408211946Sjchandra			    (1 << O_MAC_CONFIG_1__rxen));
1409211946Sjchandra			break;
1410211946Sjchandra		case XLR_XAUI:
1411211946Sjchandra		case XLR_XGMII:
1412211946Sjchandra			NLGE_UPDATE(addr, R_RX_CONTROL, 0,
1413211946Sjchandra			   (1 << O_RX_CONTROL__RxEnable));
1414211946Sjchandra			break;
1415211946Sjchandra		default:
1416211946Sjchandra			printf("Error: Unsupported port_type=%d\n",
1417211946Sjchandra			    sc->mac_type);
1418211946Sjchandra		}
1419211946Sjchandra
1420211946Sjchandra		/* 1.1 Wait for RxControl.RxHalt to be set */
1421211946Sjchandra		do {
1422211946Sjchandra			rx_ctrl = NLGE_READ(addr, R_RX_CONTROL);
1423211946Sjchandra		} while (!(rx_ctrl & 0x2));
1424211946Sjchandra
1425211946Sjchandra		/* 2. Set the soft reset bit in RxControl */
1426211946Sjchandra		NLGE_UPDATE(addr, R_RX_CONTROL, (1 << O_RX_CONTROL__SoftReset),
1427211946Sjchandra		    (1 << O_RX_CONTROL__SoftReset));
1428211946Sjchandra
1429211946Sjchandra		/* 2.1 Wait for RxControl.SoftResetDone to be set */
1430211946Sjchandra		do {
1431211946Sjchandra			rx_ctrl = NLGE_READ(addr, R_RX_CONTROL);
1432211946Sjchandra		} while (!(rx_ctrl & 0x8));
1433211946Sjchandra
1434211946Sjchandra		/* 3. Clear the soft reset bit in RxControl */
1435211946Sjchandra		NLGE_UPDATE(addr, R_RX_CONTROL, 0,
1436211946Sjchandra		    (1 << O_RX_CONTROL__SoftReset));
1437211946Sjchandra
1438211946Sjchandra		/* Turn off tx/rx on the port. */
1439211946Sjchandra		NLGE_UPDATE(addr, R_RX_CONTROL, 0,
1440211946Sjchandra		    (1 << O_RX_CONTROL__RxEnable));
1441211946Sjchandra		NLGE_UPDATE(addr, R_TX_CONTROL, 0,
1442211946Sjchandra		    (1 << O_TX_CONTROL__TxEnable));
1443211946Sjchandra	}
1444211946Sjchandra}
1445211946Sjchandra
1446211946Sjchandrastatic void
1447211946Sjchandranlna_disable_ports(struct nlna_softc *sc)
1448211946Sjchandra{
1449211946Sjchandra	int i;
1450211946Sjchandra
1451211946Sjchandra	for (i = 0; i < sc->num_ports; i++) {
1452213475Sjchandra		if (sc->child_sc[i] != NULL)
1453213475Sjchandra			nlge_port_disable(sc->child_sc[i]);
1454211946Sjchandra	}
1455211946Sjchandra}
1456211946Sjchandra
1457211946Sjchandrastatic void
1458211946Sjchandranlna_enable_ports(struct nlna_softc *sc)
1459211946Sjchandra{
1460211946Sjchandra	device_t		nlge_dev, *devlist;
1461211946Sjchandra	struct nlge_softc 	*port_sc;
1462211946Sjchandra	int 			i, numdevs;
1463211946Sjchandra
1464211946Sjchandra	device_get_children(sc->nlna_dev, &devlist, &numdevs);
1465211946Sjchandra	for (i = 0; i < numdevs; i++) {
1466211946Sjchandra		nlge_dev = devlist[i];
1467211946Sjchandra		if (nlge_dev == NULL)
1468211946Sjchandra			continue;
1469211946Sjchandra		port_sc = device_get_softc(nlge_dev);
1470211946Sjchandra		if (port_sc->nlge_if->if_drv_flags & IFF_DRV_RUNNING)
1471211946Sjchandra			nlge_port_enable(port_sc);
1472211946Sjchandra	}
1473211946Sjchandra	free(devlist, M_TEMP);
1474211946Sjchandra}
1475211946Sjchandra
1476211946Sjchandrastatic void
1477211946Sjchandranlna_get_all_softc(device_t iodi_dev, struct nlna_softc **sc_vec,
1478211946Sjchandra		   uint32_t vec_sz)
1479211946Sjchandra{
1480211946Sjchandra	device_t  na_dev;
1481211946Sjchandra	int       i;
1482211946Sjchandra
1483211946Sjchandra	for (i = 0; i < vec_sz; i++) {
1484211946Sjchandra		sc_vec[i] = NULL;
1485211946Sjchandra		na_dev = device_find_child(iodi_dev, "nlna", i);
1486211946Sjchandra		if (na_dev != NULL)
1487211946Sjchandra			sc_vec[i] = device_get_softc(na_dev);
1488211946Sjchandra	}
1489211946Sjchandra}
1490211946Sjchandra
1491211946Sjchandrastatic void
1492213475Sjchandranlge_port_disable(struct nlge_softc *sc)
1493211946Sjchandra{
1494213475Sjchandra	struct ifnet *ifp;
1495213475Sjchandra	xlr_reg_t *base;
1496211946Sjchandra	uint32_t rd;
1497213475Sjchandra	int id, port_type;
1498211946Sjchandra
1499213475Sjchandra	id = sc->id;
1500213475Sjchandra	port_type = sc->port_type;
1501213475Sjchandra	base = sc->base;
1502213475Sjchandra	ifp = sc->nlge_if;
1503213475Sjchandra
1504211946Sjchandra	NLGE_UPDATE(base, R_RX_CONTROL, 0x0, 1 << O_RX_CONTROL__RxEnable);
1505211946Sjchandra	do {
1506211946Sjchandra		rd = NLGE_READ(base, R_RX_CONTROL);
1507211946Sjchandra	} while (!(rd & (1 << O_RX_CONTROL__RxHalt)));
1508211946Sjchandra
1509211946Sjchandra	NLGE_UPDATE(base, R_TX_CONTROL, 0, 1 << O_TX_CONTROL__TxEnable);
1510211946Sjchandra	do {
1511211946Sjchandra		rd = NLGE_READ(base, R_TX_CONTROL);
1512211946Sjchandra	} while (!(rd & (1 << O_TX_CONTROL__TxIdle)));
1513211946Sjchandra
1514211946Sjchandra	switch (port_type) {
1515211946Sjchandra	case XLR_RGMII:
1516211946Sjchandra	case XLR_SGMII:
1517211946Sjchandra		NLGE_UPDATE(base, R_MAC_CONFIG_1, 0,
1518211946Sjchandra		   ((1 << O_MAC_CONFIG_1__rxen) |
1519211946Sjchandra		   (1 << O_MAC_CONFIG_1__txen)));
1520211946Sjchandra		break;
1521211946Sjchandra	case XLR_XGMII:
1522211946Sjchandra	case XLR_XAUI:
1523211946Sjchandra		NLGE_UPDATE(base, R_XGMAC_CONFIG_1, 0,
1524211946Sjchandra		   ((1 << O_XGMAC_CONFIG_1__hsttfen) |
1525211946Sjchandra		   (1 << O_XGMAC_CONFIG_1__hstrfen)));
1526211946Sjchandra		break;
1527211946Sjchandra	default:
1528211946Sjchandra		panic("Unknown MAC type on port %d\n", id);
1529211946Sjchandra	}
1530213475Sjchandra
1531213475Sjchandra	if (ifp) {
1532213475Sjchandra		ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
1533213475Sjchandra	}
1534211946Sjchandra}
1535211946Sjchandra
1536211946Sjchandrastatic void
1537211946Sjchandranlge_port_enable(struct nlge_softc *sc)
1538211946Sjchandra{
1539211946Sjchandra	struct xlr_gmac_port  *self;
1540211946Sjchandra	xlr_reg_t *base;
1541211946Sjchandra
1542211946Sjchandra	base = sc->base;
1543211946Sjchandra	self = device_get_ivars(sc->nlge_dev);
1544211946Sjchandra	if (xlr_board_info.is_xls && sc->port_type == XLR_RGMII)
1545211946Sjchandra		NLGE_UPDATE(base, R_RX_CONTROL, (1 << O_RX_CONTROL__RGMII),
1546211946Sjchandra	    	    (1 << O_RX_CONTROL__RGMII));
1547211946Sjchandra
1548211946Sjchandra	NLGE_UPDATE(base, R_RX_CONTROL, (1 << O_RX_CONTROL__RxEnable),
1549211946Sjchandra	    (1 << O_RX_CONTROL__RxEnable));
1550211946Sjchandra	NLGE_UPDATE(base, R_TX_CONTROL,
1551211946Sjchandra	    (1 << O_TX_CONTROL__TxEnable | RGE_TX_THRESHOLD_BYTES),
1552211946Sjchandra	    (1 << O_TX_CONTROL__TxEnable | 0x3fff));
1553211946Sjchandra	switch (sc->port_type) {
1554211946Sjchandra	case XLR_RGMII:
1555211946Sjchandra	case XLR_SGMII:
1556211946Sjchandra		NLGE_UPDATE(base, R_MAC_CONFIG_1,
1557211946Sjchandra		    ((1 << O_MAC_CONFIG_1__rxen) | (1 << O_MAC_CONFIG_1__txen)),
1558211946Sjchandra		    ((1 << O_MAC_CONFIG_1__rxen) | (1 << O_MAC_CONFIG_1__txen)));
1559211946Sjchandra		break;
1560211946Sjchandra	case XLR_XGMII:
1561211946Sjchandra	case XLR_XAUI:
1562211946Sjchandra		NLGE_UPDATE(base, R_XGMAC_CONFIG_1,
1563211946Sjchandra		    ((1 << O_XGMAC_CONFIG_1__hsttfen) | (1 << O_XGMAC_CONFIG_1__hstrfen)),
1564211946Sjchandra		    ((1 << O_XGMAC_CONFIG_1__hsttfen) | (1 << O_XGMAC_CONFIG_1__hstrfen)));
1565211946Sjchandra		break;
1566211946Sjchandra	default:
1567211946Sjchandra		panic("Unknown MAC type on port %d\n", sc->id);
1568211946Sjchandra	}
1569211946Sjchandra}
1570211946Sjchandra
1571211946Sjchandrastatic void
1572213475Sjchandranlge_mac_set_rx_mode(struct nlge_softc *sc)
1573213475Sjchandra{
1574213475Sjchandra	uint32_t regval;
1575213475Sjchandra
1576213475Sjchandra	regval = NLGE_READ(sc->base, R_MAC_FILTER_CONFIG);
1577213475Sjchandra
1578213475Sjchandra	if (sc->if_flags & IFF_PROMISC) {
1579213475Sjchandra		regval |= (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) |
1580213475Sjchandra		    (1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) |
1581213475Sjchandra		    (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) |
1582213475Sjchandra		    (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN);
1583213475Sjchandra	} else {
1584213475Sjchandra		regval &= ~((1 << O_MAC_FILTER_CONFIG__PAUSE_FRAME_EN) |
1585213475Sjchandra		    (1 << O_MAC_FILTER_CONFIG__ALL_UCAST_EN));
1586213475Sjchandra	}
1587213475Sjchandra
1588213475Sjchandra	NLGE_WRITE(sc->base, R_MAC_FILTER_CONFIG, regval);
1589213475Sjchandra}
1590213475Sjchandra
1591213475Sjchandrastatic void
1592211946Sjchandranlge_sgmii_init(struct nlge_softc *sc)
1593211946Sjchandra{
1594211946Sjchandra	xlr_reg_t *mmio_gpio;
1595211946Sjchandra	int phy;
1596211946Sjchandra
1597211946Sjchandra	if (sc->port_type != XLR_SGMII)
1598211946Sjchandra		return;
1599211946Sjchandra
1600211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 0, 0x6DB0);
1601211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 1, 0xFFFF);
1602211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 2, 0xB6D0);
1603211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 3, 0x00FF);
1604211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 4, 0x0000);
1605211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 5, 0x0000);
1606211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 6, 0x0005);
1607211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 7, 0x0001);
1608211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 8, 0x0000);
1609211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26, 9, 0x0000);
1610211946Sjchandra	nlge_mii_write_internal(sc->serdes_addr, 26,10, 0x0000);
1611211946Sjchandra
1612211946Sjchandra	/* program  GPIO values for serdes init parameters */
1613212896Sjchandra	DELAY(100);
1614212896Sjchandra	mmio_gpio = xlr_io_mmio(XLR_IO_GPIO_OFFSET);
1615212896Sjchandra	xlr_write_reg(mmio_gpio, 0x20, 0x7e6802);
1616212896Sjchandra	xlr_write_reg(mmio_gpio, 0x10, 0x7104);
1617212896Sjchandra	DELAY(100);
1618211946Sjchandra
1619212896Sjchandra	/*
1620212896Sjchandra	 * This kludge is needed to setup serdes (?) clock correctly on some
1621212896Sjchandra	 * XLS boards
1622212896Sjchandra	 */
1623212896Sjchandra	if ((xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XI ||
1624212896Sjchandra	    xlr_boot1_info.board_major_version == RMI_XLR_BOARD_ARIZONA_XII) &&
1625212896Sjchandra	    xlr_boot1_info.board_minor_version == 4) {
1626212896Sjchandra		/* use 125 Mhz instead of 156.25Mhz ref clock */
1627212896Sjchandra		DELAY(100);
1628212896Sjchandra		xlr_write_reg(mmio_gpio, 0x10, 0x7103);
1629212896Sjchandra		xlr_write_reg(mmio_gpio, 0x21, 0x7103);
1630212896Sjchandra		DELAY(100);
1631212896Sjchandra	}
1632212896Sjchandra
1633211946Sjchandra	/* enable autoneg - more magic */
1634211946Sjchandra	phy = sc->phy_addr % 4 + 27;
1635211946Sjchandra	nlge_mii_write_internal(sc->pcs_addr, phy, 0, 0x1000);
1636211946Sjchandra	DELAY(100000);
1637211946Sjchandra	nlge_mii_write_internal(sc->pcs_addr, phy, 0, 0x0200);
1638211946Sjchandra	DELAY(100000);
1639211946Sjchandra}
1640211946Sjchandra
1641211946Sjchandrastatic void
1642211946Sjchandranlge_intr(void *arg)
1643211946Sjchandra{
1644211946Sjchandra	struct nlge_port_set    *pset;
1645211946Sjchandra	struct nlge_softc 	*sc;
1646211946Sjchandra	struct nlge_softc 	*port_sc;
1647211946Sjchandra	xlr_reg_t 		*base;
1648211946Sjchandra	uint32_t		intreg;
1649211946Sjchandra	uint32_t		intr_status;
1650211946Sjchandra	int 			i;
1651211946Sjchandra
1652211946Sjchandra	sc = arg;
1653211946Sjchandra	if (sc == NULL) {
1654211946Sjchandra		printf("warning: No port registered for interrupt\n");
1655211946Sjchandra		return;
1656211946Sjchandra	}
1657211946Sjchandra	base = sc->base;
1658211946Sjchandra
1659211946Sjchandra	intreg = NLGE_READ(base, R_INTREG);
1660211946Sjchandra	if (intreg & (1 << O_INTREG__MDInt)) {
1661211946Sjchandra		pset = sc->mdio_pset;
1662211946Sjchandra		if (pset == NULL) {
1663211946Sjchandra			printf("warning: No ports for MDIO interrupt\n");
1664211946Sjchandra			return;
1665211946Sjchandra		}
1666211946Sjchandra		for (i = 0; i < pset->vec_sz; i++) {
1667211946Sjchandra			port_sc = pset->port_vec[i];
1668211946Sjchandra
1669211946Sjchandra			if (port_sc == NULL)
1670211946Sjchandra				continue;
1671211946Sjchandra
1672211946Sjchandra			/* Ack phy interrupt - clear on read*/
1673211946Sjchandra			intr_status = nlge_mii_read_internal(port_sc->mii_base,
1674211946Sjchandra			    port_sc->phy_addr, 26);
1675211946Sjchandra			PDEBUG("Phy_%d: int_status=0x%08x\n", port_sc->phy_addr,
1676211946Sjchandra			    intr_status);
1677211946Sjchandra
1678211946Sjchandra			if (!(intr_status & 0x8000)) {
1679211946Sjchandra				/* no interrupt for this port */
1680211946Sjchandra				continue;
1681211946Sjchandra			}
1682211946Sjchandra
1683211946Sjchandra			if (intr_status & 0x2410) {
1684211946Sjchandra				/* update link status for port */
1685213475Sjchandra				nlge_gmac_config_speed(port_sc, 1);
1686211946Sjchandra			} else {
1687211946Sjchandra				printf("%s: Unsupported phy interrupt"
1688211946Sjchandra				    " (0x%08x)\n",
1689211946Sjchandra				    device_get_nameunit(port_sc->nlge_dev),
1690211946Sjchandra				    intr_status);
1691211946Sjchandra			}
1692211946Sjchandra		}
1693211946Sjchandra	}
1694211946Sjchandra
1695211946Sjchandra	/* Clear the NA interrupt */
1696211946Sjchandra	xlr_write_reg(base, R_INTREG, 0xffffffff);
1697211946Sjchandra
1698211946Sjchandra	return;
1699211946Sjchandra}
1700211946Sjchandra
1701211946Sjchandrastatic int
1702211946Sjchandranlge_irq_init(struct nlge_softc *sc)
1703211946Sjchandra{
1704211946Sjchandra	struct resource		irq_res;
1705211946Sjchandra	struct nlna_softc  	*na_sc;
1706211946Sjchandra	struct xlr_gmac_block_t *block_info;
1707211946Sjchandra	device_t		na_dev;
1708211946Sjchandra	int			ret;
1709211946Sjchandra	int			irq_num;
1710211946Sjchandra
1711211946Sjchandra	na_dev = device_get_parent(sc->nlge_dev);
1712211946Sjchandra	block_info = device_get_ivars(na_dev);
1713211946Sjchandra
1714211946Sjchandra	irq_num = block_info->baseirq + sc->instance;
1715211946Sjchandra	irq_res.__r_i = (struct resource_i *)(intptr_t) (irq_num);
1716217072Sjhb	ret = bus_setup_intr(sc->nlge_dev, &irq_res,
1717217072Sjhb	    INTR_TYPE_NET | INTR_MPSAFE, NULL, nlge_intr, sc, NULL);
1718211946Sjchandra	if (ret) {
1719211946Sjchandra		nlge_detach(sc->nlge_dev);
1720211946Sjchandra		device_printf(sc->nlge_dev, "couldn't set up irq: error=%d\n",
1721211946Sjchandra		    ret);
1722211946Sjchandra		return (ENXIO);
1723211946Sjchandra	}
1724211946Sjchandra	PDEBUG("Setup intr for dev=%s, irq=%d\n",
1725211946Sjchandra	    device_get_nameunit(sc->nlge_dev), irq_num);
1726211946Sjchandra
1727211946Sjchandra	if (sc->instance == 0) {
1728211946Sjchandra		na_sc = device_get_softc(na_dev);
1729211946Sjchandra		sc->mdio_pset = &na_sc->mdio_set;
1730211946Sjchandra	}
1731211946Sjchandra	return (0);
1732211946Sjchandra}
1733211946Sjchandra
1734211946Sjchandrastatic void
1735211946Sjchandranlge_irq_fini(struct nlge_softc *sc)
1736211946Sjchandra{
1737211946Sjchandra}
1738211946Sjchandra
1739211946Sjchandrastatic void
1740211946Sjchandranlge_hw_init(struct nlge_softc *sc)
1741211946Sjchandra{
1742211946Sjchandra	struct xlr_gmac_port  *port_info;
1743211946Sjchandra	xlr_reg_t *base;
1744211946Sjchandra
1745211946Sjchandra	base = sc->base;
1746211946Sjchandra	port_info = device_get_ivars(sc->nlge_dev);
1747211946Sjchandra	sc->tx_bucket_id = port_info->tx_bucket_id;
1748211946Sjchandra
1749211946Sjchandra	/* each packet buffer is 1536 bytes */
1750211946Sjchandra	NLGE_WRITE(base, R_DESC_PACK_CTRL,
1751215939Sjchandra	    (1 << O_DESC_PACK_CTRL__MaxEntry) |
1752215939Sjchandra#ifdef NLGE_HW_CHKSUM
1753215939Sjchandra	    (1 << O_DESC_PACK_CTRL__PrePadEnable) |
1754215939Sjchandra#endif
1755215939Sjchandra	    (MAX_FRAME_SIZE << O_DESC_PACK_CTRL__RegularSize));
1756211946Sjchandra	NLGE_WRITE(base, R_STATCTRL, ((1 << O_STATCTRL__Sten) |
1757211946Sjchandra	    (1 << O_STATCTRL__ClrCnt)));
1758211946Sjchandra	NLGE_WRITE(base, R_L2ALLOCCTRL, 0xffffffff);
1759211946Sjchandra	NLGE_WRITE(base, R_INTMASK, 0);
1760211946Sjchandra	nlge_set_mac_addr(sc);
1761211946Sjchandra	nlge_media_specific_init(sc);
1762211946Sjchandra}
1763211946Sjchandra
1764211946Sjchandrastatic void
1765211946Sjchandranlge_sc_init(struct nlge_softc *sc, device_t dev,
1766211946Sjchandra    struct xlr_gmac_port *port_info)
1767211946Sjchandra{
1768211946Sjchandra	memset(sc, 0, sizeof(*sc));
1769211946Sjchandra	sc->nlge_dev = dev;
1770211946Sjchandra	sc->id = device_get_unit(dev);
1771211946Sjchandra	nlge_set_port_attribs(sc, port_info);
1772211946Sjchandra}
1773211946Sjchandra
1774211946Sjchandrastatic void
1775211946Sjchandranlge_media_specific_init(struct nlge_softc *sc)
1776211946Sjchandra{
1777211946Sjchandra	struct mii_data *media;
1778211946Sjchandra	struct bucket_size *bucket_sizes;
1779211946Sjchandra
1780211946Sjchandra	bucket_sizes = xlr_board_info.bucket_sizes;
1781211946Sjchandra	switch (sc->port_type) {
1782211946Sjchandra	case XLR_RGMII:
1783211946Sjchandra	case XLR_SGMII:
1784211946Sjchandra	case XLR_XAUI:
1785211946Sjchandra		NLGE_UPDATE(sc->base, R_DESC_PACK_CTRL,
1786211946Sjchandra		    (BYTE_OFFSET << O_DESC_PACK_CTRL__ByteOffset),
1787211946Sjchandra		    (W_DESC_PACK_CTRL__ByteOffset <<
1788211946Sjchandra		        O_DESC_PACK_CTRL__ByteOffset));
1789211946Sjchandra		NLGE_WRITE(sc->base, R_GMAC_TX0_BUCKET_SIZE + sc->instance,
1790211946Sjchandra		    bucket_sizes->bucket[sc->tx_bucket_id]);
1791211946Sjchandra		if (sc->port_type != XLR_XAUI) {
1792211946Sjchandra			nlge_gmac_config_speed(sc, 1);
1793211946Sjchandra			if (sc->mii_bus) {
1794211946Sjchandra				media = (struct mii_data *)device_get_softc(
1795211946Sjchandra				    sc->mii_bus);
1796211946Sjchandra			}
1797211946Sjchandra		}
1798211946Sjchandra		break;
1799211946Sjchandra
1800211946Sjchandra	case XLR_XGMII:
1801211946Sjchandra		NLGE_WRITE(sc->base, R_BYTEOFFSET0, 0x2);
1802211946Sjchandra		NLGE_WRITE(sc->base, R_XGMACPADCALIBRATION, 0x30);
1803211946Sjchandra		NLGE_WRITE(sc->base, R_XGS_TX0_BUCKET_SIZE,
1804211946Sjchandra		    bucket_sizes->bucket[sc->tx_bucket_id]);
1805211946Sjchandra		break;
1806211946Sjchandra	default:
1807211946Sjchandra		break;
1808211946Sjchandra	}
1809211946Sjchandra}
1810211946Sjchandra
1811211946Sjchandra/*
1812211946Sjchandra * Read the MAC address from the XLR boot registers. All port addresses
1813211946Sjchandra * are identical except for the lowest octet.
1814211946Sjchandra */
1815211946Sjchandrastatic void
1816211946Sjchandranlge_read_mac_addr(struct nlge_softc *sc)
1817211946Sjchandra{
1818211946Sjchandra	int i, j;
1819211946Sjchandra
1820211946Sjchandra	for (i = 0, j = 40; i < ETHER_ADDR_LEN && j >= 0; i++, j-= 8)
1821211946Sjchandra		sc->dev_addr[i] = (xlr_boot1_info.mac_addr >> j) & 0xff;
1822211946Sjchandra
1823211946Sjchandra	sc->dev_addr[i - 1] +=  sc->id;	/* last octet is port-specific */
1824211946Sjchandra}
1825211946Sjchandra
1826211946Sjchandra/*
1827211946Sjchandra * Write the MAC address to the XLR MAC port. Also, set the address
1828211946Sjchandra * masks and MAC filter configuration.
1829211946Sjchandra */
1830211946Sjchandrastatic void
1831211946Sjchandranlge_set_mac_addr(struct nlge_softc *sc)
1832211946Sjchandra{
1833211946Sjchandra	NLGE_WRITE(sc->base, R_MAC_ADDR0,
1834211946Sjchandra		  ((sc->dev_addr[5] << 24) | (sc->dev_addr[4] << 16) |
1835211946Sjchandra		   (sc->dev_addr[3] << 8) | (sc->dev_addr[2])));
1836211946Sjchandra	NLGE_WRITE(sc->base, R_MAC_ADDR0 + 1,
1837211946Sjchandra		  ((sc->dev_addr[1] << 24) | (sc-> dev_addr[0] << 16)));
1838211946Sjchandra
1839211946Sjchandra	NLGE_WRITE(sc->base, R_MAC_ADDR_MASK2, 0xffffffff);
1840211946Sjchandra	NLGE_WRITE(sc->base, R_MAC_ADDR_MASK2 + 1, 0xffffffff);
1841211946Sjchandra	NLGE_WRITE(sc->base, R_MAC_ADDR_MASK3, 0xffffffff);
1842211946Sjchandra	NLGE_WRITE(sc->base, R_MAC_ADDR_MASK3 + 1, 0xffffffff);
1843211946Sjchandra
1844211946Sjchandra	NLGE_WRITE(sc->base, R_MAC_FILTER_CONFIG,
1845211946Sjchandra		  (1 << O_MAC_FILTER_CONFIG__BROADCAST_EN) |
1846211946Sjchandra		  (1 << O_MAC_FILTER_CONFIG__ALL_MCAST_EN) |
1847211946Sjchandra		  (1 << O_MAC_FILTER_CONFIG__MAC_ADDR0_VALID));
1848211946Sjchandra
1849211946Sjchandra	if (sc->port_type == XLR_RGMII || sc->port_type == XLR_SGMII) {
1850211946Sjchandra		NLGE_UPDATE(sc->base, R_IPG_IFG, MAC_B2B_IPG, 0x7f);
1851211946Sjchandra	}
1852211946Sjchandra}
1853211946Sjchandra
1854211946Sjchandrastatic int
1855211946Sjchandranlge_if_init(struct nlge_softc *sc)
1856211946Sjchandra{
1857211946Sjchandra	struct ifnet 	*ifp;
1858211946Sjchandra	device_t	dev;
1859211946Sjchandra	int error;
1860211946Sjchandra
1861211946Sjchandra	error = 0;
1862211946Sjchandra	dev = sc->nlge_dev;
1863211946Sjchandra	NLGE_LOCK_INIT(sc, device_get_nameunit(dev));
1864211946Sjchandra
1865211946Sjchandra	ifp = sc->nlge_if = if_alloc(IFT_ETHER);
1866211946Sjchandra	if (ifp == NULL) {
1867211946Sjchandra		device_printf(dev, "can not if_alloc()\n");
1868211946Sjchandra		error = ENOSPC;
1869211946Sjchandra		goto fail;
1870211946Sjchandra	}
1871211946Sjchandra	ifp->if_softc = sc;
1872211946Sjchandra	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
1873211946Sjchandra	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
1874213475Sjchandra	ifp->if_capabilities = 0;
1875211946Sjchandra	ifp->if_capenable = ifp->if_capabilities;
1876211946Sjchandra	ifp->if_ioctl = nlge_ioctl;
1877211946Sjchandra	ifp->if_init = nlge_init;
1878211946Sjchandra	ifp->if_hwassist = 0;
1879211946Sjchandra	ifp->if_snd.ifq_drv_maxlen = RGE_TX_Q_SIZE;
1880211946Sjchandra	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
1881211946Sjchandra	IFQ_SET_READY(&ifp->if_snd);
1882211946Sjchandra
1883211946Sjchandra	ifmedia_init(&sc->nlge_mii.mii_media, 0, nlge_mediachange,
1884211946Sjchandra	    nlge_mediastatus);
1885211946Sjchandra	ifmedia_add(&sc->nlge_mii.mii_media, IFM_ETHER | IFM_AUTO, 0, NULL);
1886211946Sjchandra	ifmedia_set(&sc->nlge_mii.mii_media, IFM_ETHER | IFM_AUTO);
1887211946Sjchandra	sc->nlge_mii.mii_media.ifm_media = sc->nlge_mii.mii_media.ifm_cur->ifm_media;
1888211946Sjchandra	nlge_read_mac_addr(sc);
1889211946Sjchandra
1890211946Sjchandra	ether_ifattach(ifp, sc->dev_addr);
1891211946Sjchandra
1892215939Sjchandra	/* override if_transmit : per ifnet(9), do it after if_attach */
1893215939Sjchandra	ifp->if_transmit = nlge_tx;
1894215939Sjchandra
1895211946Sjchandrafail:
1896211946Sjchandra	return (error);
1897211946Sjchandra}
1898211946Sjchandra
1899211946Sjchandrastatic void
1900211946Sjchandranlge_mii_init(device_t dev, struct nlge_softc *sc)
1901211946Sjchandra{
1902211946Sjchandra	int error;
1903211946Sjchandra
1904211946Sjchandra	if (sc->port_type != XLR_XAUI && sc->port_type != XLR_XGMII) {
1905211946Sjchandra		NLGE_WRITE(sc->mii_base, R_MII_MGMT_CONFIG, 0x07);
1906211946Sjchandra	}
1907213893Smarius	error = mii_attach(dev, &sc->mii_bus, sc->nlge_if, nlge_mediachange,
1908213893Smarius	    nlge_mediastatus, BMSR_DEFCAPMASK, sc->phy_addr, MII_OFFSET_ANY,
1909213893Smarius	    0);
1910211946Sjchandra	if (error) {
1911213893Smarius		device_printf(dev, "attaching PHYs failed\n");
1912211946Sjchandra		sc->mii_bus = NULL;
1913211946Sjchandra	}
1914211946Sjchandra	if (sc->mii_bus != NULL) {
1915211946Sjchandra		/*
1916211946Sjchandra		 * Enable all MDIO interrupts in the phy. RX_ER bit seems to get
1917211946Sjchandra		 * set about every 1 sec in GigE mode, ignore it for now...
1918211946Sjchandra		 */
1919211946Sjchandra		nlge_mii_write_internal(sc->mii_base, sc->phy_addr, 25,
1920211946Sjchandra		    0xfffffffe);
1921211946Sjchandra	}
1922211946Sjchandra}
1923211946Sjchandra
1924211946Sjchandra/*
1925211946Sjchandra *  Read a PHY register.
1926211946Sjchandra *
1927211946Sjchandra *  Input parameters:
1928211946Sjchandra *  	   mii_base - Base address of MII
1929211946Sjchandra *  	   phyaddr - PHY's address
1930211946Sjchandra *  	   regidx = index of register to read
1931211946Sjchandra *
1932211946Sjchandra *  Return value:
1933211946Sjchandra *  	   value read, or 0 if an error occurred.
1934211946Sjchandra */
1935211946Sjchandra
1936211946Sjchandrastatic int
1937211946Sjchandranlge_mii_read_internal(xlr_reg_t *mii_base, int phyaddr, int regidx)
1938211946Sjchandra{
1939211946Sjchandra	int i, val;
1940211946Sjchandra
1941211946Sjchandra	/* setup the phy reg to be used */
1942211946Sjchandra	NLGE_WRITE(mii_base, R_MII_MGMT_ADDRESS,
1943211946Sjchandra	    (phyaddr << 8) | (regidx << 0));
1944211946Sjchandra	/* Issue the read command */
1945211946Sjchandra	NLGE_WRITE(mii_base, R_MII_MGMT_COMMAND,
1946211946Sjchandra	    (1 << O_MII_MGMT_COMMAND__rstat));
1947211946Sjchandra
1948211946Sjchandra	/* poll for the read cycle to complete */
1949211946Sjchandra	for (i = 0; i < PHY_STATUS_RETRIES; i++) {
1950211946Sjchandra		if (NLGE_READ(mii_base, R_MII_MGMT_INDICATORS) == 0)
1951211946Sjchandra			break;
1952211946Sjchandra	}
1953211946Sjchandra
1954211946Sjchandra	/* clear the read cycle */
1955211946Sjchandra	NLGE_WRITE(mii_base, R_MII_MGMT_COMMAND, 0);
1956211946Sjchandra
1957211946Sjchandra	if (i == PHY_STATUS_RETRIES) {
1958211946Sjchandra		return (0xffffffff);
1959211946Sjchandra	}
1960211946Sjchandra
1961211946Sjchandra	val = NLGE_READ(mii_base, R_MII_MGMT_STATUS);
1962211946Sjchandra
1963211946Sjchandra	return (val);
1964211946Sjchandra}
1965211946Sjchandra
1966211946Sjchandra/*
1967211946Sjchandra *  Write a value to a PHY register.
1968211946Sjchandra *
1969211946Sjchandra *  Input parameters:
1970211946Sjchandra *  	   mii_base - Base address of MII
1971211946Sjchandra *  	   phyaddr - PHY to use
1972211946Sjchandra *  	   regidx - register within the PHY
1973211946Sjchandra *  	   regval - data to write to register
1974211946Sjchandra *
1975211946Sjchandra *  Return value:
1976211946Sjchandra *  	   nothing
1977211946Sjchandra */
1978211946Sjchandrastatic void
1979211946Sjchandranlge_mii_write_internal(xlr_reg_t *mii_base, int phyaddr, int regidx,
1980211946Sjchandra    int regval)
1981211946Sjchandra{
1982211946Sjchandra	int i;
1983211946Sjchandra
1984211946Sjchandra	NLGE_WRITE(mii_base, R_MII_MGMT_ADDRESS,
1985211946Sjchandra	   (phyaddr << 8) | (regidx << 0));
1986211946Sjchandra
1987211946Sjchandra	/* Write the data which starts the write cycle */
1988211946Sjchandra	NLGE_WRITE(mii_base, R_MII_MGMT_WRITE_DATA, regval);
1989211946Sjchandra
1990211946Sjchandra	/* poll for the write cycle to complete */
1991211946Sjchandra	for (i = 0; i < PHY_STATUS_RETRIES; i++) {
1992211946Sjchandra		if (NLGE_READ(mii_base, R_MII_MGMT_INDICATORS) == 0)
1993211946Sjchandra			break;
1994211946Sjchandra	}
1995211946Sjchandra}
1996211946Sjchandra
1997211946Sjchandra/*
1998211946Sjchandra * Function to optimize the use of p2d descriptors for the given PDU.
1999211946Sjchandra * As it is on the fast-path (called during packet transmission), it
2000211946Sjchandra * described in more detail than the initialization functions.
2001211946Sjchandra *
2002211946Sjchandra * Input: mbuf chain (MC), pointer to fmn message
2003211946Sjchandra * Input constraints: None
2004211946Sjchandra * Output: FMN message to transmit the data in MC
2005211946Sjchandra * Return values: 0 - success
2006211946Sjchandra *                1 - MC cannot be handled (see Limitations below)
2007211946Sjchandra *                2 - MC cannot be handled presently (maybe worth re-trying)
2008211946Sjchandra * Other output: Number of entries filled in the FMN message
2009211946Sjchandra *
2010211946Sjchandra * Output structure/constraints:
2011211946Sjchandra *     1. Max 3 p2d's + 1 zero-len (ZL) p2d with virtual address of MC.
2012211946Sjchandra *     2. 3 p2d's + 1 p2p with max 14 p2d's (ZL p2d not required in this case).
2013211946Sjchandra *     3. Each p2d points to physically contiguous chunk of data (subject to
2014211946Sjchandra *        entire MC requiring max 17 p2d's).
2015211946Sjchandra * Limitations:
2016211946Sjchandra *     1. MC's that require more than 17 p2d's are not handled.
2017211946Sjchandra * Benefits: MC's that require <= 3 p2d's avoid the overhead of allocating
2018211946Sjchandra *           the p2p structure. Small packets (which typically give low
2019211946Sjchandra *           performance) are expected to have a small MC that takes
2020211946Sjchandra *           advantage of this.
2021211946Sjchandra */
2022211946Sjchandrastatic int
2023211946Sjchandraprepare_fmn_message(struct nlge_softc *sc, struct msgrng_msg *fmn_msg,
2024211946Sjchandra    uint32_t *n_entries, struct mbuf *mbuf_chain, uint64_t fb_stn_id,
2025211946Sjchandra    struct nlge_tx_desc **tx_desc)
2026211946Sjchandra{
2027211946Sjchandra	struct mbuf     *m;
2028211946Sjchandra	struct nlge_tx_desc *p2p;
2029211946Sjchandra	uint64_t        *cur_p2d;
2030212896Sjchandra	uint64_t        fbpaddr;
2031211946Sjchandra	vm_offset_t	buf;
2032211946Sjchandra	vm_paddr_t      paddr;
2033212896Sjchandra	int             msg_sz, p2p_sz, len, frag_sz;
2034211946Sjchandra	/* Num entries per FMN msg is 4 for XLR/XLS */
2035211946Sjchandra	const int       FMN_SZ = sizeof(*fmn_msg) / sizeof(uint64_t);
2036211946Sjchandra
2037212896Sjchandra	msg_sz = p2p_sz = 0;
2038211946Sjchandra	p2p = NULL;
2039211946Sjchandra	cur_p2d = &fmn_msg->msg0;
2040211946Sjchandra
2041211946Sjchandra	for (m = mbuf_chain; m != NULL; m = m->m_next) {
2042211946Sjchandra		buf = (vm_offset_t) m->m_data;
2043211946Sjchandra		len = m->m_len;
2044211946Sjchandra
2045211946Sjchandra		while (len) {
2046211946Sjchandra			if (msg_sz == (FMN_SZ - 1)) {
2047212324Sjchandra				p2p = uma_zalloc(nl_tx_desc_zone, M_NOWAIT);
2048212324Sjchandra				if (p2p == NULL) {
2049212957Sjchandra					return (2);
2050212324Sjchandra				}
2051211946Sjchandra				/*
2052212758Sjchandra				 * Save the virtual address in the descriptor,
2053212758Sjchandra				 * it makes freeing easy.
2054211946Sjchandra				 */
2055211946Sjchandra				p2p->frag[XLR_MAX_TX_FRAGS] =
2056212758Sjchandra				    (uint64_t)(vm_offset_t)p2p;
2057211946Sjchandra				cur_p2d = &p2p->frag[0];
2058212324Sjchandra			} else if (msg_sz == (FMN_SZ - 2 + XLR_MAX_TX_FRAGS)) {
2059211946Sjchandra				uma_zfree(nl_tx_desc_zone, p2p);
2060212896Sjchandra				return (1);
2061211946Sjchandra			}
2062211946Sjchandra			paddr = vtophys(buf);
2063211994Sjchandra			frag_sz = PAGE_SIZE - (buf & PAGE_MASK);
2064211946Sjchandra			if (len < frag_sz)
2065211946Sjchandra				frag_sz = len;
2066211946Sjchandra			*cur_p2d++ = (127ULL << 54) | ((uint64_t)frag_sz << 40)
2067211946Sjchandra			    | paddr;
2068211946Sjchandra			msg_sz++;
2069212896Sjchandra			if (p2p != NULL)
2070211946Sjchandra				p2p_sz++;
2071211946Sjchandra			len -= frag_sz;
2072211946Sjchandra			buf += frag_sz;
2073211946Sjchandra		}
2074211946Sjchandra	}
2075211946Sjchandra
2076212324Sjchandra	if (msg_sz ==  0) {
2077211946Sjchandra		printf("Zero-length mbuf chain ??\n");
2078211946Sjchandra		*n_entries = msg_sz ;
2079212896Sjchandra		return (0);
2080211946Sjchandra	}
2081211946Sjchandra
2082212896Sjchandra	/* set eop in most-recent p2d */
2083212896Sjchandra	cur_p2d[-1] |= (1ULL << 63);
2084212896Sjchandra
2085212957Sjchandra#ifdef __mips_n64
2086212896Sjchandra	/*
2087212896Sjchandra	 * On n64, we cannot store our mbuf pointer(64 bit) in the freeback
2088212896Sjchandra	 * message (40bit available), so we put the mbuf in m_nextpkt and
2089212896Sjchandra	 * use the physical addr of that in freeback message.
2090212896Sjchandra	 */
2091212896Sjchandra	mbuf_chain->m_nextpkt = mbuf_chain;
2092212896Sjchandra	fbpaddr = vtophys(&mbuf_chain->m_nextpkt);
2093212896Sjchandra#else
2094212896Sjchandra	/* Careful, don't sign extend when going to 64bit */
2095212896Sjchandra	fbpaddr = (uint64_t)(uintptr_t)mbuf_chain;
2096212896Sjchandra#endif
2097212896Sjchandra	*cur_p2d = (1ULL << 63) | ((uint64_t)fb_stn_id << 54) | fbpaddr;
2098211946Sjchandra	*tx_desc = p2p;
2099211946Sjchandra
2100212896Sjchandra	if (p2p != NULL) {
2101211946Sjchandra		paddr = vtophys(p2p);
2102212324Sjchandra		p2p_sz++;
2103212324Sjchandra		fmn_msg->msg3 = (1ULL << 62) | ((uint64_t)fb_stn_id << 54) |
2104211946Sjchandra		    ((uint64_t)(p2p_sz * 8) << 40) | paddr;
2105211946Sjchandra		*n_entries = FMN_SZ;
2106211946Sjchandra	} else {
2107211946Sjchandra		*n_entries = msg_sz + 1;
2108211946Sjchandra	}
2109211946Sjchandra
2110211946Sjchandra	return (0);
2111211946Sjchandra}
2112211946Sjchandra
2113211946Sjchandrastatic int
2114211946Sjchandrasend_fmn_msg_tx(struct nlge_softc *sc, struct msgrng_msg *msg,
2115211946Sjchandra    uint32_t n_entries)
2116211946Sjchandra{
2117212324Sjchandra	uint32_t msgrng_flags;
2118212409Sjchandra	int ret;
2119212409Sjchandra	int i = 0;
2120211946Sjchandra
2121212324Sjchandra	do {
2122212324Sjchandra		msgrng_flags = msgrng_access_enable();
2123212553Sjchandra		ret = message_send(n_entries, MSGRNG_CODE_MAC,
2124212324Sjchandra		    sc->tx_bucket_id, msg);
2125212324Sjchandra		msgrng_restore(msgrng_flags);
2126212790Sjchandra		if (ret == 0)
2127212790Sjchandra			return (0);
2128212790Sjchandra		i++;
2129212790Sjchandra	} while (i < 100000);
2130212790Sjchandra
2131212896Sjchandra	device_printf(sc->nlge_dev, "Too many credit fails in tx path\n");
2132212790Sjchandra
2133212790Sjchandra	return (1);
2134211946Sjchandra}
2135211946Sjchandra
2136211946Sjchandrastatic void
2137212324Sjchandrarelease_tx_desc(vm_paddr_t paddr)
2138211946Sjchandra{
2139211946Sjchandra	struct nlge_tx_desc *tx_desc;
2140211946Sjchandra	uint32_t 	sr;
2141212758Sjchandra	uint64_t	vaddr;
2142211946Sjchandra
2143211946Sjchandra	paddr += (XLR_MAX_TX_FRAGS * sizeof(uint64_t));
2144211946Sjchandra	sr = xlr_enable_kx();
2145212758Sjchandra	vaddr = xlr_paddr_ld(paddr);
2146212758Sjchandra	xlr_restore_kx(sr);
2147211946Sjchandra
2148212758Sjchandra	tx_desc = (struct nlge_tx_desc*)(intptr_t)vaddr;
2149211946Sjchandra	uma_zfree(nl_tx_desc_zone, tx_desc);
2150211946Sjchandra}
2151211946Sjchandra
2152211946Sjchandrastatic void *
2153211946Sjchandraget_buf(void)
2154211946Sjchandra{
2155212758Sjchandra	struct mbuf	*m_new;
2156212758Sjchandra	uint64_t 	*md;
2157212758Sjchandra#ifdef INVARIANTS
2158212758Sjchandra	vm_paddr_t	temp1, temp2;
2159212758Sjchandra#endif
2160211946Sjchandra
2161243882Sglebius	if ((m_new = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR)) == NULL)
2162212758Sjchandra		return (NULL);
2163212347Sjchandra	m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
2164212896Sjchandra	m_adj(m_new, XLR_CACHELINE_SIZE - ((uintptr_t)m_new->m_data & 0x1f));
2165212758Sjchandra	md = (uint64_t *)m_new->m_data;
2166212758Sjchandra	md[0] = (intptr_t)m_new;	/* Back Ptr */
2167211946Sjchandra	md[1] = 0xf00bad;
2168211946Sjchandra	m_adj(m_new, XLR_CACHELINE_SIZE);
2169211946Sjchandra
2170212758Sjchandra#ifdef INVARIANTS
2171211946Sjchandra	temp1 = vtophys((vm_offset_t) m_new->m_data);
2172211946Sjchandra	temp2 = vtophys((vm_offset_t) m_new->m_data + 1536);
2173211946Sjchandra	if ((temp1 + 1536) != temp2)
2174211946Sjchandra		panic("ALLOCED BUFFER IS NOT CONTIGUOUS\n");
2175212758Sjchandra#endif
2176211946Sjchandra
2177211946Sjchandra	return ((void *)m_new->m_data);
2178211946Sjchandra}
2179211946Sjchandra
2180211946Sjchandrastatic int
2181211946Sjchandranlge_gmac_config_speed(struct nlge_softc *sc, int quick)
2182211946Sjchandra{
2183211946Sjchandra	struct mii_data *md;
2184211946Sjchandra	xlr_reg_t  *mmio;
2185211946Sjchandra	int bmsr, n_tries, max_tries;
2186211946Sjchandra	int core_ctl[]    = { 0x2, 0x1, 0x0, 0x1 };
2187211946Sjchandra	int sgmii_speed[] = { SGMII_SPEED_10,
2188211946Sjchandra			      SGMII_SPEED_100,
2189211946Sjchandra			      SGMII_SPEED_1000,
2190211946Sjchandra			      SGMII_SPEED_100 };    /* default to 100Mbps */
2191211946Sjchandra	char *speed_str[] = { "10",
2192211946Sjchandra			      "100",
2193211946Sjchandra			      "1000",
2194211946Sjchandra			      "unknown, defaulting to 100" };
2195211946Sjchandra	int link_state = LINK_STATE_DOWN;
2196211946Sjchandra
2197211946Sjchandra	if (sc->port_type == XLR_XAUI || sc->port_type == XLR_XGMII)
2198211946Sjchandra		return 0;
2199211946Sjchandra
2200211946Sjchandra	md = NULL;
2201211946Sjchandra	mmio = sc->base;
2202211946Sjchandra	if (sc->mii_base != NULL) {
2203211946Sjchandra		max_tries = (quick == 1) ? 100 : 4000;
2204211946Sjchandra		bmsr = 0;
2205211946Sjchandra		for (n_tries = 0; n_tries < max_tries; n_tries++) {
2206211946Sjchandra			bmsr = nlge_mii_read_internal(sc->mii_base,
2207211946Sjchandra			    sc->phy_addr, MII_BMSR);
2208211946Sjchandra			if ((bmsr & BMSR_ACOMP) && (bmsr & BMSR_LINK))
2209211946Sjchandra				break; /* Auto-negotiation is complete
2210211946Sjchandra					  and link is up */
2211211946Sjchandra			DELAY(1000);
2212211946Sjchandra		}
2213211946Sjchandra		bmsr &= BMSR_LINK;
2214211946Sjchandra		sc->link = (bmsr == 0) ? xlr_mac_link_down : xlr_mac_link_up;
2215211946Sjchandra		sc->speed = nlge_mii_read_internal(sc->mii_base, sc->phy_addr, 28);
2216211946Sjchandra		sc->speed = (sc->speed >> 3) & 0x03;
2217211946Sjchandra		if (sc->link == xlr_mac_link_up) {
2218211946Sjchandra			link_state = LINK_STATE_UP;
2219211946Sjchandra			nlge_sgmii_init(sc);
2220211946Sjchandra		}
2221211946Sjchandra		if (sc->mii_bus)
2222211946Sjchandra			md = (struct mii_data *)device_get_softc(sc->mii_bus);
2223211946Sjchandra	}
2224211946Sjchandra
2225211946Sjchandra	if (sc->port_type != XLR_RGMII)
2226211946Sjchandra		NLGE_WRITE(mmio, R_INTERFACE_CONTROL, sgmii_speed[sc->speed]);
2227211946Sjchandra	if (sc->speed == xlr_mac_speed_10 || sc->speed == xlr_mac_speed_100 ||
2228211946Sjchandra	    sc->speed == xlr_mac_speed_rsvd) {
2229211946Sjchandra		NLGE_WRITE(mmio, R_MAC_CONFIG_2, 0x7117);
2230211946Sjchandra	} else if (sc->speed == xlr_mac_speed_1000) {
2231211946Sjchandra		NLGE_WRITE(mmio, R_MAC_CONFIG_2, 0x7217);
2232211946Sjchandra		if (md != NULL) {
2233211946Sjchandra			ifmedia_set(&md->mii_media, IFM_MAKEWORD(IFM_ETHER,
2234211946Sjchandra			    IFM_1000_T, IFM_FDX, md->mii_instance));
2235211946Sjchandra		}
2236211946Sjchandra	}
2237211946Sjchandra	NLGE_WRITE(mmio, R_CORECONTROL, core_ctl[sc->speed]);
2238211946Sjchandra	if_link_state_change(sc->nlge_if, link_state);
2239211946Sjchandra	printf("%s: [%sMbps]\n", device_get_nameunit(sc->nlge_dev),
2240211946Sjchandra	    speed_str[sc->speed]);
2241213475Sjchandra
2242211946Sjchandra	return (0);
2243211946Sjchandra}
2244211946Sjchandra
2245211946Sjchandra/*
2246211946Sjchandra * This function is called for each port that was added to the device tree
2247211946Sjchandra * and it initializes the following port attributes:
2248211946Sjchandra * 	- type
2249211946Sjchandra *      - base (base address to access port-specific registers)
2250211946Sjchandra *      - mii_base
2251211946Sjchandra * 	- phy_addr
2252211946Sjchandra */
2253211946Sjchandrastatic void
2254211946Sjchandranlge_set_port_attribs(struct nlge_softc *sc,
2255211946Sjchandra    struct xlr_gmac_port *port_info)
2256211946Sjchandra{
2257211946Sjchandra	sc->instance = port_info->instance % 4;	/* TBD: will not work for SPI-4 */
2258211946Sjchandra	sc->port_type = port_info->type;
2259212896Sjchandra	sc->base = xlr_io_mmio(port_info->base_addr);
2260212896Sjchandra	sc->mii_base = xlr_io_mmio(port_info->mii_addr);
2261211946Sjchandra	if (port_info->pcs_addr != 0)
2262212896Sjchandra		sc->pcs_addr = xlr_io_mmio(port_info->pcs_addr);
2263211946Sjchandra	if (port_info->serdes_addr != 0)
2264212896Sjchandra		sc->serdes_addr = xlr_io_mmio(port_info->serdes_addr);
2265211946Sjchandra	sc->phy_addr = port_info->phy_addr;
2266211946Sjchandra
2267211946Sjchandra	PDEBUG("Port%d: base=%p, mii_base=%p, phy_addr=%d\n", sc->id, sc->base,
2268211946Sjchandra	    sc->mii_base, sc->phy_addr);
2269211946Sjchandra}
2270211946Sjchandra
2271211946Sjchandra/* ------------------------------------------------------------------------ */
2272211946Sjchandra
2273211946Sjchandra/* Debug dump functions */
2274211946Sjchandra
2275211946Sjchandra#ifdef DEBUG
2276211946Sjchandra
2277211946Sjchandrastatic void
2278211946Sjchandradump_reg(xlr_reg_t *base, uint32_t offset, char *name)
2279211946Sjchandra{
2280211946Sjchandra	int val;
2281211946Sjchandra
2282211946Sjchandra	val = NLGE_READ(base, offset);
2283211946Sjchandra	printf("%-30s: 0x%8x 0x%8x\n", name, offset, val);
2284211946Sjchandra}
2285211946Sjchandra
2286211946Sjchandra#define STRINGIFY(x) 		#x
2287211946Sjchandra
2288211946Sjchandrastatic void
2289211946Sjchandradump_na_registers(xlr_reg_t *base_addr, int port_id)
2290211946Sjchandra{
2291211946Sjchandra	PDEBUG("Register dump for NA (of port=%d)\n", port_id);
2292211946Sjchandra	dump_reg(base_addr, R_PARSERCONFIGREG, STRINGIFY(R_PARSERCONFIGREG));
2293211946Sjchandra	PDEBUG("Tx bucket sizes\n");
2294211946Sjchandra	dump_reg(base_addr, R_GMAC_JFR0_BUCKET_SIZE,
2295211946Sjchandra	    STRINGIFY(R_GMAC_JFR0_BUCKET_SIZE));
2296211946Sjchandra	dump_reg(base_addr, R_GMAC_RFR0_BUCKET_SIZE,
2297211946Sjchandra	    STRINGIFY(R_GMAC_RFR0_BUCKET_SIZE));
2298211946Sjchandra	dump_reg(base_addr, R_GMAC_TX0_BUCKET_SIZE,
2299211946Sjchandra	    STRINGIFY(R_GMAC_TX0_BUCKET_SIZE));
2300211946Sjchandra	dump_reg(base_addr, R_GMAC_TX1_BUCKET_SIZE,
2301211946Sjchandra	    STRINGIFY(R_GMAC_TX1_BUCKET_SIZE));
2302211946Sjchandra	dump_reg(base_addr, R_GMAC_TX2_BUCKET_SIZE,
2303211946Sjchandra	    STRINGIFY(R_GMAC_TX2_BUCKET_SIZE));
2304211946Sjchandra	dump_reg(base_addr, R_GMAC_TX3_BUCKET_SIZE,
2305211946Sjchandra	    STRINGIFY(R_GMAC_TX3_BUCKET_SIZE));
2306211946Sjchandra	dump_reg(base_addr, R_GMAC_JFR1_BUCKET_SIZE,
2307211946Sjchandra	    STRINGIFY(R_GMAC_JFR1_BUCKET_SIZE));
2308211946Sjchandra	dump_reg(base_addr, R_GMAC_RFR1_BUCKET_SIZE,
2309211946Sjchandra	    STRINGIFY(R_GMAC_RFR1_BUCKET_SIZE));
2310211946Sjchandra	dump_reg(base_addr, R_TXDATAFIFO0, STRINGIFY(R_TXDATAFIFO0));
2311211946Sjchandra	dump_reg(base_addr, R_TXDATAFIFO1, STRINGIFY(R_TXDATAFIFO1));
2312211946Sjchandra}
2313211946Sjchandra
2314211946Sjchandrastatic void
2315211946Sjchandradump_gmac_registers(struct nlge_softc *sc)
2316211946Sjchandra{
2317211946Sjchandra	xlr_reg_t *base_addr = sc->base;
2318211946Sjchandra	int port_id = sc->instance;
2319211946Sjchandra
2320211946Sjchandra	PDEBUG("Register dump for port=%d\n", port_id);
2321211946Sjchandra	if (sc->port_type == XLR_RGMII || sc->port_type == XLR_SGMII) {
2322211946Sjchandra		dump_reg(base_addr, R_MAC_CONFIG_1, STRINGIFY(R_MAC_CONFIG_1));
2323211946Sjchandra		dump_reg(base_addr, R_MAC_CONFIG_2, STRINGIFY(R_MAC_CONFIG_2));
2324211946Sjchandra		dump_reg(base_addr, R_IPG_IFG, STRINGIFY(R_IPG_IFG));
2325211946Sjchandra		dump_reg(base_addr, R_HALF_DUPLEX, STRINGIFY(R_HALF_DUPLEX));
2326211946Sjchandra		dump_reg(base_addr, R_MAXIMUM_FRAME_LENGTH,
2327211946Sjchandra		    STRINGIFY(R_MAXIMUM_FRAME_LENGTH));
2328211946Sjchandra		dump_reg(base_addr, R_TEST, STRINGIFY(R_TEST));
2329211946Sjchandra		dump_reg(base_addr, R_MII_MGMT_CONFIG,
2330211946Sjchandra		    STRINGIFY(R_MII_MGMT_CONFIG));
2331211946Sjchandra		dump_reg(base_addr, R_MII_MGMT_COMMAND,
2332211946Sjchandra		    STRINGIFY(R_MII_MGMT_COMMAND));
2333211946Sjchandra		dump_reg(base_addr, R_MII_MGMT_ADDRESS,
2334211946Sjchandra		    STRINGIFY(R_MII_MGMT_ADDRESS));
2335211946Sjchandra		dump_reg(base_addr, R_MII_MGMT_WRITE_DATA,
2336211946Sjchandra		    STRINGIFY(R_MII_MGMT_WRITE_DATA));
2337211946Sjchandra		dump_reg(base_addr, R_MII_MGMT_STATUS,
2338211946Sjchandra		    STRINGIFY(R_MII_MGMT_STATUS));
2339211946Sjchandra		dump_reg(base_addr, R_MII_MGMT_INDICATORS,
2340211946Sjchandra		    STRINGIFY(R_MII_MGMT_INDICATORS));
2341211946Sjchandra		dump_reg(base_addr, R_INTERFACE_CONTROL,
2342211946Sjchandra		    STRINGIFY(R_INTERFACE_CONTROL));
2343211946Sjchandra		dump_reg(base_addr, R_INTERFACE_STATUS,
2344211946Sjchandra		    STRINGIFY(R_INTERFACE_STATUS));
2345211946Sjchandra	} else if (sc->port_type == XLR_XAUI || sc->port_type == XLR_XGMII) {
2346211946Sjchandra		dump_reg(base_addr, R_XGMAC_CONFIG_0,
2347211946Sjchandra		    STRINGIFY(R_XGMAC_CONFIG_0));
2348211946Sjchandra		dump_reg(base_addr, R_XGMAC_CONFIG_1,
2349211946Sjchandra		    STRINGIFY(R_XGMAC_CONFIG_1));
2350211946Sjchandra		dump_reg(base_addr, R_XGMAC_CONFIG_2,
2351211946Sjchandra		    STRINGIFY(R_XGMAC_CONFIG_2));
2352211946Sjchandra		dump_reg(base_addr, R_XGMAC_CONFIG_3,
2353211946Sjchandra		    STRINGIFY(R_XGMAC_CONFIG_3));
2354211946Sjchandra		dump_reg(base_addr, R_XGMAC_STATION_ADDRESS_LS,
2355211946Sjchandra		    STRINGIFY(R_XGMAC_STATION_ADDRESS_LS));
2356211946Sjchandra		dump_reg(base_addr, R_XGMAC_STATION_ADDRESS_MS,
2357211946Sjchandra		    STRINGIFY(R_XGMAC_STATION_ADDRESS_MS));
2358211946Sjchandra		dump_reg(base_addr, R_XGMAC_MAX_FRAME_LEN,
2359211946Sjchandra		    STRINGIFY(R_XGMAC_MAX_FRAME_LEN));
2360211946Sjchandra		dump_reg(base_addr, R_XGMAC_REV_LEVEL,
2361211946Sjchandra		    STRINGIFY(R_XGMAC_REV_LEVEL));
2362211946Sjchandra		dump_reg(base_addr, R_XGMAC_MIIM_COMMAND,
2363211946Sjchandra		    STRINGIFY(R_XGMAC_MIIM_COMMAND));
2364211946Sjchandra		dump_reg(base_addr, R_XGMAC_MIIM_FILED,
2365211946Sjchandra		    STRINGIFY(R_XGMAC_MIIM_FILED));
2366211946Sjchandra		dump_reg(base_addr, R_XGMAC_MIIM_CONFIG,
2367211946Sjchandra		    STRINGIFY(R_XGMAC_MIIM_CONFIG));
2368211946Sjchandra		dump_reg(base_addr, R_XGMAC_MIIM_LINK_FAIL_VECTOR,
2369211946Sjchandra		    STRINGIFY(R_XGMAC_MIIM_LINK_FAIL_VECTOR));
2370211946Sjchandra		dump_reg(base_addr, R_XGMAC_MIIM_INDICATOR,
2371211946Sjchandra		    STRINGIFY(R_XGMAC_MIIM_INDICATOR));
2372211946Sjchandra	}
2373211946Sjchandra
2374211946Sjchandra	dump_reg(base_addr, R_MAC_ADDR0, STRINGIFY(R_MAC_ADDR0));
2375211946Sjchandra	dump_reg(base_addr, R_MAC_ADDR0 + 1, STRINGIFY(R_MAC_ADDR0+1));
2376211946Sjchandra	dump_reg(base_addr, R_MAC_ADDR1, STRINGIFY(R_MAC_ADDR1));
2377211946Sjchandra	dump_reg(base_addr, R_MAC_ADDR2, STRINGIFY(R_MAC_ADDR2));
2378211946Sjchandra	dump_reg(base_addr, R_MAC_ADDR3, STRINGIFY(R_MAC_ADDR3));
2379211946Sjchandra	dump_reg(base_addr, R_MAC_ADDR_MASK2, STRINGIFY(R_MAC_ADDR_MASK2));
2380211946Sjchandra	dump_reg(base_addr, R_MAC_ADDR_MASK3, STRINGIFY(R_MAC_ADDR_MASK3));
2381211946Sjchandra	dump_reg(base_addr, R_MAC_FILTER_CONFIG, STRINGIFY(R_MAC_FILTER_CONFIG));
2382211946Sjchandra	dump_reg(base_addr, R_TX_CONTROL, STRINGIFY(R_TX_CONTROL));
2383211946Sjchandra	dump_reg(base_addr, R_RX_CONTROL, STRINGIFY(R_RX_CONTROL));
2384211946Sjchandra	dump_reg(base_addr, R_DESC_PACK_CTRL, STRINGIFY(R_DESC_PACK_CTRL));
2385211946Sjchandra	dump_reg(base_addr, R_STATCTRL, STRINGIFY(R_STATCTRL));
2386211946Sjchandra	dump_reg(base_addr, R_L2ALLOCCTRL, STRINGIFY(R_L2ALLOCCTRL));
2387211946Sjchandra	dump_reg(base_addr, R_INTMASK, STRINGIFY(R_INTMASK));
2388211946Sjchandra	dump_reg(base_addr, R_INTREG, STRINGIFY(R_INTREG));
2389211946Sjchandra	dump_reg(base_addr, R_TXRETRY, STRINGIFY(R_TXRETRY));
2390211946Sjchandra	dump_reg(base_addr, R_CORECONTROL, STRINGIFY(R_CORECONTROL));
2391211946Sjchandra	dump_reg(base_addr, R_BYTEOFFSET0, STRINGIFY(R_BYTEOFFSET0));
2392211946Sjchandra	dump_reg(base_addr, R_BYTEOFFSET1, STRINGIFY(R_BYTEOFFSET1));
2393211946Sjchandra	dump_reg(base_addr, R_L2TYPE_0, STRINGIFY(R_L2TYPE_0));
2394211946Sjchandra	dump_na_registers(base_addr, port_id);
2395211946Sjchandra}
2396211946Sjchandra
2397211946Sjchandrastatic void
2398211946Sjchandradump_fmn_cpu_credits_for_gmac(struct xlr_board_info *board, int gmac_id)
2399211946Sjchandra{
2400211946Sjchandra	struct stn_cc *cc;
2401211946Sjchandra	int gmac_bucket_ids[] = { 97, 98, 99, 100, 101, 103 };
2402211946Sjchandra	int j, k, r, c;
2403211946Sjchandra	int n_gmac_buckets;
2404211946Sjchandra
2405211946Sjchandra	n_gmac_buckets = sizeof (gmac_bucket_ids) / sizeof (gmac_bucket_ids[0]);
2406211946Sjchandra	for (j = 0; j < 8; j++) { 		// for each cpu
2407211946Sjchandra		cc = board->credit_configs[j];
2408211946Sjchandra		printf("Credits for Station CPU_%d ---> GMAC buckets (tx path)\n", j);
2409211946Sjchandra		for (k = 0; k < n_gmac_buckets; k++) {
2410211946Sjchandra			r = gmac_bucket_ids[k] / 8;
2411211946Sjchandra			c = gmac_bucket_ids[k] % 8;
2412211946Sjchandra			printf ("    --> gmac%d_bucket_%-3d: credits=%d\n", gmac_id,
2413211946Sjchandra				gmac_bucket_ids[k], cc->counters[r][c]);
2414211946Sjchandra		}
2415211946Sjchandra	}
2416211946Sjchandra}
2417211946Sjchandra
2418211946Sjchandrastatic void
2419211946Sjchandradump_fmn_gmac_credits(struct xlr_board_info *board, int gmac_id)
2420211946Sjchandra{
2421211946Sjchandra	struct stn_cc *cc;
2422211946Sjchandra	int j, k;
2423211946Sjchandra
2424211946Sjchandra	cc = board->gmac_block[gmac_id].credit_config;
2425211946Sjchandra	printf("Credits for Station: GMAC_%d ---> CPU buckets (rx path)\n", gmac_id);
2426211946Sjchandra	for (j = 0; j < 8; j++) { 		// for each cpu
2427211946Sjchandra		printf("    ---> cpu_%d\n", j);
2428211946Sjchandra		for (k = 0; k < 8; k++) {	// for each bucket in cpu
2429211946Sjchandra			printf("        ---> bucket_%d: credits=%d\n", j * 8 + k,
2430211946Sjchandra			       cc->counters[j][k]);
2431211946Sjchandra		}
2432211946Sjchandra	}
2433211946Sjchandra}
2434211946Sjchandra
2435211946Sjchandrastatic void
2436211946Sjchandradump_board_info(struct xlr_board_info *board)
2437211946Sjchandra{
2438211946Sjchandra	struct xlr_gmac_block_t *gm;
2439211946Sjchandra	int i, k;
2440211946Sjchandra
2441211946Sjchandra	printf("cpu=%x ", xlr_revision());
2442211946Sjchandra	printf("board_version: major=%llx, minor=%llx\n",
2443211946Sjchandra	    xlr_boot1_info.board_major_version,
2444211946Sjchandra	    xlr_boot1_info.board_minor_version);
2445211946Sjchandra	printf("is_xls=%d, nr_cpus=%d, usb=%s, cfi=%s, ata=%s\npci_irq=%d,"
2446211946Sjchandra	    "gmac_ports=%d\n", board->is_xls, board->nr_cpus,
2447211946Sjchandra	    board->usb ? "Yes" : "No", board->cfi ? "Yes": "No",
2448211946Sjchandra	    board->ata ? "Yes" : "No", board->pci_irq, board->gmacports);
2449211946Sjchandra	printf("FMN: Core-station bucket sizes\n");
2450211946Sjchandra	for (i = 0; i < 128; i++) {
2451211946Sjchandra		if (i && ((i % 16) == 0))
2452211946Sjchandra			printf("\n");
2453211946Sjchandra		printf ("b[%d] = %d ", i, board->bucket_sizes->bucket[i]);
2454211946Sjchandra	}
2455211946Sjchandra	printf("\n");
2456211946Sjchandra	for (i = 0; i < 3; i++) {
2457211946Sjchandra		gm = &board->gmac_block[i];
2458211946Sjchandra		printf("RNA_%d: type=%d, enabled=%s, mode=%d, station_id=%d,"
2459211946Sjchandra		    "station_txbase=%d, station_rfr=%d ", i, gm->type,
2460211946Sjchandra		    gm->enabled ? "Yes" : "No", gm->mode, gm->station_id,
2461211946Sjchandra		    gm->station_txbase, gm->station_rfr);
2462211946Sjchandra		printf("n_ports=%d, baseaddr=%p, baseirq=%d, baseinst=%d\n",
2463211946Sjchandra		     gm->num_ports, (xlr_reg_t *)gm->baseaddr, gm->baseirq,
2464211946Sjchandra		     gm->baseinst);
2465211946Sjchandra	}
2466211946Sjchandra	for (k = 0; k < 3; k++) { 	// for each NA
2467211946Sjchandra		dump_fmn_cpu_credits_for_gmac(board, k);
2468211946Sjchandra		dump_fmn_gmac_credits(board, k);
2469211946Sjchandra	}
2470211946Sjchandra}
2471211946Sjchandra
2472211946Sjchandrastatic void
2473211946Sjchandradump_mac_stats(struct nlge_softc *sc)
2474211946Sjchandra{
2475211946Sjchandra	xlr_reg_t *addr;
2476211946Sjchandra	uint32_t pkts_tx, pkts_rx;
2477211946Sjchandra
2478211946Sjchandra	addr = sc->base;
2479211946Sjchandra	pkts_rx = NLGE_READ(sc->base, R_RPKT);
2480211946Sjchandra	pkts_tx = NLGE_READ(sc->base, R_TPKT);
2481211946Sjchandra
2482211946Sjchandra	printf("[nlge_%d mac stats]: pkts_tx=%u, pkts_rx=%u\n", sc->id, pkts_tx,
2483211946Sjchandra	    pkts_rx);
2484211946Sjchandra	if (pkts_rx > 0) {
2485211946Sjchandra		uint32_t r;
2486211946Sjchandra
2487211946Sjchandra		/* dump all rx counters. we need this because pkts_rx includes
2488211946Sjchandra		   bad packets. */
2489211946Sjchandra		for (r = R_RFCS; r <= R_ROVR; r++)
2490211946Sjchandra			printf("[nlge_%d mac stats]: [0x%x]=%u\n", sc->id, r,
2491211946Sjchandra			    NLGE_READ(sc->base, r));
2492211946Sjchandra	}
2493211946Sjchandra	if (pkts_tx > 0) {
2494211946Sjchandra		uint32_t r;
2495211946Sjchandra
2496211946Sjchandra		/* dump all tx counters. might be useful for debugging. */
2497211946Sjchandra		for (r = R_TMCA; r <= R_TFRG; r++) {
2498211946Sjchandra			if ((r == (R_TNCL + 1)) || (r == (R_TNCL + 2)))
2499211946Sjchandra				continue;
2500211946Sjchandra			printf("[nlge_%d mac stats]: [0x%x]=%u\n", sc->id, r,
2501211946Sjchandra			    NLGE_READ(sc->base, r));
2502211946Sjchandra		}
2503211946Sjchandra	}
2504211946Sjchandra
2505211946Sjchandra}
2506211946Sjchandra
2507211946Sjchandrastatic void
2508211946Sjchandradump_mii_regs(struct nlge_softc *sc)
2509211946Sjchandra{
2510211946Sjchandra	uint32_t mii_regs[] = {  0x0,  0x1,  0x2,  0x3,  0x4,  0x5,  0x6,  0x7,
2511211946Sjchandra	                         0x8,  0x9,  0xa,  0xf, 0x10, 0x11, 0x12, 0x13,
2512211946Sjchandra				0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
2513211946Sjchandra				0x1c, 0x1d, 0x1e};
2514211946Sjchandra	int i, n_regs;
2515211946Sjchandra
2516211946Sjchandra	if (sc->mii_base == NULL || sc->mii_bus == NULL)
2517211946Sjchandra		return;
2518211946Sjchandra
2519211946Sjchandra	n_regs = sizeof (mii_regs) / sizeof (mii_regs[0]);
2520211946Sjchandra	for (i = 0; i < n_regs; i++) {
2521211946Sjchandra		printf("[mii_0x%x] = %x\n", mii_regs[i],
2522211946Sjchandra		    nlge_mii_read_internal(sc->mii_base, sc->phy_addr,
2523211946Sjchandra		        mii_regs[i]));
2524211946Sjchandra	}
2525211946Sjchandra}
2526211946Sjchandra
2527211946Sjchandrastatic void
2528211946Sjchandradump_ifmedia(struct ifmedia *ifm)
2529211946Sjchandra{
2530211946Sjchandra	printf("ifm_mask=%08x, ifm_media=%08x, cur=%p\n", ifm->ifm_mask,
2531211946Sjchandra	    ifm->ifm_media, ifm->ifm_cur);
2532211946Sjchandra	if (ifm->ifm_cur != NULL) {
2533211946Sjchandra		printf("Cur attribs: ifmedia_entry.ifm_media=%08x,"
2534211946Sjchandra		    " ifmedia_entry.ifm_data=%08x\n", ifm->ifm_cur->ifm_media,
2535211946Sjchandra		    ifm->ifm_cur->ifm_data);
2536211946Sjchandra	}
2537211946Sjchandra}
2538211946Sjchandra
2539211946Sjchandrastatic void
2540211946Sjchandradump_mii_data(struct mii_data *mii)
2541211946Sjchandra{
2542211946Sjchandra	dump_ifmedia(&mii->mii_media);
2543211946Sjchandra	printf("ifp=%p, mii_instance=%d, mii_media_status=%08x,"
2544211946Sjchandra	    " mii_media_active=%08x\n", mii->mii_ifp, mii->mii_instance,
2545211946Sjchandra	    mii->mii_media_status, mii->mii_media_active);
2546211946Sjchandra}
2547211946Sjchandra
2548211946Sjchandrastatic void
2549211946Sjchandradump_pcs_regs(struct nlge_softc *sc, int phy)
2550211946Sjchandra{
2551211946Sjchandra	int i, val;
2552211946Sjchandra
2553211946Sjchandra	printf("PCS regs from %p for phy=%d\n", sc->pcs_addr, phy);
2554211946Sjchandra	for (i = 0; i < 18; i++) {
2555211946Sjchandra		if (i == 2 || i == 3 || (i >= 9 && i <= 14))
2556211946Sjchandra			continue;
2557211946Sjchandra		val = nlge_mii_read_internal(sc->pcs_addr, phy, i);
2558211946Sjchandra		printf("PHY:%d pcs[0x%x] is 0x%x\n", phy, i, val);
2559211946Sjchandra	}
2560211946Sjchandra}
2561211946Sjchandra#endif
2562