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