1179337Syongari/*-
2179337Syongari * Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
3179337Syongari * All rights reserved.
4179337Syongari *
5179337Syongari * Redistribution and use in source and binary forms, with or without
6179337Syongari * modification, are permitted provided that the following conditions
7179337Syongari * are met:
8179337Syongari * 1. Redistributions of source code must retain the above copyright
9179337Syongari *    notice unmodified, this list of conditions, and the following
10179337Syongari *    disclaimer.
11179337Syongari * 2. Redistributions in binary form must reproduce the above copyright
12179337Syongari *    notice, this list of conditions and the following disclaimer in the
13179337Syongari *    documentation and/or other materials provided with the distribution.
14179337Syongari *
15179337Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16179337Syongari * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17179337Syongari * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18179337Syongari * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19179337Syongari * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20179337Syongari * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21179337Syongari * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22179337Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23179337Syongari * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24179337Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25179337Syongari * SUCH DAMAGE.
26179337Syongari */
27179337Syongari
28179337Syongari#include <sys/cdefs.h>
29179337Syongari__FBSDID("$FreeBSD$");
30179337Syongari
31179337Syongari#include <sys/param.h>
32179337Syongari#include <sys/systm.h>
33179337Syongari#include <sys/bus.h>
34179337Syongari#include <sys/endian.h>
35179337Syongari#include <sys/kernel.h>
36179337Syongari#include <sys/malloc.h>
37179337Syongari#include <sys/mbuf.h>
38179337Syongari#include <sys/rman.h>
39179337Syongari#include <sys/module.h>
40179337Syongari#include <sys/proc.h>
41179337Syongari#include <sys/queue.h>
42179337Syongari#include <sys/socket.h>
43179337Syongari#include <sys/sockio.h>
44179337Syongari#include <sys/sysctl.h>
45179337Syongari#include <sys/taskqueue.h>
46179337Syongari
47179337Syongari#include <net/bpf.h>
48179337Syongari#include <net/if.h>
49257176Sglebius#include <net/if_var.h>
50179337Syongari#include <net/if_arp.h>
51179337Syongari#include <net/ethernet.h>
52179337Syongari#include <net/if_dl.h>
53179337Syongari#include <net/if_media.h>
54179337Syongari#include <net/if_types.h>
55179337Syongari#include <net/if_vlan_var.h>
56179337Syongari
57179337Syongari#include <netinet/in.h>
58179337Syongari#include <netinet/in_systm.h>
59179337Syongari#include <netinet/ip.h>
60179337Syongari#include <netinet/tcp.h>
61179337Syongari
62179337Syongari#include <dev/mii/mii.h>
63179337Syongari#include <dev/mii/miivar.h>
64179337Syongari
65179337Syongari#include <dev/pci/pcireg.h>
66179337Syongari#include <dev/pci/pcivar.h>
67179337Syongari
68179337Syongari#include <machine/bus.h>
69179337Syongari#include <machine/in_cksum.h>
70179337Syongari
71179337Syongari#include <dev/jme/if_jmereg.h>
72179337Syongari#include <dev/jme/if_jmevar.h>
73179337Syongari
74179337Syongari/* "device miibus" required.  See GENERIC if you get errors here. */
75179337Syongari#include "miibus_if.h"
76179337Syongari
77179337Syongari/* Define the following to disable printing Rx errors. */
78179337Syongari#undef	JME_SHOW_ERRORS
79179337Syongari
80179337Syongari#define	JME_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
81179337Syongari
82179337SyongariMODULE_DEPEND(jme, pci, 1, 1, 1);
83179337SyongariMODULE_DEPEND(jme, ether, 1, 1, 1);
84179337SyongariMODULE_DEPEND(jme, miibus, 1, 1, 1);
85179337Syongari
86179337Syongari/* Tunables. */
87179337Syongaristatic int msi_disable = 0;
88179337Syongaristatic int msix_disable = 0;
89179337SyongariTUNABLE_INT("hw.jme.msi_disable", &msi_disable);
90179337SyongariTUNABLE_INT("hw.jme.msix_disable", &msix_disable);
91179337Syongari
92179337Syongari/*
93179337Syongari * Devices supported by this driver.
94179337Syongari */
95179337Syongaristatic struct jme_dev {
96179337Syongari	uint16_t	jme_vendorid;
97179337Syongari	uint16_t	jme_deviceid;
98179337Syongari	const char	*jme_name;
99179337Syongari} jme_devs[] = {
100179337Syongari	{ VENDORID_JMICRON, DEVICEID_JMC250,
101216551Syongari	    "JMicron Inc, JMC25x Gigabit Ethernet" },
102179337Syongari	{ VENDORID_JMICRON, DEVICEID_JMC260,
103216551Syongari	    "JMicron Inc, JMC26x Fast Ethernet" },
104179337Syongari};
105179337Syongari
106179337Syongaristatic int jme_miibus_readreg(device_t, int, int);
107179337Syongaristatic int jme_miibus_writereg(device_t, int, int, int);
108179337Syongaristatic void jme_miibus_statchg(device_t);
109179337Syongaristatic void jme_mediastatus(struct ifnet *, struct ifmediareq *);
110179337Syongaristatic int jme_mediachange(struct ifnet *);
111179337Syongaristatic int jme_probe(device_t);
112179337Syongaristatic int jme_eeprom_read_byte(struct jme_softc *, uint8_t, uint8_t *);
113179337Syongaristatic int jme_eeprom_macaddr(struct jme_softc *);
114216551Syongaristatic int jme_efuse_macaddr(struct jme_softc *);
115179337Syongaristatic void jme_reg_macaddr(struct jme_softc *);
116216551Syongaristatic void jme_set_macaddr(struct jme_softc *, uint8_t *);
117179337Syongaristatic void jme_map_intr_vector(struct jme_softc *);
118179337Syongaristatic int jme_attach(device_t);
119179337Syongaristatic int jme_detach(device_t);
120179337Syongaristatic void jme_sysctl_node(struct jme_softc *);
121179337Syongaristatic void jme_dmamap_cb(void *, bus_dma_segment_t *, int, int);
122179337Syongaristatic int jme_dma_alloc(struct jme_softc *);
123179337Syongaristatic void jme_dma_free(struct jme_softc *);
124179337Syongaristatic int jme_shutdown(device_t);
125179337Syongaristatic void jme_setlinkspeed(struct jme_softc *);
126179337Syongaristatic void jme_setwol(struct jme_softc *);
127179337Syongaristatic int jme_suspend(device_t);
128179337Syongaristatic int jme_resume(device_t);
129179337Syongaristatic int jme_encap(struct jme_softc *, struct mbuf **);
130179337Syongaristatic void jme_start(struct ifnet *);
131217353Sjhbstatic void jme_start_locked(struct ifnet *);
132179337Syongaristatic void jme_watchdog(struct jme_softc *);
133179337Syongaristatic int jme_ioctl(struct ifnet *, u_long, caddr_t);
134179337Syongaristatic void jme_mac_config(struct jme_softc *);
135179337Syongaristatic void jme_link_task(void *, int);
136179337Syongaristatic int jme_intr(void *);
137179337Syongaristatic void jme_int_task(void *, int);
138179337Syongaristatic void jme_txeof(struct jme_softc *);
139179337Syongaristatic __inline void jme_discard_rxbuf(struct jme_softc *, int);
140179337Syongaristatic void jme_rxeof(struct jme_softc *);
141179337Syongaristatic int jme_rxintr(struct jme_softc *, int);
142179337Syongaristatic void jme_tick(void *);
143179337Syongaristatic void jme_reset(struct jme_softc *);
144179337Syongaristatic void jme_init(void *);
145179337Syongaristatic void jme_init_locked(struct jme_softc *);
146179337Syongaristatic void jme_stop(struct jme_softc *);
147179337Syongaristatic void jme_stop_tx(struct jme_softc *);
148179337Syongaristatic void jme_stop_rx(struct jme_softc *);
149179337Syongaristatic int jme_init_rx_ring(struct jme_softc *);
150179337Syongaristatic void jme_init_tx_ring(struct jme_softc *);
151179337Syongaristatic void jme_init_ssb(struct jme_softc *);
152179337Syongaristatic int jme_newbuf(struct jme_softc *, struct jme_rxdesc *);
153179337Syongaristatic void jme_set_vlan(struct jme_softc *);
154179337Syongaristatic void jme_set_filter(struct jme_softc *);
155185597Syongaristatic void jme_stats_clear(struct jme_softc *);
156185597Syongaristatic void jme_stats_save(struct jme_softc *);
157185597Syongaristatic void jme_stats_update(struct jme_softc *);
158216551Syongaristatic void jme_phy_down(struct jme_softc *);
159216551Syongaristatic void jme_phy_up(struct jme_softc *);
160179337Syongaristatic int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int);
161179337Syongaristatic int sysctl_hw_jme_tx_coal_to(SYSCTL_HANDLER_ARGS);
162179337Syongaristatic int sysctl_hw_jme_tx_coal_pkt(SYSCTL_HANDLER_ARGS);
163179337Syongaristatic int sysctl_hw_jme_rx_coal_to(SYSCTL_HANDLER_ARGS);
164179337Syongaristatic int sysctl_hw_jme_rx_coal_pkt(SYSCTL_HANDLER_ARGS);
165179337Syongaristatic int sysctl_hw_jme_proc_limit(SYSCTL_HANDLER_ARGS);
166179337Syongari
167179337Syongari
168179337Syongaristatic device_method_t jme_methods[] = {
169179337Syongari	/* Device interface. */
170179337Syongari	DEVMETHOD(device_probe,		jme_probe),
171179337Syongari	DEVMETHOD(device_attach,	jme_attach),
172179337Syongari	DEVMETHOD(device_detach,	jme_detach),
173179337Syongari	DEVMETHOD(device_shutdown,	jme_shutdown),
174179337Syongari	DEVMETHOD(device_suspend,	jme_suspend),
175179337Syongari	DEVMETHOD(device_resume,	jme_resume),
176179337Syongari
177179337Syongari	/* MII interface. */
178179337Syongari	DEVMETHOD(miibus_readreg,	jme_miibus_readreg),
179179337Syongari	DEVMETHOD(miibus_writereg,	jme_miibus_writereg),
180179337Syongari	DEVMETHOD(miibus_statchg,	jme_miibus_statchg),
181179337Syongari
182179337Syongari	{ NULL, NULL }
183179337Syongari};
184179337Syongari
185179337Syongaristatic driver_t jme_driver = {
186179337Syongari	"jme",
187179337Syongari	jme_methods,
188179337Syongari	sizeof(struct jme_softc)
189179337Syongari};
190179337Syongari
191179337Syongaristatic devclass_t jme_devclass;
192179337Syongari
193179337SyongariDRIVER_MODULE(jme, pci, jme_driver, jme_devclass, 0, 0);
194179337SyongariDRIVER_MODULE(miibus, jme, miibus_driver, miibus_devclass, 0, 0);
195179337Syongari
196179337Syongaristatic struct resource_spec jme_res_spec_mem[] = {
197179337Syongari	{ SYS_RES_MEMORY,	PCIR_BAR(0),	RF_ACTIVE },
198179337Syongari	{ -1,			0,		0 }
199179337Syongari};
200179337Syongari
201179337Syongaristatic struct resource_spec jme_irq_spec_legacy[] = {
202179337Syongari	{ SYS_RES_IRQ,		0,		RF_ACTIVE | RF_SHAREABLE },
203179337Syongari	{ -1,			0,		0 }
204179337Syongari};
205179337Syongari
206179337Syongaristatic struct resource_spec jme_irq_spec_msi[] = {
207179337Syongari	{ SYS_RES_IRQ,		1,		RF_ACTIVE },
208179337Syongari	{ -1,			0,		0 }
209179337Syongari};
210179337Syongari
211179337Syongari/*
212179337Syongari *	Read a PHY register on the MII of the JMC250.
213179337Syongari */
214179337Syongaristatic int
215179337Syongarijme_miibus_readreg(device_t dev, int phy, int reg)
216179337Syongari{
217179337Syongari	struct jme_softc *sc;
218179337Syongari	uint32_t val;
219179337Syongari	int i;
220179337Syongari
221179337Syongari	sc = device_get_softc(dev);
222179337Syongari
223179337Syongari	/* For FPGA version, PHY address 0 should be ignored. */
224213893Smarius	if ((sc->jme_flags & JME_FLAG_FPGA) != 0 && phy == 0)
225213893Smarius		return (0);
226179337Syongari
227179337Syongari	CSR_WRITE_4(sc, JME_SMI, SMI_OP_READ | SMI_OP_EXECUTE |
228179337Syongari	    SMI_PHY_ADDR(phy) | SMI_REG_ADDR(reg));
229179337Syongari	for (i = JME_PHY_TIMEOUT; i > 0; i--) {
230179337Syongari		DELAY(1);
231179337Syongari		if (((val = CSR_READ_4(sc, JME_SMI)) & SMI_OP_EXECUTE) == 0)
232179337Syongari			break;
233179337Syongari	}
234179337Syongari
235179337Syongari	if (i == 0) {
236179337Syongari		device_printf(sc->jme_dev, "phy read timeout : %d\n", reg);
237179337Syongari		return (0);
238179337Syongari	}
239179337Syongari
240179337Syongari	return ((val & SMI_DATA_MASK) >> SMI_DATA_SHIFT);
241179337Syongari}
242179337Syongari
243179337Syongari/*
244179337Syongari *	Write a PHY register on the MII of the JMC250.
245179337Syongari */
246179337Syongaristatic int
247179337Syongarijme_miibus_writereg(device_t dev, int phy, int reg, int val)
248179337Syongari{
249179337Syongari	struct jme_softc *sc;
250179337Syongari	int i;
251179337Syongari
252179337Syongari	sc = device_get_softc(dev);
253179337Syongari
254179337Syongari	/* For FPGA version, PHY address 0 should be ignored. */
255213893Smarius	if ((sc->jme_flags & JME_FLAG_FPGA) != 0 && phy == 0)
256213893Smarius		return (0);
257179337Syongari
258179337Syongari	CSR_WRITE_4(sc, JME_SMI, SMI_OP_WRITE | SMI_OP_EXECUTE |
259179337Syongari	    ((val << SMI_DATA_SHIFT) & SMI_DATA_MASK) |
260179337Syongari	    SMI_PHY_ADDR(phy) | SMI_REG_ADDR(reg));
261179337Syongari	for (i = JME_PHY_TIMEOUT; i > 0; i--) {
262179337Syongari		DELAY(1);
263179337Syongari		if (((val = CSR_READ_4(sc, JME_SMI)) & SMI_OP_EXECUTE) == 0)
264179337Syongari			break;
265179337Syongari	}
266179337Syongari
267179337Syongari	if (i == 0)
268179337Syongari		device_printf(sc->jme_dev, "phy write timeout : %d\n", reg);
269179337Syongari
270179337Syongari	return (0);
271179337Syongari}
272179337Syongari
273179337Syongari/*
274179337Syongari *	Callback from MII layer when media changes.
275179337Syongari */
276179337Syongaristatic void
277179337Syongarijme_miibus_statchg(device_t dev)
278179337Syongari{
279179337Syongari	struct jme_softc *sc;
280179337Syongari
281179337Syongari	sc = device_get_softc(dev);
282179337Syongari	taskqueue_enqueue(taskqueue_swi, &sc->jme_link_task);
283179337Syongari}
284179337Syongari
285179337Syongari/*
286179337Syongari *	Get the current interface media status.
287179337Syongari */
288179337Syongaristatic void
289179337Syongarijme_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
290179337Syongari{
291179337Syongari	struct jme_softc *sc;
292179337Syongari	struct mii_data *mii;
293179337Syongari
294179337Syongari	sc = ifp->if_softc;
295179337Syongari	JME_LOCK(sc);
296197585Syongari	if ((ifp->if_flags & IFF_UP) == 0) {
297197585Syongari		JME_UNLOCK(sc);
298197585Syongari		return;
299197585Syongari	}
300179337Syongari	mii = device_get_softc(sc->jme_miibus);
301179337Syongari
302179337Syongari	mii_pollstat(mii);
303179337Syongari	ifmr->ifm_status = mii->mii_media_status;
304179337Syongari	ifmr->ifm_active = mii->mii_media_active;
305179337Syongari	JME_UNLOCK(sc);
306179337Syongari}
307179337Syongari
308179337Syongari/*
309179337Syongari *	Set hardware to newly-selected media.
310179337Syongari */
311179337Syongaristatic int
312179337Syongarijme_mediachange(struct ifnet *ifp)
313179337Syongari{
314179337Syongari	struct jme_softc *sc;
315179337Syongari	struct mii_data *mii;
316179337Syongari	struct mii_softc *miisc;
317179337Syongari	int error;
318179337Syongari
319179337Syongari	sc = ifp->if_softc;
320179337Syongari	JME_LOCK(sc);
321179337Syongari	mii = device_get_softc(sc->jme_miibus);
322221407Smarius	LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
323221407Smarius		PHY_RESET(miisc);
324179337Syongari	error = mii_mediachg(mii);
325179337Syongari	JME_UNLOCK(sc);
326179337Syongari
327179337Syongari	return (error);
328179337Syongari}
329179337Syongari
330179337Syongaristatic int
331179337Syongarijme_probe(device_t dev)
332179337Syongari{
333179337Syongari	struct jme_dev *sp;
334179337Syongari	int i;
335179337Syongari	uint16_t vendor, devid;
336179337Syongari
337179337Syongari	vendor = pci_get_vendor(dev);
338179337Syongari	devid = pci_get_device(dev);
339179337Syongari	sp = jme_devs;
340298307Spfg	for (i = 0; i < nitems(jme_devs); i++, sp++) {
341179337Syongari		if (vendor == sp->jme_vendorid &&
342179337Syongari		    devid == sp->jme_deviceid) {
343179337Syongari			device_set_desc(dev, sp->jme_name);
344179337Syongari			return (BUS_PROBE_DEFAULT);
345179337Syongari		}
346179337Syongari	}
347179337Syongari
348179337Syongari	return (ENXIO);
349179337Syongari}
350179337Syongari
351179337Syongaristatic int
352179337Syongarijme_eeprom_read_byte(struct jme_softc *sc, uint8_t addr, uint8_t *val)
353179337Syongari{
354179337Syongari	uint32_t reg;
355179337Syongari	int i;
356179337Syongari
357179337Syongari	*val = 0;
358179337Syongari	for (i = JME_TIMEOUT; i > 0; i--) {
359179337Syongari		reg = CSR_READ_4(sc, JME_SMBCSR);
360179337Syongari		if ((reg & SMBCSR_HW_BUSY_MASK) == SMBCSR_HW_IDLE)
361179337Syongari			break;
362179337Syongari		DELAY(1);
363179337Syongari	}
364179337Syongari
365179337Syongari	if (i == 0) {
366179337Syongari		device_printf(sc->jme_dev, "EEPROM idle timeout!\n");
367179337Syongari		return (ETIMEDOUT);
368179337Syongari	}
369179337Syongari
370179337Syongari	reg = ((uint32_t)addr << SMBINTF_ADDR_SHIFT) & SMBINTF_ADDR_MASK;
371179337Syongari	CSR_WRITE_4(sc, JME_SMBINTF, reg | SMBINTF_RD | SMBINTF_CMD_TRIGGER);
372179337Syongari	for (i = JME_TIMEOUT; i > 0; i--) {
373179337Syongari		DELAY(1);
374179337Syongari		reg = CSR_READ_4(sc, JME_SMBINTF);
375179337Syongari		if ((reg & SMBINTF_CMD_TRIGGER) == 0)
376179337Syongari			break;
377179337Syongari	}
378179337Syongari
379179337Syongari	if (i == 0) {
380179337Syongari		device_printf(sc->jme_dev, "EEPROM read timeout!\n");
381179337Syongari		return (ETIMEDOUT);
382179337Syongari	}
383179337Syongari
384179337Syongari	reg = CSR_READ_4(sc, JME_SMBINTF);
385179337Syongari	*val = (reg & SMBINTF_RD_DATA_MASK) >> SMBINTF_RD_DATA_SHIFT;
386179337Syongari
387179337Syongari	return (0);
388179337Syongari}
389179337Syongari
390179337Syongaristatic int
391179337Syongarijme_eeprom_macaddr(struct jme_softc *sc)
392179337Syongari{
393179337Syongari	uint8_t eaddr[ETHER_ADDR_LEN];
394179337Syongari	uint8_t fup, reg, val;
395179337Syongari	uint32_t offset;
396179337Syongari	int match;
397179337Syongari
398179337Syongari	offset = 0;
399179337Syongari	if (jme_eeprom_read_byte(sc, offset++, &fup) != 0 ||
400179337Syongari	    fup != JME_EEPROM_SIG0)
401179337Syongari		return (ENOENT);
402179337Syongari	if (jme_eeprom_read_byte(sc, offset++, &fup) != 0 ||
403179337Syongari	    fup != JME_EEPROM_SIG1)
404179337Syongari		return (ENOENT);
405179337Syongari	match = 0;
406179337Syongari	do {
407179337Syongari		if (jme_eeprom_read_byte(sc, offset, &fup) != 0)
408179337Syongari			break;
409183859Syongari		if (JME_EEPROM_MKDESC(JME_EEPROM_FUNC0, JME_EEPROM_PAGE_BAR1) ==
410183859Syongari		    (fup & (JME_EEPROM_FUNC_MASK | JME_EEPROM_PAGE_MASK))) {
411179337Syongari			if (jme_eeprom_read_byte(sc, offset + 1, &reg) != 0)
412179337Syongari				break;
413179337Syongari			if (reg >= JME_PAR0 &&
414179337Syongari			    reg < JME_PAR0 + ETHER_ADDR_LEN) {
415179337Syongari				if (jme_eeprom_read_byte(sc, offset + 2,
416179337Syongari				    &val) != 0)
417179337Syongari					break;
418179337Syongari				eaddr[reg - JME_PAR0] = val;
419179337Syongari				match++;
420179337Syongari			}
421179337Syongari		}
422183859Syongari		/* Check for the end of EEPROM descriptor. */
423183859Syongari		if ((fup & JME_EEPROM_DESC_END) == JME_EEPROM_DESC_END)
424183859Syongari			break;
425179337Syongari		/* Try next eeprom descriptor. */
426179337Syongari		offset += JME_EEPROM_DESC_BYTES;
427179337Syongari	} while (match != ETHER_ADDR_LEN && offset < JME_EEPROM_END);
428179337Syongari
429179337Syongari	if (match == ETHER_ADDR_LEN) {
430179337Syongari		bcopy(eaddr, sc->jme_eaddr, ETHER_ADDR_LEN);
431179337Syongari		return (0);
432179337Syongari	}
433179337Syongari
434179337Syongari	return (ENOENT);
435179337Syongari}
436179337Syongari
437216551Syongaristatic int
438216551Syongarijme_efuse_macaddr(struct jme_softc *sc)
439216551Syongari{
440216551Syongari	uint32_t reg;
441216551Syongari	int i;
442216551Syongari
443216551Syongari	reg = pci_read_config(sc->jme_dev, JME_EFUSE_CTL1, 4);
444216551Syongari	if ((reg & (EFUSE_CTL1_AUTOLOAD_ERR | EFUSE_CTL1_AUTOLAOD_DONE)) !=
445216551Syongari	    EFUSE_CTL1_AUTOLAOD_DONE)
446216551Syongari		return (ENOENT);
447216551Syongari	/* Reset eFuse controller. */
448216551Syongari	reg = pci_read_config(sc->jme_dev, JME_EFUSE_CTL2, 4);
449216551Syongari	reg |= EFUSE_CTL2_RESET;
450216551Syongari	pci_write_config(sc->jme_dev, JME_EFUSE_CTL2, reg, 4);
451216551Syongari	reg = pci_read_config(sc->jme_dev, JME_EFUSE_CTL2, 4);
452216551Syongari	reg &= ~EFUSE_CTL2_RESET;
453216551Syongari	pci_write_config(sc->jme_dev, JME_EFUSE_CTL2, reg, 4);
454216551Syongari
455216551Syongari	/* Have eFuse reload station address to MAC controller. */
456216551Syongari	reg = pci_read_config(sc->jme_dev, JME_EFUSE_CTL1, 4);
457216551Syongari	reg &= ~EFUSE_CTL1_CMD_MASK;
458216551Syongari	reg |= EFUSE_CTL1_CMD_AUTOLOAD | EFUSE_CTL1_EXECUTE;
459216551Syongari	pci_write_config(sc->jme_dev, JME_EFUSE_CTL1, reg, 4);
460216551Syongari
461216551Syongari	/*
462216551Syongari	 * Verify completion of eFuse autload command.  It should be
463216551Syongari	 * completed within 108us.
464216551Syongari	 */
465216551Syongari	DELAY(110);
466216551Syongari	for (i = 10; i > 0; i--) {
467216551Syongari		reg = pci_read_config(sc->jme_dev, JME_EFUSE_CTL1, 4);
468216551Syongari		if ((reg & (EFUSE_CTL1_AUTOLOAD_ERR |
469216551Syongari		    EFUSE_CTL1_AUTOLAOD_DONE)) != EFUSE_CTL1_AUTOLAOD_DONE) {
470216551Syongari			DELAY(20);
471216551Syongari			continue;
472216551Syongari		}
473216551Syongari		if ((reg & EFUSE_CTL1_EXECUTE) == 0)
474216551Syongari			break;
475216551Syongari		/* Station address loading is still in progress. */
476216551Syongari		DELAY(20);
477216551Syongari	}
478216551Syongari	if (i == 0) {
479216551Syongari		device_printf(sc->jme_dev, "eFuse autoload timed out.\n");
480216551Syongari		return (ETIMEDOUT);
481216551Syongari	}
482216551Syongari
483216551Syongari	return (0);
484216551Syongari}
485216551Syongari
486179337Syongaristatic void
487179337Syongarijme_reg_macaddr(struct jme_softc *sc)
488179337Syongari{
489179337Syongari	uint32_t par0, par1;
490179337Syongari
491179337Syongari	/* Read station address. */
492179337Syongari	par0 = CSR_READ_4(sc, JME_PAR0);
493179337Syongari	par1 = CSR_READ_4(sc, JME_PAR1);
494179337Syongari	par1 &= 0xFFFF;
495179337Syongari	if ((par0 == 0 && par1 == 0) ||
496179337Syongari	    (par0 == 0xFFFFFFFF && par1 == 0xFFFF)) {
497179337Syongari		device_printf(sc->jme_dev,
498201781Sgavin		    "Failed to retrieve Ethernet address.\n");
499179337Syongari	} else {
500216551Syongari		/*
501216551Syongari		 * For controllers that use eFuse, the station address
502216551Syongari		 * could also be extracted from JME_PCI_PAR0 and
503216551Syongari		 * JME_PCI_PAR1 registers in PCI configuration space.
504216551Syongari		 * Each register holds exactly half of station address(24bits)
505216551Syongari		 * so use JME_PAR0, JME_PAR1 registers instead.
506216551Syongari		 */
507179337Syongari		sc->jme_eaddr[0] = (par0 >> 0) & 0xFF;
508179337Syongari		sc->jme_eaddr[1] = (par0 >> 8) & 0xFF;
509179337Syongari		sc->jme_eaddr[2] = (par0 >> 16) & 0xFF;
510179337Syongari		sc->jme_eaddr[3] = (par0 >> 24) & 0xFF;
511179337Syongari		sc->jme_eaddr[4] = (par1 >> 0) & 0xFF;
512179337Syongari		sc->jme_eaddr[5] = (par1 >> 8) & 0xFF;
513179337Syongari	}
514179337Syongari}
515179337Syongari
516179337Syongaristatic void
517216551Syongarijme_set_macaddr(struct jme_softc *sc, uint8_t *eaddr)
518216551Syongari{
519216551Syongari	uint32_t val;
520216551Syongari	int i;
521216551Syongari
522216551Syongari	if ((sc->jme_flags & JME_FLAG_EFUSE) != 0) {
523216551Syongari		/*
524216551Syongari		 * Avoid reprogramming station address if the address
525216551Syongari		 * is the same as previous one.  Note, reprogrammed
526216551Syongari		 * station address is permanent as if it was written
527216551Syongari		 * to EEPROM. So if station address was changed by
528216551Syongari		 * admistrator it's possible to lose factory configured
529216551Syongari		 * address when driver fails to restore its address.
530216551Syongari		 * (e.g. reboot or system crash)
531216551Syongari		 */
532216551Syongari		if (bcmp(eaddr, sc->jme_eaddr, ETHER_ADDR_LEN) != 0) {
533216551Syongari			for (i = 0; i < ETHER_ADDR_LEN; i++) {
534216551Syongari				val = JME_EFUSE_EEPROM_FUNC0 <<
535216551Syongari				    JME_EFUSE_EEPROM_FUNC_SHIFT;
536216551Syongari				val |= JME_EFUSE_EEPROM_PAGE_BAR1 <<
537216551Syongari				    JME_EFUSE_EEPROM_PAGE_SHIFT;
538216551Syongari				val |= (JME_PAR0 + i) <<
539216551Syongari				    JME_EFUSE_EEPROM_ADDR_SHIFT;
540216551Syongari				val |= eaddr[i] << JME_EFUSE_EEPROM_DATA_SHIFT;
541216551Syongari				pci_write_config(sc->jme_dev, JME_EFUSE_EEPROM,
542216551Syongari				    val | JME_EFUSE_EEPROM_WRITE, 4);
543216551Syongari			}
544216551Syongari		}
545216551Syongari	} else {
546216551Syongari		CSR_WRITE_4(sc, JME_PAR0,
547216551Syongari		    eaddr[3] << 24 | eaddr[2] << 16 | eaddr[1] << 8 | eaddr[0]);
548216551Syongari		CSR_WRITE_4(sc, JME_PAR1, eaddr[5] << 8 | eaddr[4]);
549216551Syongari	}
550216551Syongari}
551216551Syongari
552216551Syongaristatic void
553179337Syongarijme_map_intr_vector(struct jme_softc *sc)
554179337Syongari{
555179337Syongari	uint32_t map[MSINUM_NUM_INTR_SOURCE / JME_MSI_MESSAGES];
556179337Syongari
557179337Syongari	bzero(map, sizeof(map));
558179337Syongari
559179337Syongari	/* Map Tx interrupts source to MSI/MSIX vector 2. */
560179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ0_COMP)] =
561179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ0_COMP);
562179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ1_COMP)] |=
563179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ1_COMP);
564179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ2_COMP)] |=
565179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ2_COMP);
566179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ3_COMP)] |=
567179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ3_COMP);
568179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ4_COMP)] |=
569179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ4_COMP);
570179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ4_COMP)] |=
571179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ5_COMP);
572179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ6_COMP)] |=
573179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ6_COMP);
574179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ7_COMP)] |=
575179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ7_COMP);
576179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ_COAL)] |=
577179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ_COAL);
578179337Syongari	map[MSINUM_REG_INDEX(N_INTR_TXQ_COAL_TO)] |=
579179337Syongari	    MSINUM_INTR_SOURCE(2, N_INTR_TXQ_COAL_TO);
580179337Syongari
581179337Syongari	/* Map Rx interrupts source to MSI/MSIX vector 1. */
582179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ0_COMP)] =
583179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ0_COMP);
584179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ1_COMP)] =
585179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ1_COMP);
586179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ2_COMP)] =
587179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ2_COMP);
588179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ3_COMP)] =
589179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ3_COMP);
590179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ0_DESC_EMPTY)] =
591179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ0_DESC_EMPTY);
592179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ1_DESC_EMPTY)] =
593179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ1_DESC_EMPTY);
594179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ2_DESC_EMPTY)] =
595179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ2_DESC_EMPTY);
596179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ3_DESC_EMPTY)] =
597179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ3_DESC_EMPTY);
598179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ0_COAL)] =
599179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ0_COAL);
600179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ1_COAL)] =
601179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ1_COAL);
602179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ2_COAL)] =
603179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ2_COAL);
604179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ3_COAL)] =
605179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ3_COAL);
606179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ0_COAL_TO)] =
607179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ0_COAL_TO);
608179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ1_COAL_TO)] =
609179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ1_COAL_TO);
610179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ2_COAL_TO)] =
611179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ2_COAL_TO);
612179337Syongari	map[MSINUM_REG_INDEX(N_INTR_RXQ3_COAL_TO)] =
613179337Syongari	    MSINUM_INTR_SOURCE(1, N_INTR_RXQ3_COAL_TO);
614179337Syongari
615179337Syongari	/* Map all other interrupts source to MSI/MSIX vector 0. */
616179337Syongari	CSR_WRITE_4(sc, JME_MSINUM_BASE + sizeof(uint32_t) * 0, map[0]);
617179337Syongari	CSR_WRITE_4(sc, JME_MSINUM_BASE + sizeof(uint32_t) * 1, map[1]);
618179337Syongari	CSR_WRITE_4(sc, JME_MSINUM_BASE + sizeof(uint32_t) * 2, map[2]);
619179337Syongari	CSR_WRITE_4(sc, JME_MSINUM_BASE + sizeof(uint32_t) * 3, map[3]);
620179337Syongari}
621179337Syongari
622179337Syongaristatic int
623179337Syongarijme_attach(device_t dev)
624179337Syongari{
625179337Syongari	struct jme_softc *sc;
626179337Syongari	struct ifnet *ifp;
627179337Syongari	struct mii_softc *miisc;
628179337Syongari	struct mii_data *mii;
629179337Syongari	uint32_t reg;
630179337Syongari	uint16_t burst;
631216551Syongari	int error, i, mii_flags, msic, msixc, pmc;
632179337Syongari
633179337Syongari	error = 0;
634179337Syongari	sc = device_get_softc(dev);
635179337Syongari	sc->jme_dev = dev;
636179337Syongari
637179337Syongari	mtx_init(&sc->jme_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
638179337Syongari	    MTX_DEF);
639179337Syongari	callout_init_mtx(&sc->jme_tick_ch, &sc->jme_mtx, 0);
640179337Syongari	TASK_INIT(&sc->jme_int_task, 0, jme_int_task, sc);
641179337Syongari	TASK_INIT(&sc->jme_link_task, 0, jme_link_task, sc);
642179337Syongari
643179337Syongari	/*
644179337Syongari	 * Map the device. JMC250 supports both memory mapped and I/O
645179337Syongari	 * register space access. Because I/O register access should
646179337Syongari	 * use different BARs to access registers it's waste of time
647179337Syongari	 * to use I/O register spce access. JMC250 uses 16K to map
648179337Syongari	 * entire memory space.
649179337Syongari	 */
650179337Syongari	pci_enable_busmaster(dev);
651179337Syongari	sc->jme_res_spec = jme_res_spec_mem;
652179337Syongari	sc->jme_irq_spec = jme_irq_spec_legacy;
653179337Syongari	error = bus_alloc_resources(dev, sc->jme_res_spec, sc->jme_res);
654179337Syongari	if (error != 0) {
655179337Syongari		device_printf(dev, "cannot allocate memory resources.\n");
656179337Syongari		goto fail;
657179337Syongari	}
658179337Syongari
659179337Syongari	/* Allocate IRQ resources. */
660179337Syongari	msixc = pci_msix_count(dev);
661179337Syongari	msic = pci_msi_count(dev);
662179337Syongari	if (bootverbose) {
663179337Syongari		device_printf(dev, "MSIX count : %d\n", msixc);
664179337Syongari		device_printf(dev, "MSI count : %d\n", msic);
665179337Syongari	}
666179337Syongari
667215848Syongari	/* Use 1 MSI/MSI-X. */
668215848Syongari	if (msixc > 1)
669215848Syongari		msixc = 1;
670215848Syongari	if (msic > 1)
671215848Syongari		msic = 1;
672179337Syongari	/* Prefer MSIX over MSI. */
673179337Syongari	if (msix_disable == 0 || msi_disable == 0) {
674215848Syongari		if (msix_disable == 0 && msixc > 0 &&
675179337Syongari		    pci_alloc_msix(dev, &msixc) == 0) {
676215848Syongari			if (msixc == 1) {
677179337Syongari				device_printf(dev, "Using %d MSIX messages.\n",
678179337Syongari				    msixc);
679179337Syongari				sc->jme_flags |= JME_FLAG_MSIX;
680179337Syongari				sc->jme_irq_spec = jme_irq_spec_msi;
681179337Syongari			} else
682179337Syongari				pci_release_msi(dev);
683179337Syongari		}
684179337Syongari		if (msi_disable == 0 && (sc->jme_flags & JME_FLAG_MSIX) == 0 &&
685215848Syongari		    msic > 0 && pci_alloc_msi(dev, &msic) == 0) {
686215848Syongari			if (msic == 1) {
687179337Syongari				device_printf(dev, "Using %d MSI messages.\n",
688179337Syongari				    msic);
689179337Syongari				sc->jme_flags |= JME_FLAG_MSI;
690179337Syongari				sc->jme_irq_spec = jme_irq_spec_msi;
691179337Syongari			} else
692179337Syongari				pci_release_msi(dev);
693179337Syongari		}
694179337Syongari		/* Map interrupt vector 0, 1 and 2. */
695179337Syongari		if ((sc->jme_flags & JME_FLAG_MSI) != 0 ||
696179337Syongari		    (sc->jme_flags & JME_FLAG_MSIX) != 0)
697179337Syongari			jme_map_intr_vector(sc);
698179337Syongari	}
699179337Syongari
700179337Syongari	error = bus_alloc_resources(dev, sc->jme_irq_spec, sc->jme_irq);
701179337Syongari	if (error != 0) {
702179337Syongari		device_printf(dev, "cannot allocate IRQ resources.\n");
703179337Syongari		goto fail;
704179337Syongari	}
705179337Syongari
706183814Syongari	sc->jme_rev = pci_get_device(dev);
707183814Syongari	if ((sc->jme_rev & DEVICEID_JMC2XX_MASK) == DEVICEID_JMC260) {
708179337Syongari		sc->jme_flags |= JME_FLAG_FASTETH;
709179337Syongari		sc->jme_flags |= JME_FLAG_NOJUMBO;
710179337Syongari	}
711179337Syongari	reg = CSR_READ_4(sc, JME_CHIPMODE);
712179337Syongari	sc->jme_chip_rev = (reg & CHIPMODE_REV_MASK) >> CHIPMODE_REV_SHIFT;
713179337Syongari	if (((reg & CHIPMODE_FPGA_REV_MASK) >> CHIPMODE_FPGA_REV_SHIFT) !=
714179337Syongari	    CHIPMODE_NOT_FPGA)
715179337Syongari		sc->jme_flags |= JME_FLAG_FPGA;
716179337Syongari	if (bootverbose) {
717179337Syongari		device_printf(dev, "PCI device revision : 0x%04x\n",
718179337Syongari		    sc->jme_rev);
719179337Syongari		device_printf(dev, "Chip revision : 0x%02x\n",
720179337Syongari		    sc->jme_chip_rev);
721179337Syongari		if ((sc->jme_flags & JME_FLAG_FPGA) != 0)
722179337Syongari			device_printf(dev, "FPGA revision : 0x%04x\n",
723179337Syongari			    (reg & CHIPMODE_FPGA_REV_MASK) >>
724179337Syongari			    CHIPMODE_FPGA_REV_SHIFT);
725179337Syongari	}
726179337Syongari	if (sc->jme_chip_rev == 0xFF) {
727179337Syongari		device_printf(dev, "Unknown chip revision : 0x%02x\n",
728179337Syongari		    sc->jme_rev);
729179337Syongari		error = ENXIO;
730179337Syongari		goto fail;
731179337Syongari	}
732179337Syongari
733216551Syongari	/* Identify controller features and bugs. */
734185596Syongari	if (CHIPMODE_REVFM(sc->jme_chip_rev) >= 2) {
735185596Syongari		if ((sc->jme_rev & DEVICEID_JMC2XX_MASK) == DEVICEID_JMC260 &&
736185596Syongari		    CHIPMODE_REVFM(sc->jme_chip_rev) == 2)
737185596Syongari			sc->jme_flags |= JME_FLAG_DMA32BIT;
738216551Syongari		if (CHIPMODE_REVFM(sc->jme_chip_rev) >= 5)
739216551Syongari			sc->jme_flags |= JME_FLAG_EFUSE | JME_FLAG_PCCPCD;
740216551Syongari		sc->jme_flags |= JME_FLAG_TXCLK | JME_FLAG_RXCLK;
741185597Syongari		sc->jme_flags |= JME_FLAG_HWMIB;
742185596Syongari	}
743185596Syongari
744179337Syongari	/* Reset the ethernet controller. */
745179337Syongari	jme_reset(sc);
746179337Syongari
747179337Syongari	/* Get station address. */
748216551Syongari	if ((sc->jme_flags & JME_FLAG_EFUSE) != 0) {
749216551Syongari		error = jme_efuse_macaddr(sc);
750216551Syongari		if (error == 0)
751216551Syongari			jme_reg_macaddr(sc);
752216551Syongari	} else {
753216551Syongari		error = ENOENT;
754216551Syongari		reg = CSR_READ_4(sc, JME_SMBCSR);
755216551Syongari		if ((reg & SMBCSR_EEPROM_PRESENT) != 0)
756216551Syongari			error = jme_eeprom_macaddr(sc);
757216551Syongari		if (error != 0 && bootverbose)
758179337Syongari			device_printf(sc->jme_dev,
759179337Syongari			    "ethernet hardware address not found in EEPROM.\n");
760216551Syongari		if (error != 0)
761216551Syongari			jme_reg_macaddr(sc);
762179337Syongari	}
763179337Syongari
764179337Syongari	/*
765179337Syongari	 * Save PHY address.
766179337Syongari	 * Integrated JR0211 has fixed PHY address whereas FPGA version
767179337Syongari	 * requires PHY probing to get correct PHY address.
768179337Syongari	 */
769179337Syongari	if ((sc->jme_flags & JME_FLAG_FPGA) == 0) {
770179337Syongari		sc->jme_phyaddr = CSR_READ_4(sc, JME_GPREG0) &
771179337Syongari		    GPREG0_PHY_ADDR_MASK;
772179337Syongari		if (bootverbose)
773179337Syongari			device_printf(dev, "PHY is at address %d.\n",
774179337Syongari			    sc->jme_phyaddr);
775179337Syongari	} else
776179337Syongari		sc->jme_phyaddr = 0;
777179337Syongari
778179337Syongari	/* Set max allowable DMA size. */
779219902Sjhb	if (pci_find_cap(dev, PCIY_EXPRESS, &i) == 0) {
780179337Syongari		sc->jme_flags |= JME_FLAG_PCIE;
781240680Sgavin		burst = pci_read_config(dev, i + PCIER_DEVICE_CTL, 2);
782179337Syongari		if (bootverbose) {
783179337Syongari			device_printf(dev, "Read request size : %d bytes.\n",
784179337Syongari			    128 << ((burst >> 12) & 0x07));
785179337Syongari			device_printf(dev, "TLP payload size : %d bytes.\n",
786179337Syongari			    128 << ((burst >> 5) & 0x07));
787179337Syongari		}
788179337Syongari		switch ((burst >> 12) & 0x07) {
789179337Syongari		case 0:
790179337Syongari			sc->jme_tx_dma_size = TXCSR_DMA_SIZE_128;
791179337Syongari			break;
792179337Syongari		case 1:
793179337Syongari			sc->jme_tx_dma_size = TXCSR_DMA_SIZE_256;
794179337Syongari			break;
795179337Syongari		default:
796179337Syongari			sc->jme_tx_dma_size = TXCSR_DMA_SIZE_512;
797179337Syongari			break;
798179337Syongari		}
799179337Syongari		sc->jme_rx_dma_size = RXCSR_DMA_SIZE_128;
800179337Syongari	} else {
801179337Syongari		sc->jme_tx_dma_size = TXCSR_DMA_SIZE_512;
802179337Syongari		sc->jme_rx_dma_size = RXCSR_DMA_SIZE_128;
803179337Syongari	}
804179337Syongari	/* Create coalescing sysctl node. */
805179337Syongari	jme_sysctl_node(sc);
806295735Syongari	if ((error = jme_dma_alloc(sc)) != 0)
807179337Syongari		goto fail;
808179337Syongari
809179337Syongari	ifp = sc->jme_ifp = if_alloc(IFT_ETHER);
810179337Syongari	if (ifp == NULL) {
811179337Syongari		device_printf(dev, "cannot allocate ifnet structure.\n");
812179337Syongari		error = ENXIO;
813179337Syongari		goto fail;
814179337Syongari	}
815179337Syongari
816179337Syongari	ifp->if_softc = sc;
817179337Syongari	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
818179337Syongari	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
819179337Syongari	ifp->if_ioctl = jme_ioctl;
820179337Syongari	ifp->if_start = jme_start;
821179337Syongari	ifp->if_init = jme_init;
822179337Syongari	ifp->if_snd.ifq_drv_maxlen = JME_TX_RING_CNT - 1;
823179337Syongari	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
824179337Syongari	IFQ_SET_READY(&ifp->if_snd);
825179337Syongari	/* JMC250 supports Tx/Rx checksum offload as well as TSO. */
826179337Syongari	ifp->if_capabilities = IFCAP_HWCSUM | IFCAP_TSO4;
827179337Syongari	ifp->if_hwassist = JME_CSUM_FEATURES | CSUM_TSO;
828219902Sjhb	if (pci_find_cap(dev, PCIY_PMG, &pmc) == 0) {
829179337Syongari		sc->jme_flags |= JME_FLAG_PMCAP;
830179337Syongari		ifp->if_capabilities |= IFCAP_WOL_MAGIC;
831179337Syongari	}
832179337Syongari	ifp->if_capenable = ifp->if_capabilities;
833179337Syongari
834216551Syongari	/* Wakeup PHY. */
835216551Syongari	jme_phy_up(sc);
836216551Syongari	mii_flags = MIIF_DOPAUSE;
837216551Syongari	/* Ask PHY calibration to PHY driver. */
838216551Syongari	if (CHIPMODE_REVFM(sc->jme_chip_rev) >= 5)
839216551Syongari		mii_flags |= MIIF_MACPRIV0;
840179337Syongari	/* Set up MII bus. */
841213893Smarius	error = mii_attach(dev, &sc->jme_miibus, ifp, jme_mediachange,
842216548Syongari	    jme_mediastatus, BMSR_DEFCAPMASK,
843216548Syongari	    sc->jme_flags & JME_FLAG_FPGA ? MII_PHY_ANY : sc->jme_phyaddr,
844216551Syongari	    MII_OFFSET_ANY, mii_flags);
845213893Smarius	if (error != 0) {
846213893Smarius		device_printf(dev, "attaching PHYs failed\n");
847179337Syongari		goto fail;
848179337Syongari	}
849179337Syongari
850179337Syongari	/*
851179337Syongari	 * Force PHY to FPGA mode.
852179337Syongari	 */
853179337Syongari	if ((sc->jme_flags & JME_FLAG_FPGA) != 0) {
854179337Syongari		mii = device_get_softc(sc->jme_miibus);
855179337Syongari		if (mii->mii_instance != 0) {
856179337Syongari			LIST_FOREACH(miisc, &mii->mii_phys, mii_list) {
857179337Syongari				if (miisc->mii_phy != 0) {
858179337Syongari					sc->jme_phyaddr = miisc->mii_phy;
859179337Syongari					break;
860179337Syongari				}
861179337Syongari			}
862179337Syongari			if (sc->jme_phyaddr != 0) {
863179337Syongari				device_printf(sc->jme_dev,
864179337Syongari				    "FPGA PHY is at %d\n", sc->jme_phyaddr);
865179337Syongari				/* vendor magic. */
866179337Syongari				jme_miibus_writereg(dev, sc->jme_phyaddr, 27,
867179337Syongari				    0x0004);
868179337Syongari			}
869179337Syongari		}
870179337Syongari	}
871179337Syongari
872179337Syongari	ether_ifattach(ifp, sc->jme_eaddr);
873179337Syongari
874179337Syongari	/* VLAN capability setup */
875179337Syongari	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWTAGGING |
876204225Syongari	    IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTSO;
877179337Syongari	ifp->if_capenable = ifp->if_capabilities;
878179337Syongari
879179337Syongari	/* Tell the upper layer(s) we support long frames. */
880270856Sglebius	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
881179337Syongari
882179337Syongari	/* Create local taskq. */
883179337Syongari	sc->jme_tq = taskqueue_create_fast("jme_taskq", M_WAITOK,
884179337Syongari	    taskqueue_thread_enqueue, &sc->jme_tq);
885179337Syongari	if (sc->jme_tq == NULL) {
886179337Syongari		device_printf(dev, "could not create taskqueue.\n");
887179337Syongari		ether_ifdetach(ifp);
888179337Syongari		error = ENXIO;
889179337Syongari		goto fail;
890179337Syongari	}
891179337Syongari	taskqueue_start_threads(&sc->jme_tq, 1, PI_NET, "%s taskq",
892179337Syongari	    device_get_nameunit(sc->jme_dev));
893179337Syongari
894215848Syongari	for (i = 0; i < 1; i++) {
895179337Syongari		error = bus_setup_intr(dev, sc->jme_irq[i],
896179337Syongari		    INTR_TYPE_NET | INTR_MPSAFE, jme_intr, NULL, sc,
897179337Syongari		    &sc->jme_intrhand[i]);
898179337Syongari		if (error != 0)
899179337Syongari			break;
900179337Syongari	}
901179337Syongari
902179337Syongari	if (error != 0) {
903179337Syongari		device_printf(dev, "could not set up interrupt handler.\n");
904179337Syongari		taskqueue_free(sc->jme_tq);
905179337Syongari		sc->jme_tq = NULL;
906179337Syongari		ether_ifdetach(ifp);
907179337Syongari		goto fail;
908179337Syongari	}
909179337Syongari
910179337Syongarifail:
911179337Syongari	if (error != 0)
912179337Syongari		jme_detach(dev);
913179337Syongari
914179337Syongari	return (error);
915179337Syongari}
916179337Syongari
917179337Syongaristatic int
918179337Syongarijme_detach(device_t dev)
919179337Syongari{
920179337Syongari	struct jme_softc *sc;
921179337Syongari	struct ifnet *ifp;
922215848Syongari	int i;
923179337Syongari
924179337Syongari	sc = device_get_softc(dev);
925179337Syongari
926179337Syongari	ifp = sc->jme_ifp;
927179337Syongari	if (device_is_attached(dev)) {
928179337Syongari		JME_LOCK(sc);
929179337Syongari		sc->jme_flags |= JME_FLAG_DETACH;
930179337Syongari		jme_stop(sc);
931179337Syongari		JME_UNLOCK(sc);
932179337Syongari		callout_drain(&sc->jme_tick_ch);
933179337Syongari		taskqueue_drain(sc->jme_tq, &sc->jme_int_task);
934179337Syongari		taskqueue_drain(taskqueue_swi, &sc->jme_link_task);
935216551Syongari		/* Restore possibly modified station address. */
936216551Syongari		if ((sc->jme_flags & JME_FLAG_EFUSE) != 0)
937216551Syongari			jme_set_macaddr(sc, sc->jme_eaddr);
938179337Syongari		ether_ifdetach(ifp);
939179337Syongari	}
940179337Syongari
941179337Syongari	if (sc->jme_tq != NULL) {
942179337Syongari		taskqueue_drain(sc->jme_tq, &sc->jme_int_task);
943179337Syongari		taskqueue_free(sc->jme_tq);
944179337Syongari		sc->jme_tq = NULL;
945179337Syongari	}
946179337Syongari
947179337Syongari	if (sc->jme_miibus != NULL) {
948179337Syongari		device_delete_child(dev, sc->jme_miibus);
949179337Syongari		sc->jme_miibus = NULL;
950179337Syongari	}
951179337Syongari	bus_generic_detach(dev);
952179337Syongari	jme_dma_free(sc);
953179337Syongari
954179337Syongari	if (ifp != NULL) {
955179337Syongari		if_free(ifp);
956179337Syongari		sc->jme_ifp = NULL;
957179337Syongari	}
958179337Syongari
959215848Syongari	for (i = 0; i < 1; i++) {
960179337Syongari		if (sc->jme_intrhand[i] != NULL) {
961179337Syongari			bus_teardown_intr(dev, sc->jme_irq[i],
962179337Syongari			    sc->jme_intrhand[i]);
963179337Syongari			sc->jme_intrhand[i] = NULL;
964179337Syongari		}
965179337Syongari	}
966179337Syongari
967216549Syongari	if (sc->jme_irq[0] != NULL)
968216549Syongari		bus_release_resources(dev, sc->jme_irq_spec, sc->jme_irq);
969179337Syongari	if ((sc->jme_flags & (JME_FLAG_MSIX | JME_FLAG_MSI)) != 0)
970179337Syongari		pci_release_msi(dev);
971216549Syongari	if (sc->jme_res[0] != NULL)
972216549Syongari		bus_release_resources(dev, sc->jme_res_spec, sc->jme_res);
973179337Syongari	mtx_destroy(&sc->jme_mtx);
974179337Syongari
975179337Syongari	return (0);
976179337Syongari}
977179337Syongari
978185597Syongari#define	JME_SYSCTL_STAT_ADD32(c, h, n, p, d)	\
979185597Syongari	    SYSCTL_ADD_UINT(c, h, OID_AUTO, n, CTLFLAG_RD, p, 0, d)
980185597Syongari
981179337Syongaristatic void
982179337Syongarijme_sysctl_node(struct jme_softc *sc)
983179337Syongari{
984185597Syongari	struct sysctl_ctx_list *ctx;
985185597Syongari	struct sysctl_oid_list *child, *parent;
986185597Syongari	struct sysctl_oid *tree;
987185597Syongari	struct jme_hw_stats *stats;
988179337Syongari	int error;
989179337Syongari
990185597Syongari	stats = &sc->jme_stats;
991185597Syongari	ctx = device_get_sysctl_ctx(sc->jme_dev);
992185597Syongari	child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev));
993179337Syongari
994185597Syongari	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_coal_to",
995185597Syongari	    CTLTYPE_INT | CTLFLAG_RW, &sc->jme_tx_coal_to, 0,
996185597Syongari	    sysctl_hw_jme_tx_coal_to, "I", "jme tx coalescing timeout");
997179337Syongari
998185597Syongari	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_coal_pkt",
999185597Syongari	    CTLTYPE_INT | CTLFLAG_RW, &sc->jme_tx_coal_pkt, 0,
1000185597Syongari	    sysctl_hw_jme_tx_coal_pkt, "I", "jme tx coalescing packet");
1001179337Syongari
1002185597Syongari	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_coal_to",
1003185597Syongari	    CTLTYPE_INT | CTLFLAG_RW, &sc->jme_rx_coal_to, 0,
1004185597Syongari	    sysctl_hw_jme_rx_coal_to, "I", "jme rx coalescing timeout");
1005179337Syongari
1006185597Syongari	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_coal_pkt",
1007185597Syongari	    CTLTYPE_INT | CTLFLAG_RW, &sc->jme_rx_coal_pkt, 0,
1008185597Syongari	    sysctl_hw_jme_rx_coal_pkt, "I", "jme rx coalescing packet");
1009185597Syongari
1010185597Syongari	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "process_limit",
1011185597Syongari	    CTLTYPE_INT | CTLFLAG_RW, &sc->jme_process_limit, 0,
1012185597Syongari	    sysctl_hw_jme_proc_limit, "I",
1013179337Syongari	    "max number of Rx events to process");
1014179337Syongari
1015179337Syongari	/* Pull in device tunables. */
1016179337Syongari	sc->jme_process_limit = JME_PROC_DEFAULT;
1017179337Syongari	error = resource_int_value(device_get_name(sc->jme_dev),
1018179337Syongari	    device_get_unit(sc->jme_dev), "process_limit",
1019179337Syongari	    &sc->jme_process_limit);
1020179337Syongari	if (error == 0) {
1021179337Syongari		if (sc->jme_process_limit < JME_PROC_MIN ||
1022179337Syongari		    sc->jme_process_limit > JME_PROC_MAX) {
1023179337Syongari			device_printf(sc->jme_dev,
1024179337Syongari			    "process_limit value out of range; "
1025179337Syongari			    "using default: %d\n", JME_PROC_DEFAULT);
1026179337Syongari			sc->jme_process_limit = JME_PROC_DEFAULT;
1027179337Syongari		}
1028179337Syongari	}
1029179337Syongari
1030179337Syongari	sc->jme_tx_coal_to = PCCTX_COAL_TO_DEFAULT;
1031179337Syongari	error = resource_int_value(device_get_name(sc->jme_dev),
1032179337Syongari	    device_get_unit(sc->jme_dev), "tx_coal_to", &sc->jme_tx_coal_to);
1033179337Syongari	if (error == 0) {
1034179337Syongari		if (sc->jme_tx_coal_to < PCCTX_COAL_TO_MIN ||
1035179337Syongari		    sc->jme_tx_coal_to > PCCTX_COAL_TO_MAX) {
1036179337Syongari			device_printf(sc->jme_dev,
1037179337Syongari			    "tx_coal_to value out of range; "
1038179337Syongari			    "using default: %d\n", PCCTX_COAL_TO_DEFAULT);
1039179337Syongari			sc->jme_tx_coal_to = PCCTX_COAL_TO_DEFAULT;
1040179337Syongari		}
1041179337Syongari	}
1042179337Syongari
1043179337Syongari	sc->jme_tx_coal_pkt = PCCTX_COAL_PKT_DEFAULT;
1044179337Syongari	error = resource_int_value(device_get_name(sc->jme_dev),
1045179337Syongari	    device_get_unit(sc->jme_dev), "tx_coal_pkt", &sc->jme_tx_coal_to);
1046179337Syongari	if (error == 0) {
1047179337Syongari		if (sc->jme_tx_coal_pkt < PCCTX_COAL_PKT_MIN ||
1048179337Syongari		    sc->jme_tx_coal_pkt > PCCTX_COAL_PKT_MAX) {
1049179337Syongari			device_printf(sc->jme_dev,
1050179337Syongari			    "tx_coal_pkt value out of range; "
1051179337Syongari			    "using default: %d\n", PCCTX_COAL_PKT_DEFAULT);
1052179337Syongari			sc->jme_tx_coal_pkt = PCCTX_COAL_PKT_DEFAULT;
1053179337Syongari		}
1054179337Syongari	}
1055179337Syongari
1056179337Syongari	sc->jme_rx_coal_to = PCCRX_COAL_TO_DEFAULT;
1057179337Syongari	error = resource_int_value(device_get_name(sc->jme_dev),
1058179337Syongari	    device_get_unit(sc->jme_dev), "rx_coal_to", &sc->jme_rx_coal_to);
1059179337Syongari	if (error == 0) {
1060179337Syongari		if (sc->jme_rx_coal_to < PCCRX_COAL_TO_MIN ||
1061179337Syongari		    sc->jme_rx_coal_to > PCCRX_COAL_TO_MAX) {
1062179337Syongari			device_printf(sc->jme_dev,
1063179337Syongari			    "rx_coal_to value out of range; "
1064179337Syongari			    "using default: %d\n", PCCRX_COAL_TO_DEFAULT);
1065179337Syongari			sc->jme_rx_coal_to = PCCRX_COAL_TO_DEFAULT;
1066179337Syongari		}
1067179337Syongari	}
1068179337Syongari
1069179337Syongari	sc->jme_rx_coal_pkt = PCCRX_COAL_PKT_DEFAULT;
1070179337Syongari	error = resource_int_value(device_get_name(sc->jme_dev),
1071179337Syongari	    device_get_unit(sc->jme_dev), "rx_coal_pkt", &sc->jme_rx_coal_to);
1072179337Syongari	if (error == 0) {
1073179337Syongari		if (sc->jme_rx_coal_pkt < PCCRX_COAL_PKT_MIN ||
1074179337Syongari		    sc->jme_rx_coal_pkt > PCCRX_COAL_PKT_MAX) {
1075179337Syongari			device_printf(sc->jme_dev,
1076179337Syongari			    "tx_coal_pkt value out of range; "
1077179337Syongari			    "using default: %d\n", PCCRX_COAL_PKT_DEFAULT);
1078179337Syongari			sc->jme_rx_coal_pkt = PCCRX_COAL_PKT_DEFAULT;
1079179337Syongari		}
1080179337Syongari	}
1081185597Syongari
1082185597Syongari	if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
1083185597Syongari		return;
1084185597Syongari
1085185597Syongari	tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
1086185597Syongari	    NULL, "JME statistics");
1087185597Syongari	parent = SYSCTL_CHILDREN(tree);
1088185597Syongari
1089185597Syongari	/* Rx statistics. */
1090185597Syongari	tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "rx", CTLFLAG_RD,
1091185597Syongari	    NULL, "Rx MAC statistics");
1092185597Syongari	child = SYSCTL_CHILDREN(tree);
1093185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "good_frames",
1094185597Syongari	    &stats->rx_good_frames, "Good frames");
1095185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "crc_errs",
1096185597Syongari	    &stats->rx_crc_errs, "CRC errors");
1097185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "mii_errs",
1098185597Syongari	    &stats->rx_mii_errs, "MII errors");
1099185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "fifo_oflows",
1100185597Syongari	    &stats->rx_fifo_oflows, "FIFO overflows");
1101185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "desc_empty",
1102185597Syongari	    &stats->rx_desc_empty, "Descriptor empty");
1103185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "bad_frames",
1104185597Syongari	    &stats->rx_bad_frames, "Bad frames");
1105185597Syongari
1106185597Syongari	/* Tx statistics. */
1107185597Syongari	tree = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "tx", CTLFLAG_RD,
1108185597Syongari	    NULL, "Tx MAC statistics");
1109185597Syongari	child = SYSCTL_CHILDREN(tree);
1110185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "good_frames",
1111185597Syongari	    &stats->tx_good_frames, "Good frames");
1112185597Syongari	JME_SYSCTL_STAT_ADD32(ctx, child, "bad_frames",
1113185597Syongari	    &stats->tx_bad_frames, "Bad frames");
1114179337Syongari}
1115179337Syongari
1116185597Syongari#undef	JME_SYSCTL_STAT_ADD32
1117185597Syongari
1118179337Syongaristruct jme_dmamap_arg {
1119179337Syongari	bus_addr_t	jme_busaddr;
1120179337Syongari};
1121179337Syongari
1122179337Syongaristatic void
1123179337Syongarijme_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
1124179337Syongari{
1125179337Syongari	struct jme_dmamap_arg *ctx;
1126179337Syongari
1127179337Syongari	if (error != 0)
1128179337Syongari		return;
1129179337Syongari
1130179337Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
1131179337Syongari
1132179337Syongari	ctx = (struct jme_dmamap_arg *)arg;
1133179337Syongari	ctx->jme_busaddr = segs[0].ds_addr;
1134179337Syongari}
1135179337Syongari
1136179337Syongaristatic int
1137179337Syongarijme_dma_alloc(struct jme_softc *sc)
1138179337Syongari{
1139179337Syongari	struct jme_dmamap_arg ctx;
1140179337Syongari	struct jme_txdesc *txd;
1141179337Syongari	struct jme_rxdesc *rxd;
1142179337Syongari	bus_addr_t lowaddr, rx_ring_end, tx_ring_end;
1143179337Syongari	int error, i;
1144179337Syongari
1145179337Syongari	lowaddr = BUS_SPACE_MAXADDR;
1146185596Syongari	if ((sc->jme_flags & JME_FLAG_DMA32BIT) != 0)
1147185596Syongari		lowaddr = BUS_SPACE_MAXADDR_32BIT;
1148179337Syongari
1149179337Syongariagain:
1150179337Syongari	/* Create parent ring tag. */
1151179337Syongari	error = bus_dma_tag_create(bus_get_dma_tag(sc->jme_dev),/* parent */
1152179337Syongari	    1, 0,			/* algnmnt, boundary */
1153179337Syongari	    lowaddr,			/* lowaddr */
1154179337Syongari	    BUS_SPACE_MAXADDR,		/* highaddr */
1155179337Syongari	    NULL, NULL,			/* filter, filterarg */
1156179337Syongari	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsize */
1157179337Syongari	    0,				/* nsegments */
1158179337Syongari	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
1159179337Syongari	    0,				/* flags */
1160179337Syongari	    NULL, NULL,			/* lockfunc, lockarg */
1161179337Syongari	    &sc->jme_cdata.jme_ring_tag);
1162179337Syongari	if (error != 0) {
1163179337Syongari		device_printf(sc->jme_dev,
1164179337Syongari		    "could not create parent ring DMA tag.\n");
1165179337Syongari		goto fail;
1166179337Syongari	}
1167179337Syongari	/* Create tag for Tx ring. */
1168179337Syongari	error = bus_dma_tag_create(sc->jme_cdata.jme_ring_tag,/* parent */
1169179337Syongari	    JME_TX_RING_ALIGN, 0,	/* algnmnt, boundary */
1170179337Syongari	    BUS_SPACE_MAXADDR,		/* lowaddr */
1171179337Syongari	    BUS_SPACE_MAXADDR,		/* highaddr */
1172179337Syongari	    NULL, NULL,			/* filter, filterarg */
1173179337Syongari	    JME_TX_RING_SIZE,		/* maxsize */
1174179337Syongari	    1,				/* nsegments */
1175179337Syongari	    JME_TX_RING_SIZE,		/* maxsegsize */
1176179337Syongari	    0,				/* flags */
1177179337Syongari	    NULL, NULL,			/* lockfunc, lockarg */
1178179337Syongari	    &sc->jme_cdata.jme_tx_ring_tag);
1179179337Syongari	if (error != 0) {
1180179337Syongari		device_printf(sc->jme_dev,
1181179337Syongari		    "could not allocate Tx ring DMA tag.\n");
1182179337Syongari		goto fail;
1183179337Syongari	}
1184179337Syongari
1185179337Syongari	/* Create tag for Rx ring. */
1186179337Syongari	error = bus_dma_tag_create(sc->jme_cdata.jme_ring_tag,/* parent */
1187179337Syongari	    JME_RX_RING_ALIGN, 0,	/* algnmnt, boundary */
1188179337Syongari	    lowaddr,			/* lowaddr */
1189179337Syongari	    BUS_SPACE_MAXADDR,		/* highaddr */
1190179337Syongari	    NULL, NULL,			/* filter, filterarg */
1191179337Syongari	    JME_RX_RING_SIZE,		/* maxsize */
1192179337Syongari	    1,				/* nsegments */
1193179337Syongari	    JME_RX_RING_SIZE,		/* maxsegsize */
1194179337Syongari	    0,				/* flags */
1195179337Syongari	    NULL, NULL,			/* lockfunc, lockarg */
1196179337Syongari	    &sc->jme_cdata.jme_rx_ring_tag);
1197179337Syongari	if (error != 0) {
1198179337Syongari		device_printf(sc->jme_dev,
1199179337Syongari		    "could not allocate Rx ring DMA tag.\n");
1200179337Syongari		goto fail;
1201179337Syongari	}
1202179337Syongari
1203179337Syongari	/* Allocate DMA'able memory and load the DMA map for Tx ring. */
1204179337Syongari	error = bus_dmamem_alloc(sc->jme_cdata.jme_tx_ring_tag,
1205179337Syongari	    (void **)&sc->jme_rdata.jme_tx_ring,
1206179337Syongari	    BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_COHERENT,
1207179337Syongari	    &sc->jme_cdata.jme_tx_ring_map);
1208179337Syongari	if (error != 0) {
1209179337Syongari		device_printf(sc->jme_dev,
1210179337Syongari		    "could not allocate DMA'able memory for Tx ring.\n");
1211179337Syongari		goto fail;
1212179337Syongari	}
1213179337Syongari
1214179337Syongari	ctx.jme_busaddr = 0;
1215179337Syongari	error = bus_dmamap_load(sc->jme_cdata.jme_tx_ring_tag,
1216179337Syongari	    sc->jme_cdata.jme_tx_ring_map, sc->jme_rdata.jme_tx_ring,
1217179337Syongari	    JME_TX_RING_SIZE, jme_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
1218179337Syongari	if (error != 0 || ctx.jme_busaddr == 0) {
1219179337Syongari		device_printf(sc->jme_dev,
1220179337Syongari		    "could not load DMA'able memory for Tx ring.\n");
1221179337Syongari		goto fail;
1222179337Syongari	}
1223179337Syongari	sc->jme_rdata.jme_tx_ring_paddr = ctx.jme_busaddr;
1224179337Syongari
1225179337Syongari	/* Allocate DMA'able memory and load the DMA map for Rx ring. */
1226179337Syongari	error = bus_dmamem_alloc(sc->jme_cdata.jme_rx_ring_tag,
1227179337Syongari	    (void **)&sc->jme_rdata.jme_rx_ring,
1228179337Syongari	    BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_COHERENT,
1229179337Syongari	    &sc->jme_cdata.jme_rx_ring_map);
1230179337Syongari	if (error != 0) {
1231179337Syongari		device_printf(sc->jme_dev,
1232179337Syongari		    "could not allocate DMA'able memory for Rx ring.\n");
1233179337Syongari		goto fail;
1234179337Syongari	}
1235179337Syongari
1236179337Syongari	ctx.jme_busaddr = 0;
1237179337Syongari	error = bus_dmamap_load(sc->jme_cdata.jme_rx_ring_tag,
1238179337Syongari	    sc->jme_cdata.jme_rx_ring_map, sc->jme_rdata.jme_rx_ring,
1239179337Syongari	    JME_RX_RING_SIZE, jme_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
1240179337Syongari	if (error != 0 || ctx.jme_busaddr == 0) {
1241179337Syongari		device_printf(sc->jme_dev,
1242179337Syongari		    "could not load DMA'able memory for Rx ring.\n");
1243179337Syongari		goto fail;
1244179337Syongari	}
1245179337Syongari	sc->jme_rdata.jme_rx_ring_paddr = ctx.jme_busaddr;
1246179337Syongari
1247185596Syongari	if (lowaddr != BUS_SPACE_MAXADDR_32BIT) {
1248185596Syongari		/* Tx/Rx descriptor queue should reside within 4GB boundary. */
1249185596Syongari		tx_ring_end = sc->jme_rdata.jme_tx_ring_paddr +
1250185596Syongari		    JME_TX_RING_SIZE;
1251185596Syongari		rx_ring_end = sc->jme_rdata.jme_rx_ring_paddr +
1252185596Syongari		    JME_RX_RING_SIZE;
1253185596Syongari		if ((JME_ADDR_HI(tx_ring_end) !=
1254185596Syongari		    JME_ADDR_HI(sc->jme_rdata.jme_tx_ring_paddr)) ||
1255185596Syongari		    (JME_ADDR_HI(rx_ring_end) !=
1256185596Syongari		     JME_ADDR_HI(sc->jme_rdata.jme_rx_ring_paddr))) {
1257185596Syongari			device_printf(sc->jme_dev, "4GB boundary crossed, "
1258185596Syongari			    "switching to 32bit DMA address mode.\n");
1259185596Syongari			jme_dma_free(sc);
1260185596Syongari			/* Limit DMA address space to 32bit and try again. */
1261185596Syongari			lowaddr = BUS_SPACE_MAXADDR_32BIT;
1262185596Syongari			goto again;
1263185596Syongari		}
1264179337Syongari	}
1265179337Syongari
1266185596Syongari	lowaddr = BUS_SPACE_MAXADDR;
1267185596Syongari	if ((sc->jme_flags & JME_FLAG_DMA32BIT) != 0)
1268185596Syongari		lowaddr = BUS_SPACE_MAXADDR_32BIT;
1269179337Syongari	/* Create parent buffer tag. */
1270179337Syongari	error = bus_dma_tag_create(bus_get_dma_tag(sc->jme_dev),/* parent */
1271179337Syongari	    1, 0,			/* algnmnt, boundary */
1272185596Syongari	    lowaddr,			/* lowaddr */
1273179337Syongari	    BUS_SPACE_MAXADDR,		/* highaddr */
1274179337Syongari	    NULL, NULL,			/* filter, filterarg */
1275179337Syongari	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsize */
1276179337Syongari	    0,				/* nsegments */
1277179337Syongari	    BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
1278179337Syongari	    0,				/* flags */
1279179337Syongari	    NULL, NULL,			/* lockfunc, lockarg */
1280179337Syongari	    &sc->jme_cdata.jme_buffer_tag);
1281179337Syongari	if (error != 0) {
1282179337Syongari		device_printf(sc->jme_dev,
1283179337Syongari		    "could not create parent buffer DMA tag.\n");
1284179337Syongari		goto fail;
1285179337Syongari	}
1286179337Syongari
1287179337Syongari	/* Create shadow status block tag. */
1288179337Syongari	error = bus_dma_tag_create(sc->jme_cdata.jme_buffer_tag,/* parent */
1289179337Syongari	    JME_SSB_ALIGN, 0,		/* algnmnt, boundary */
1290179337Syongari	    BUS_SPACE_MAXADDR,		/* lowaddr */
1291179337Syongari	    BUS_SPACE_MAXADDR,		/* highaddr */
1292179337Syongari	    NULL, NULL,			/* filter, filterarg */
1293179337Syongari	    JME_SSB_SIZE,		/* maxsize */
1294179337Syongari	    1,				/* nsegments */
1295179337Syongari	    JME_SSB_SIZE,		/* maxsegsize */
1296179337Syongari	    0,				/* flags */
1297179337Syongari	    NULL, NULL,			/* lockfunc, lockarg */
1298179337Syongari	    &sc->jme_cdata.jme_ssb_tag);
1299179337Syongari	if (error != 0) {
1300179337Syongari		device_printf(sc->jme_dev,
1301179337Syongari		    "could not create shared status block DMA tag.\n");
1302179337Syongari		goto fail;
1303179337Syongari	}
1304179337Syongari
1305179337Syongari	/* Create tag for Tx buffers. */
1306179337Syongari	error = bus_dma_tag_create(sc->jme_cdata.jme_buffer_tag,/* parent */
1307179337Syongari	    1, 0,			/* algnmnt, boundary */
1308179337Syongari	    BUS_SPACE_MAXADDR,		/* lowaddr */
1309179337Syongari	    BUS_SPACE_MAXADDR,		/* highaddr */
1310179337Syongari	    NULL, NULL,			/* filter, filterarg */
1311179337Syongari	    JME_TSO_MAXSIZE,		/* maxsize */
1312179337Syongari	    JME_MAXTXSEGS,		/* nsegments */
1313179337Syongari	    JME_TSO_MAXSEGSIZE,		/* maxsegsize */
1314179337Syongari	    0,				/* flags */
1315179337Syongari	    NULL, NULL,			/* lockfunc, lockarg */
1316179337Syongari	    &sc->jme_cdata.jme_tx_tag);
1317179337Syongari	if (error != 0) {
1318179337Syongari		device_printf(sc->jme_dev, "could not create Tx DMA tag.\n");
1319179337Syongari		goto fail;
1320179337Syongari	}
1321179337Syongari
1322179337Syongari	/* Create tag for Rx buffers. */
1323179337Syongari	error = bus_dma_tag_create(sc->jme_cdata.jme_buffer_tag,/* parent */
1324179337Syongari	    JME_RX_BUF_ALIGN, 0,	/* algnmnt, boundary */
1325179337Syongari	    BUS_SPACE_MAXADDR,		/* lowaddr */
1326179337Syongari	    BUS_SPACE_MAXADDR,		/* highaddr */
1327179337Syongari	    NULL, NULL,			/* filter, filterarg */
1328179337Syongari	    MCLBYTES,			/* maxsize */
1329179337Syongari	    1,				/* nsegments */
1330179337Syongari	    MCLBYTES,			/* maxsegsize */
1331179337Syongari	    0,				/* flags */
1332179337Syongari	    NULL, NULL,			/* lockfunc, lockarg */
1333179337Syongari	    &sc->jme_cdata.jme_rx_tag);
1334179337Syongari	if (error != 0) {
1335179337Syongari		device_printf(sc->jme_dev, "could not create Rx DMA tag.\n");
1336179337Syongari		goto fail;
1337179337Syongari	}
1338179337Syongari
1339179337Syongari	/*
1340179337Syongari	 * Allocate DMA'able memory and load the DMA map for shared
1341179337Syongari	 * status block.
1342179337Syongari	 */
1343179337Syongari	error = bus_dmamem_alloc(sc->jme_cdata.jme_ssb_tag,
1344179337Syongari	    (void **)&sc->jme_rdata.jme_ssb_block,
1345179337Syongari	    BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_COHERENT,
1346179337Syongari	    &sc->jme_cdata.jme_ssb_map);
1347179337Syongari	if (error != 0) {
1348179337Syongari		device_printf(sc->jme_dev, "could not allocate DMA'able "
1349179337Syongari		    "memory for shared status block.\n");
1350179337Syongari		goto fail;
1351179337Syongari	}
1352179337Syongari
1353179337Syongari	ctx.jme_busaddr = 0;
1354179337Syongari	error = bus_dmamap_load(sc->jme_cdata.jme_ssb_tag,
1355179337Syongari	    sc->jme_cdata.jme_ssb_map, sc->jme_rdata.jme_ssb_block,
1356179337Syongari	    JME_SSB_SIZE, jme_dmamap_cb, &ctx, BUS_DMA_NOWAIT);
1357179337Syongari	if (error != 0 || ctx.jme_busaddr == 0) {
1358179337Syongari		device_printf(sc->jme_dev, "could not load DMA'able memory "
1359179337Syongari		    "for shared status block.\n");
1360179337Syongari		goto fail;
1361179337Syongari	}
1362179337Syongari	sc->jme_rdata.jme_ssb_block_paddr = ctx.jme_busaddr;
1363179337Syongari
1364179337Syongari	/* Create DMA maps for Tx buffers. */
1365179337Syongari	for (i = 0; i < JME_TX_RING_CNT; i++) {
1366179337Syongari		txd = &sc->jme_cdata.jme_txdesc[i];
1367179337Syongari		txd->tx_m = NULL;
1368179337Syongari		txd->tx_dmamap = NULL;
1369179337Syongari		error = bus_dmamap_create(sc->jme_cdata.jme_tx_tag, 0,
1370179337Syongari		    &txd->tx_dmamap);
1371179337Syongari		if (error != 0) {
1372179337Syongari			device_printf(sc->jme_dev,
1373179337Syongari			    "could not create Tx dmamap.\n");
1374179337Syongari			goto fail;
1375179337Syongari		}
1376179337Syongari	}
1377179337Syongari	/* Create DMA maps for Rx buffers. */
1378179337Syongari	if ((error = bus_dmamap_create(sc->jme_cdata.jme_rx_tag, 0,
1379179337Syongari	    &sc->jme_cdata.jme_rx_sparemap)) != 0) {
1380179337Syongari		device_printf(sc->jme_dev,
1381179337Syongari		    "could not create spare Rx dmamap.\n");
1382179337Syongari		goto fail;
1383179337Syongari	}
1384179337Syongari	for (i = 0; i < JME_RX_RING_CNT; i++) {
1385179337Syongari		rxd = &sc->jme_cdata.jme_rxdesc[i];
1386179337Syongari		rxd->rx_m = NULL;
1387179337Syongari		rxd->rx_dmamap = NULL;
1388179337Syongari		error = bus_dmamap_create(sc->jme_cdata.jme_rx_tag, 0,
1389179337Syongari		    &rxd->rx_dmamap);
1390179337Syongari		if (error != 0) {
1391179337Syongari			device_printf(sc->jme_dev,
1392179337Syongari			    "could not create Rx dmamap.\n");
1393179337Syongari			goto fail;
1394179337Syongari		}
1395179337Syongari	}
1396179337Syongari
1397179337Syongarifail:
1398179337Syongari	return (error);
1399179337Syongari}
1400179337Syongari
1401179337Syongaristatic void
1402179337Syongarijme_dma_free(struct jme_softc *sc)
1403179337Syongari{
1404179337Syongari	struct jme_txdesc *txd;
1405179337Syongari	struct jme_rxdesc *rxd;
1406179337Syongari	int i;
1407179337Syongari
1408179337Syongari	/* Tx ring */
1409179337Syongari	if (sc->jme_cdata.jme_tx_ring_tag != NULL) {
1410267363Sjhb		if (sc->jme_rdata.jme_tx_ring_paddr)
1411179337Syongari			bus_dmamap_unload(sc->jme_cdata.jme_tx_ring_tag,
1412179337Syongari			    sc->jme_cdata.jme_tx_ring_map);
1413267363Sjhb		if (sc->jme_rdata.jme_tx_ring)
1414179337Syongari			bus_dmamem_free(sc->jme_cdata.jme_tx_ring_tag,
1415179337Syongari			    sc->jme_rdata.jme_tx_ring,
1416179337Syongari			    sc->jme_cdata.jme_tx_ring_map);
1417179337Syongari		sc->jme_rdata.jme_tx_ring = NULL;
1418267363Sjhb		sc->jme_rdata.jme_tx_ring_paddr = 0;
1419179337Syongari		bus_dma_tag_destroy(sc->jme_cdata.jme_tx_ring_tag);
1420179337Syongari		sc->jme_cdata.jme_tx_ring_tag = NULL;
1421179337Syongari	}
1422179337Syongari	/* Rx ring */
1423179337Syongari	if (sc->jme_cdata.jme_rx_ring_tag != NULL) {
1424267363Sjhb		if (sc->jme_rdata.jme_rx_ring_paddr)
1425179337Syongari			bus_dmamap_unload(sc->jme_cdata.jme_rx_ring_tag,
1426179337Syongari			    sc->jme_cdata.jme_rx_ring_map);
1427267363Sjhb		if (sc->jme_rdata.jme_rx_ring)
1428179337Syongari			bus_dmamem_free(sc->jme_cdata.jme_rx_ring_tag,
1429179337Syongari			    sc->jme_rdata.jme_rx_ring,
1430179337Syongari			    sc->jme_cdata.jme_rx_ring_map);
1431179337Syongari		sc->jme_rdata.jme_rx_ring = NULL;
1432267363Sjhb		sc->jme_rdata.jme_rx_ring_paddr = 0;
1433179337Syongari		bus_dma_tag_destroy(sc->jme_cdata.jme_rx_ring_tag);
1434179337Syongari		sc->jme_cdata.jme_rx_ring_tag = NULL;
1435179337Syongari	}
1436179337Syongari	/* Tx buffers */
1437179337Syongari	if (sc->jme_cdata.jme_tx_tag != NULL) {
1438179337Syongari		for (i = 0; i < JME_TX_RING_CNT; i++) {
1439179337Syongari			txd = &sc->jme_cdata.jme_txdesc[i];
1440179337Syongari			if (txd->tx_dmamap != NULL) {
1441179337Syongari				bus_dmamap_destroy(sc->jme_cdata.jme_tx_tag,
1442179337Syongari				    txd->tx_dmamap);
1443179337Syongari				txd->tx_dmamap = NULL;
1444179337Syongari			}
1445179337Syongari		}
1446179337Syongari		bus_dma_tag_destroy(sc->jme_cdata.jme_tx_tag);
1447179337Syongari		sc->jme_cdata.jme_tx_tag = NULL;
1448179337Syongari	}
1449179337Syongari	/* Rx buffers */
1450179337Syongari	if (sc->jme_cdata.jme_rx_tag != NULL) {
1451179337Syongari		for (i = 0; i < JME_RX_RING_CNT; i++) {
1452179337Syongari			rxd = &sc->jme_cdata.jme_rxdesc[i];
1453179337Syongari			if (rxd->rx_dmamap != NULL) {
1454179337Syongari				bus_dmamap_destroy(sc->jme_cdata.jme_rx_tag,
1455179337Syongari				    rxd->rx_dmamap);
1456179337Syongari				rxd->rx_dmamap = NULL;
1457179337Syongari			}
1458179337Syongari		}
1459179337Syongari		if (sc->jme_cdata.jme_rx_sparemap != NULL) {
1460179337Syongari			bus_dmamap_destroy(sc->jme_cdata.jme_rx_tag,
1461179337Syongari			    sc->jme_cdata.jme_rx_sparemap);
1462179337Syongari			sc->jme_cdata.jme_rx_sparemap = NULL;
1463179337Syongari		}
1464179337Syongari		bus_dma_tag_destroy(sc->jme_cdata.jme_rx_tag);
1465179337Syongari		sc->jme_cdata.jme_rx_tag = NULL;
1466179337Syongari	}
1467179337Syongari
1468179337Syongari	/* Shared status block. */
1469179337Syongari	if (sc->jme_cdata.jme_ssb_tag != NULL) {
1470267363Sjhb		if (sc->jme_rdata.jme_ssb_block_paddr)
1471179337Syongari			bus_dmamap_unload(sc->jme_cdata.jme_ssb_tag,
1472179337Syongari			    sc->jme_cdata.jme_ssb_map);
1473267363Sjhb		if (sc->jme_rdata.jme_ssb_block)
1474179337Syongari			bus_dmamem_free(sc->jme_cdata.jme_ssb_tag,
1475179337Syongari			    sc->jme_rdata.jme_ssb_block,
1476179337Syongari			    sc->jme_cdata.jme_ssb_map);
1477179337Syongari		sc->jme_rdata.jme_ssb_block = NULL;
1478267363Sjhb		sc->jme_rdata.jme_ssb_block_paddr = 0;
1479179337Syongari		bus_dma_tag_destroy(sc->jme_cdata.jme_ssb_tag);
1480179337Syongari		sc->jme_cdata.jme_ssb_tag = NULL;
1481179337Syongari	}
1482179337Syongari
1483179337Syongari	if (sc->jme_cdata.jme_buffer_tag != NULL) {
1484179337Syongari		bus_dma_tag_destroy(sc->jme_cdata.jme_buffer_tag);
1485179337Syongari		sc->jme_cdata.jme_buffer_tag = NULL;
1486179337Syongari	}
1487179337Syongari	if (sc->jme_cdata.jme_ring_tag != NULL) {
1488179337Syongari		bus_dma_tag_destroy(sc->jme_cdata.jme_ring_tag);
1489179337Syongari		sc->jme_cdata.jme_ring_tag = NULL;
1490179337Syongari	}
1491179337Syongari}
1492179337Syongari
1493179337Syongari/*
1494179337Syongari *	Make sure the interface is stopped at reboot time.
1495179337Syongari */
1496179337Syongaristatic int
1497179337Syongarijme_shutdown(device_t dev)
1498179337Syongari{
1499179337Syongari
1500179337Syongari	return (jme_suspend(dev));
1501179337Syongari}
1502179337Syongari
1503179337Syongari/*
1504179337Syongari * Unlike other ethernet controllers, JMC250 requires
1505179337Syongari * explicit resetting link speed to 10/100Mbps as gigabit
1506179337Syongari * link will cunsume more power than 375mA.
1507179337Syongari * Note, we reset the link speed to 10/100Mbps with
1508179337Syongari * auto-negotiation but we don't know whether that operation
1509179337Syongari * would succeed or not as we have no control after powering
1510179337Syongari * off. If the renegotiation fail WOL may not work. Running
1511179337Syongari * at 1Gbps draws more power than 375mA at 3.3V which is
1512179337Syongari * specified in PCI specification and that would result in
1513179337Syongari * complete shutdowning power to ethernet controller.
1514179337Syongari *
1515179337Syongari * TODO
1516179337Syongari *  Save current negotiated media speed/duplex/flow-control
1517179337Syongari *  to softc and restore the same link again after resuming.
1518179337Syongari *  PHY handling such as power down/resetting to 100Mbps
1519179337Syongari *  may be better handled in suspend method in phy driver.
1520179337Syongari */
1521179337Syongaristatic void
1522179337Syongarijme_setlinkspeed(struct jme_softc *sc)
1523179337Syongari{
1524179337Syongari	struct mii_data *mii;
1525179337Syongari	int aneg, i;
1526179337Syongari
1527179337Syongari	JME_LOCK_ASSERT(sc);
1528179337Syongari
1529179337Syongari	mii = device_get_softc(sc->jme_miibus);
1530179337Syongari	mii_pollstat(mii);
1531179337Syongari	aneg = 0;
1532179337Syongari	if ((mii->mii_media_status & IFM_AVALID) != 0) {
1533179337Syongari		switch IFM_SUBTYPE(mii->mii_media_active) {
1534179337Syongari		case IFM_10_T:
1535179337Syongari		case IFM_100_TX:
1536179337Syongari			return;
1537179337Syongari		case IFM_1000_T:
1538179337Syongari			aneg++;
1539179337Syongari		default:
1540179337Syongari			break;
1541179337Syongari		}
1542179337Syongari	}
1543179337Syongari	jme_miibus_writereg(sc->jme_dev, sc->jme_phyaddr, MII_100T2CR, 0);
1544179337Syongari	jme_miibus_writereg(sc->jme_dev, sc->jme_phyaddr, MII_ANAR,
1545179337Syongari	    ANAR_TX_FD | ANAR_TX | ANAR_10_FD | ANAR_10 | ANAR_CSMA);
1546179337Syongari	jme_miibus_writereg(sc->jme_dev, sc->jme_phyaddr, MII_BMCR,
1547179337Syongari	    BMCR_AUTOEN | BMCR_STARTNEG);
1548179337Syongari	DELAY(1000);
1549179337Syongari	if (aneg != 0) {
1550179337Syongari		/* Poll link state until jme(4) get a 10/100 link. */
1551179337Syongari		for (i = 0; i < MII_ANEGTICKS_GIGE; i++) {
1552179337Syongari			mii_pollstat(mii);
1553179337Syongari			if ((mii->mii_media_status & IFM_AVALID) != 0) {
1554179337Syongari				switch (IFM_SUBTYPE(mii->mii_media_active)) {
1555179337Syongari				case IFM_10_T:
1556179337Syongari				case IFM_100_TX:
1557179337Syongari					jme_mac_config(sc);
1558179337Syongari					return;
1559179337Syongari				default:
1560179337Syongari					break;
1561179337Syongari				}
1562179337Syongari			}
1563179337Syongari			JME_UNLOCK(sc);
1564179337Syongari			pause("jmelnk", hz);
1565179337Syongari			JME_LOCK(sc);
1566179337Syongari		}
1567179337Syongari		if (i == MII_ANEGTICKS_GIGE)
1568179337Syongari			device_printf(sc->jme_dev, "establishing link failed, "
1569179337Syongari			    "WOL may not work!");
1570179337Syongari	}
1571179337Syongari	/*
1572179337Syongari	 * No link, force MAC to have 100Mbps, full-duplex link.
1573179337Syongari	 * This is the last resort and may/may not work.
1574179337Syongari	 */
1575179337Syongari	mii->mii_media_status = IFM_AVALID | IFM_ACTIVE;
1576179337Syongari	mii->mii_media_active = IFM_ETHER | IFM_100_TX | IFM_FDX;
1577179337Syongari	jme_mac_config(sc);
1578179337Syongari}
1579179337Syongari
1580179337Syongaristatic void
1581179337Syongarijme_setwol(struct jme_softc *sc)
1582179337Syongari{
1583179337Syongari	struct ifnet *ifp;
1584179337Syongari	uint32_t gpr, pmcs;
1585179337Syongari	uint16_t pmstat;
1586179337Syongari	int pmc;
1587179337Syongari
1588179337Syongari	JME_LOCK_ASSERT(sc);
1589179337Syongari
1590219902Sjhb	if (pci_find_cap(sc->jme_dev, PCIY_PMG, &pmc) != 0) {
1591185596Syongari		/* Remove Tx MAC/offload clock to save more power. */
1592185596Syongari		if ((sc->jme_flags & JME_FLAG_TXCLK) != 0)
1593185596Syongari			CSR_WRITE_4(sc, JME_GHC, CSR_READ_4(sc, JME_GHC) &
1594185596Syongari			    ~(GHC_TX_OFFLD_CLK_100 | GHC_TX_MAC_CLK_100 |
1595185596Syongari			    GHC_TX_OFFLD_CLK_1000 | GHC_TX_MAC_CLK_1000));
1596216551Syongari		if ((sc->jme_flags & JME_FLAG_RXCLK) != 0)
1597216551Syongari			CSR_WRITE_4(sc, JME_GPREG1,
1598216551Syongari			    CSR_READ_4(sc, JME_GPREG1) | GPREG1_RX_MAC_CLK_DIS);
1599179337Syongari		/* No PME capability, PHY power down. */
1600216551Syongari		jme_phy_down(sc);
1601179337Syongari		return;
1602179337Syongari	}
1603179337Syongari
1604179337Syongari	ifp = sc->jme_ifp;
1605179337Syongari	gpr = CSR_READ_4(sc, JME_GPREG0) & ~GPREG0_PME_ENB;
1606179337Syongari	pmcs = CSR_READ_4(sc, JME_PMCS);
1607179337Syongari	pmcs &= ~PMCS_WOL_ENB_MASK;
1608179337Syongari	if ((ifp->if_capenable & IFCAP_WOL_MAGIC) != 0) {
1609179337Syongari		pmcs |= PMCS_MAGIC_FRAME | PMCS_MAGIC_FRAME_ENB;
1610179337Syongari		/* Enable PME message. */
1611179337Syongari		gpr |= GPREG0_PME_ENB;
1612179337Syongari		/* For gigabit controllers, reset link speed to 10/100. */
1613179337Syongari		if ((sc->jme_flags & JME_FLAG_FASTETH) == 0)
1614179337Syongari			jme_setlinkspeed(sc);
1615179337Syongari	}
1616179337Syongari
1617179337Syongari	CSR_WRITE_4(sc, JME_PMCS, pmcs);
1618179337Syongari	CSR_WRITE_4(sc, JME_GPREG0, gpr);
1619185596Syongari	/* Remove Tx MAC/offload clock to save more power. */
1620185596Syongari	if ((sc->jme_flags & JME_FLAG_TXCLK) != 0)
1621185596Syongari		CSR_WRITE_4(sc, JME_GHC, CSR_READ_4(sc, JME_GHC) &
1622185596Syongari		    ~(GHC_TX_OFFLD_CLK_100 | GHC_TX_MAC_CLK_100 |
1623185596Syongari		    GHC_TX_OFFLD_CLK_1000 | GHC_TX_MAC_CLK_1000));
1624179337Syongari	/* Request PME. */
1625179337Syongari	pmstat = pci_read_config(sc->jme_dev, pmc + PCIR_POWER_STATUS, 2);
1626179337Syongari	pmstat &= ~(PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE);
1627179337Syongari	if ((ifp->if_capenable & IFCAP_WOL) != 0)
1628179337Syongari		pmstat |= PCIM_PSTAT_PME | PCIM_PSTAT_PMEENABLE;
1629179337Syongari	pci_write_config(sc->jme_dev, pmc + PCIR_POWER_STATUS, pmstat, 2);
1630179337Syongari	if ((ifp->if_capenable & IFCAP_WOL) == 0) {
1631179337Syongari		/* No WOL, PHY power down. */
1632216551Syongari		jme_phy_down(sc);
1633179337Syongari	}
1634179337Syongari}
1635179337Syongari
1636179337Syongaristatic int
1637179337Syongarijme_suspend(device_t dev)
1638179337Syongari{
1639179337Syongari	struct jme_softc *sc;
1640179337Syongari
1641179337Syongari	sc = device_get_softc(dev);
1642179337Syongari
1643179337Syongari	JME_LOCK(sc);
1644179337Syongari	jme_stop(sc);
1645179337Syongari	jme_setwol(sc);
1646179337Syongari	JME_UNLOCK(sc);
1647179337Syongari
1648179337Syongari	return (0);
1649179337Syongari}
1650179337Syongari
1651179337Syongaristatic int
1652179337Syongarijme_resume(device_t dev)
1653179337Syongari{
1654179337Syongari	struct jme_softc *sc;
1655179337Syongari	struct ifnet *ifp;
1656179337Syongari	uint16_t pmstat;
1657179337Syongari	int pmc;
1658179337Syongari
1659179337Syongari	sc = device_get_softc(dev);
1660179337Syongari
1661179337Syongari	JME_LOCK(sc);
1662236700Skevlo	if (pci_find_cap(sc->jme_dev, PCIY_PMG, &pmc) == 0) {
1663179337Syongari		pmstat = pci_read_config(sc->jme_dev,
1664179337Syongari		    pmc + PCIR_POWER_STATUS, 2);
1665179337Syongari		/* Disable PME clear PME status. */
1666179337Syongari		pmstat &= ~PCIM_PSTAT_PMEENABLE;
1667179337Syongari		pci_write_config(sc->jme_dev,
1668179337Syongari		    pmc + PCIR_POWER_STATUS, pmstat, 2);
1669179337Syongari	}
1670216551Syongari	/* Wakeup PHY. */
1671216551Syongari	jme_phy_up(sc);
1672179337Syongari	ifp = sc->jme_ifp;
1673197585Syongari	if ((ifp->if_flags & IFF_UP) != 0) {
1674197585Syongari		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1675179337Syongari		jme_init_locked(sc);
1676197585Syongari	}
1677179337Syongari
1678179337Syongari	JME_UNLOCK(sc);
1679179337Syongari
1680179337Syongari	return (0);
1681179337Syongari}
1682179337Syongari
1683179337Syongaristatic int
1684179337Syongarijme_encap(struct jme_softc *sc, struct mbuf **m_head)
1685179337Syongari{
1686179337Syongari	struct jme_txdesc *txd;
1687179337Syongari	struct jme_desc *desc;
1688179337Syongari	struct mbuf *m;
1689179337Syongari	bus_dma_segment_t txsegs[JME_MAXTXSEGS];
1690179337Syongari	int error, i, nsegs, prod;
1691254803Sandre	uint32_t cflags, tsosegsz;
1692179337Syongari
1693179337Syongari	JME_LOCK_ASSERT(sc);
1694179337Syongari
1695179337Syongari	M_ASSERTPKTHDR((*m_head));
1696179337Syongari
1697179337Syongari	if (((*m_head)->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
1698179337Syongari		/*
1699179337Syongari		 * Due to the adherence to NDIS specification JMC250
1700179337Syongari		 * assumes upper stack computed TCP pseudo checksum
1701179337Syongari		 * without including payload length. This breaks
1702179337Syongari		 * checksum offload for TSO case so recompute TCP
1703179337Syongari		 * pseudo checksum for JMC250. Hopefully this wouldn't
1704179337Syongari		 * be much burden on modern CPUs.
1705179337Syongari		 */
1706179337Syongari		struct ether_header *eh;
1707179337Syongari		struct ip *ip;
1708179337Syongari		struct tcphdr *tcp;
1709179337Syongari		uint32_t ip_off, poff;
1710179337Syongari
1711179337Syongari		if (M_WRITABLE(*m_head) == 0) {
1712179337Syongari			/* Get a writable copy. */
1713243857Sglebius			m = m_dup(*m_head, M_NOWAIT);
1714179337Syongari			m_freem(*m_head);
1715179337Syongari			if (m == NULL) {
1716179337Syongari				*m_head = NULL;
1717179337Syongari				return (ENOBUFS);
1718179337Syongari			}
1719179337Syongari			*m_head = m;
1720179337Syongari		}
1721179337Syongari		ip_off = sizeof(struct ether_header);
1722179337Syongari		m = m_pullup(*m_head, ip_off);
1723179337Syongari		if (m == NULL) {
1724179337Syongari			*m_head = NULL;
1725179337Syongari			return (ENOBUFS);
1726179337Syongari		}
1727179337Syongari		eh = mtod(m, struct ether_header *);
1728179337Syongari		/* Check the existence of VLAN tag. */
1729179337Syongari		if (eh->ether_type == htons(ETHERTYPE_VLAN)) {
1730179337Syongari			ip_off = sizeof(struct ether_vlan_header);
1731179337Syongari			m = m_pullup(m, ip_off);
1732179337Syongari			if (m == NULL) {
1733179337Syongari				*m_head = NULL;
1734179337Syongari				return (ENOBUFS);
1735179337Syongari			}
1736179337Syongari		}
1737179337Syongari		m = m_pullup(m, ip_off + sizeof(struct ip));
1738179337Syongari		if (m == NULL) {
1739179337Syongari			*m_head = NULL;
1740179337Syongari			return (ENOBUFS);
1741179337Syongari		}
1742179337Syongari		ip = (struct ip *)(mtod(m, char *) + ip_off);
1743179337Syongari		poff = ip_off + (ip->ip_hl << 2);
1744179337Syongari		m = m_pullup(m, poff + sizeof(struct tcphdr));
1745179337Syongari		if (m == NULL) {
1746179337Syongari			*m_head = NULL;
1747179337Syongari			return (ENOBUFS);
1748179337Syongari		}
1749179337Syongari		/*
1750179337Syongari		 * Reset IP checksum and recompute TCP pseudo
1751179337Syongari		 * checksum that NDIS specification requires.
1752179337Syongari		 */
1753213844Syongari		ip = (struct ip *)(mtod(m, char *) + ip_off);
1754213844Syongari		tcp = (struct tcphdr *)(mtod(m, char *) + poff);
1755179337Syongari		ip->ip_sum = 0;
1756179337Syongari		if (poff + (tcp->th_off << 2) == m->m_pkthdr.len) {
1757179337Syongari			tcp->th_sum = in_pseudo(ip->ip_src.s_addr,
1758179337Syongari			    ip->ip_dst.s_addr,
1759179337Syongari			    htons((tcp->th_off << 2) + IPPROTO_TCP));
1760179337Syongari			/* No need to TSO, force IP checksum offload. */
1761179337Syongari			(*m_head)->m_pkthdr.csum_flags &= ~CSUM_TSO;
1762179337Syongari			(*m_head)->m_pkthdr.csum_flags |= CSUM_IP;
1763179337Syongari		} else
1764179337Syongari			tcp->th_sum = in_pseudo(ip->ip_src.s_addr,
1765179337Syongari			    ip->ip_dst.s_addr, htons(IPPROTO_TCP));
1766179337Syongari		*m_head = m;
1767179337Syongari	}
1768179337Syongari
1769179337Syongari	prod = sc->jme_cdata.jme_tx_prod;
1770179337Syongari	txd = &sc->jme_cdata.jme_txdesc[prod];
1771179337Syongari
1772179337Syongari	error = bus_dmamap_load_mbuf_sg(sc->jme_cdata.jme_tx_tag,
1773179337Syongari	    txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
1774179337Syongari	if (error == EFBIG) {
1775243857Sglebius		m = m_collapse(*m_head, M_NOWAIT, JME_MAXTXSEGS);
1776179337Syongari		if (m == NULL) {
1777179337Syongari			m_freem(*m_head);
1778179337Syongari			*m_head = NULL;
1779179337Syongari			return (ENOMEM);
1780179337Syongari		}
1781179337Syongari		*m_head = m;
1782179337Syongari		error = bus_dmamap_load_mbuf_sg(sc->jme_cdata.jme_tx_tag,
1783179337Syongari		    txd->tx_dmamap, *m_head, txsegs, &nsegs, 0);
1784179337Syongari		if (error != 0) {
1785179337Syongari			m_freem(*m_head);
1786179337Syongari			*m_head = NULL;
1787179337Syongari			return (error);
1788179337Syongari		}
1789179337Syongari	} else if (error != 0)
1790179337Syongari		return (error);
1791179337Syongari	if (nsegs == 0) {
1792179337Syongari		m_freem(*m_head);
1793179337Syongari		*m_head = NULL;
1794179337Syongari		return (EIO);
1795179337Syongari	}
1796179337Syongari
1797179337Syongari	/*
1798179337Syongari	 * Check descriptor overrun. Leave one free descriptor.
1799179337Syongari	 * Since we always use 64bit address mode for transmitting,
1800179337Syongari	 * each Tx request requires one more dummy descriptor.
1801179337Syongari	 */
1802179337Syongari	if (sc->jme_cdata.jme_tx_cnt + nsegs + 1 > JME_TX_RING_CNT - 1) {
1803179337Syongari		bus_dmamap_unload(sc->jme_cdata.jme_tx_tag, txd->tx_dmamap);
1804179337Syongari		return (ENOBUFS);
1805179337Syongari	}
1806179337Syongari
1807179337Syongari	m = *m_head;
1808179337Syongari	cflags = 0;
1809254803Sandre	tsosegsz = 0;
1810179337Syongari	/* Configure checksum offload and TSO. */
1811179337Syongari	if ((m->m_pkthdr.csum_flags & CSUM_TSO) != 0) {
1812254803Sandre		tsosegsz = (uint32_t)m->m_pkthdr.tso_segsz <<
1813179337Syongari		    JME_TD_MSS_SHIFT;
1814179337Syongari		cflags |= JME_TD_TSO;
1815179337Syongari	} else {
1816179337Syongari		if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0)
1817179337Syongari			cflags |= JME_TD_IPCSUM;
1818179337Syongari		if ((m->m_pkthdr.csum_flags & CSUM_TCP) != 0)
1819179337Syongari			cflags |= JME_TD_TCPCSUM;
1820179337Syongari		if ((m->m_pkthdr.csum_flags & CSUM_UDP) != 0)
1821179337Syongari			cflags |= JME_TD_UDPCSUM;
1822179337Syongari	}
1823179337Syongari	/* Configure VLAN. */
1824179337Syongari	if ((m->m_flags & M_VLANTAG) != 0) {
1825179337Syongari		cflags |= (m->m_pkthdr.ether_vtag & JME_TD_VLAN_MASK);
1826179337Syongari		cflags |= JME_TD_VLAN_TAG;
1827179337Syongari	}
1828179337Syongari
1829179337Syongari	desc = &sc->jme_rdata.jme_tx_ring[prod];
1830179337Syongari	desc->flags = htole32(cflags);
1831254803Sandre	desc->buflen = htole32(tsosegsz);
1832179337Syongari	desc->addr_hi = htole32(m->m_pkthdr.len);
1833179337Syongari	desc->addr_lo = 0;
1834179337Syongari	sc->jme_cdata.jme_tx_cnt++;
1835179337Syongari	JME_DESC_INC(prod, JME_TX_RING_CNT);
1836179337Syongari	for (i = 0; i < nsegs; i++) {
1837179337Syongari		desc = &sc->jme_rdata.jme_tx_ring[prod];
1838179337Syongari		desc->flags = htole32(JME_TD_OWN | JME_TD_64BIT);
1839179337Syongari		desc->buflen = htole32(txsegs[i].ds_len);
1840179337Syongari		desc->addr_hi = htole32(JME_ADDR_HI(txsegs[i].ds_addr));
1841179337Syongari		desc->addr_lo = htole32(JME_ADDR_LO(txsegs[i].ds_addr));
1842179337Syongari		sc->jme_cdata.jme_tx_cnt++;
1843179337Syongari		JME_DESC_INC(prod, JME_TX_RING_CNT);
1844179337Syongari	}
1845179337Syongari
1846179337Syongari	/* Update producer index. */
1847179337Syongari	sc->jme_cdata.jme_tx_prod = prod;
1848179337Syongari	/*
1849179337Syongari	 * Finally request interrupt and give the first descriptor
1850179337Syongari	 * owenership to hardware.
1851179337Syongari	 */
1852179337Syongari	desc = txd->tx_desc;
1853179337Syongari	desc->flags |= htole32(JME_TD_OWN | JME_TD_INTR);
1854179337Syongari
1855179337Syongari	txd->tx_m = m;
1856179337Syongari	txd->tx_ndesc = nsegs + 1;
1857179337Syongari
1858179337Syongari	/* Sync descriptors. */
1859179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_tx_tag, txd->tx_dmamap,
1860179337Syongari	    BUS_DMASYNC_PREWRITE);
1861179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_tx_ring_tag,
1862179337Syongari	    sc->jme_cdata.jme_tx_ring_map,
1863179337Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1864179337Syongari
1865179337Syongari	return (0);
1866179337Syongari}
1867179337Syongari
1868179337Syongaristatic void
1869217353Sjhbjme_start(struct ifnet *ifp)
1870179337Syongari{
1871217353Sjhb        struct jme_softc *sc;
1872179337Syongari
1873217353Sjhb	sc = ifp->if_softc;
1874217353Sjhb	JME_LOCK(sc);
1875217353Sjhb	jme_start_locked(ifp);
1876217353Sjhb	JME_UNLOCK(sc);
1877179337Syongari}
1878179337Syongari
1879179337Syongaristatic void
1880217353Sjhbjme_start_locked(struct ifnet *ifp)
1881179337Syongari{
1882179337Syongari        struct jme_softc *sc;
1883179337Syongari        struct mbuf *m_head;
1884179337Syongari	int enq;
1885179337Syongari
1886179337Syongari	sc = ifp->if_softc;
1887179337Syongari
1888217353Sjhb	JME_LOCK_ASSERT(sc);
1889179337Syongari
1890179337Syongari	if (sc->jme_cdata.jme_tx_cnt >= JME_TX_DESC_HIWAT)
1891179337Syongari		jme_txeof(sc);
1892179337Syongari
1893179337Syongari	if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
1894217353Sjhb	    IFF_DRV_RUNNING || (sc->jme_flags & JME_FLAG_LINK) == 0)
1895179337Syongari		return;
1896179337Syongari
1897179337Syongari	for (enq = 0; !IFQ_DRV_IS_EMPTY(&ifp->if_snd); ) {
1898179337Syongari		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
1899179337Syongari		if (m_head == NULL)
1900179337Syongari			break;
1901179337Syongari		/*
1902179337Syongari		 * Pack the data into the transmit ring. If we
1903179337Syongari		 * don't have room, set the OACTIVE flag and wait
1904179337Syongari		 * for the NIC to drain the ring.
1905179337Syongari		 */
1906179337Syongari		if (jme_encap(sc, &m_head)) {
1907179337Syongari			if (m_head == NULL)
1908179337Syongari				break;
1909179337Syongari			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
1910179337Syongari			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1911179337Syongari			break;
1912179337Syongari		}
1913179337Syongari
1914179337Syongari		enq++;
1915179337Syongari		/*
1916179337Syongari		 * If there's a BPF listener, bounce a copy of this frame
1917179337Syongari		 * to him.
1918179337Syongari		 */
1919179337Syongari		ETHER_BPF_MTAP(ifp, m_head);
1920179337Syongari	}
1921179337Syongari
1922179337Syongari	if (enq > 0) {
1923179337Syongari		/*
1924179337Syongari		 * Reading TXCSR takes very long time under heavy load
1925179337Syongari		 * so cache TXCSR value and writes the ORed value with
1926179337Syongari		 * the kick command to the TXCSR. This saves one register
1927179337Syongari		 * access cycle.
1928179337Syongari		 */
1929179337Syongari		CSR_WRITE_4(sc, JME_TXCSR, sc->jme_txcsr | TXCSR_TX_ENB |
1930179337Syongari		    TXCSR_TXQ_N_START(TXCSR_TXQ0));
1931179337Syongari		/* Set a timeout in case the chip goes out to lunch. */
1932179337Syongari		sc->jme_watchdog_timer = JME_TX_TIMEOUT;
1933179337Syongari	}
1934179337Syongari}
1935179337Syongari
1936179337Syongaristatic void
1937179337Syongarijme_watchdog(struct jme_softc *sc)
1938179337Syongari{
1939179337Syongari	struct ifnet *ifp;
1940179337Syongari
1941179337Syongari	JME_LOCK_ASSERT(sc);
1942179337Syongari
1943179337Syongari	if (sc->jme_watchdog_timer == 0 || --sc->jme_watchdog_timer)
1944179337Syongari		return;
1945179337Syongari
1946179337Syongari	ifp = sc->jme_ifp;
1947179337Syongari	if ((sc->jme_flags & JME_FLAG_LINK) == 0) {
1948179337Syongari		if_printf(sc->jme_ifp, "watchdog timeout (missed link)\n");
1949272066Sglebius		if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1950197585Syongari		ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1951179337Syongari		jme_init_locked(sc);
1952179337Syongari		return;
1953179337Syongari	}
1954179337Syongari	jme_txeof(sc);
1955179337Syongari	if (sc->jme_cdata.jme_tx_cnt == 0) {
1956179337Syongari		if_printf(sc->jme_ifp,
1957179337Syongari		    "watchdog timeout (missed Tx interrupts) -- recovering\n");
1958179337Syongari		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1959217353Sjhb			jme_start_locked(ifp);
1960179337Syongari		return;
1961179337Syongari	}
1962179337Syongari
1963179337Syongari	if_printf(sc->jme_ifp, "watchdog timeout\n");
1964272066Sglebius	if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
1965197585Syongari	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
1966179337Syongari	jme_init_locked(sc);
1967179337Syongari	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
1968217353Sjhb		jme_start_locked(ifp);
1969179337Syongari}
1970179337Syongari
1971179337Syongaristatic int
1972179337Syongarijme_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1973179337Syongari{
1974179337Syongari	struct jme_softc *sc;
1975179337Syongari	struct ifreq *ifr;
1976179337Syongari	struct mii_data *mii;
1977179337Syongari	uint32_t reg;
1978179337Syongari	int error, mask;
1979179337Syongari
1980179337Syongari	sc = ifp->if_softc;
1981179337Syongari	ifr = (struct ifreq *)data;
1982179337Syongari	error = 0;
1983179337Syongari	switch (cmd) {
1984179337Syongari	case SIOCSIFMTU:
1985179337Syongari		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > JME_JUMBO_MTU ||
1986179337Syongari		    ((sc->jme_flags & JME_FLAG_NOJUMBO) != 0 &&
1987179337Syongari		    ifr->ifr_mtu > JME_MAX_MTU)) {
1988179337Syongari			error = EINVAL;
1989179337Syongari			break;
1990179337Syongari		}
1991179337Syongari
1992179337Syongari		if (ifp->if_mtu != ifr->ifr_mtu) {
1993179337Syongari			/*
1994179337Syongari			 * No special configuration is required when interface
1995179337Syongari			 * MTU is changed but availability of TSO/Tx checksum
1996179337Syongari			 * offload should be chcked against new MTU size as
1997179337Syongari			 * FIFO size is just 2K.
1998179337Syongari			 */
1999179337Syongari			JME_LOCK(sc);
2000179337Syongari			if (ifr->ifr_mtu >= JME_TX_FIFO_SIZE) {
2001179337Syongari				ifp->if_capenable &=
2002179337Syongari				    ~(IFCAP_TXCSUM | IFCAP_TSO4);
2003179337Syongari				ifp->if_hwassist &=
2004179337Syongari				    ~(JME_CSUM_FEATURES | CSUM_TSO);
2005179337Syongari				VLAN_CAPABILITIES(ifp);
2006179337Syongari			}
2007179337Syongari			ifp->if_mtu = ifr->ifr_mtu;
2008197585Syongari			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
2009197585Syongari				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
2010179337Syongari				jme_init_locked(sc);
2011197585Syongari			}
2012179337Syongari			JME_UNLOCK(sc);
2013179337Syongari		}
2014179337Syongari		break;
2015179337Syongari	case SIOCSIFFLAGS:
2016179337Syongari		JME_LOCK(sc);
2017179337Syongari		if ((ifp->if_flags & IFF_UP) != 0) {
2018179337Syongari			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
2019179337Syongari				if (((ifp->if_flags ^ sc->jme_if_flags)
2020179337Syongari				    & (IFF_PROMISC | IFF_ALLMULTI)) != 0)
2021179337Syongari					jme_set_filter(sc);
2022179337Syongari			} else {
2023179337Syongari				if ((sc->jme_flags & JME_FLAG_DETACH) == 0)
2024179337Syongari					jme_init_locked(sc);
2025179337Syongari			}
2026179337Syongari		} else {
2027179337Syongari			if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
2028179337Syongari				jme_stop(sc);
2029179337Syongari		}
2030179337Syongari		sc->jme_if_flags = ifp->if_flags;
2031179337Syongari		JME_UNLOCK(sc);
2032179337Syongari		break;
2033179337Syongari	case SIOCADDMULTI:
2034179337Syongari	case SIOCDELMULTI:
2035179337Syongari		JME_LOCK(sc);
2036179337Syongari		if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
2037179337Syongari			jme_set_filter(sc);
2038179337Syongari		JME_UNLOCK(sc);
2039179337Syongari		break;
2040179337Syongari	case SIOCSIFMEDIA:
2041179337Syongari	case SIOCGIFMEDIA:
2042179337Syongari		mii = device_get_softc(sc->jme_miibus);
2043179337Syongari		error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, cmd);
2044179337Syongari		break;
2045179337Syongari	case SIOCSIFCAP:
2046179337Syongari		JME_LOCK(sc);
2047179337Syongari		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
2048179337Syongari		if ((mask & IFCAP_TXCSUM) != 0 &&
2049179337Syongari		    ifp->if_mtu < JME_TX_FIFO_SIZE) {
2050179337Syongari			if ((IFCAP_TXCSUM & ifp->if_capabilities) != 0) {
2051179337Syongari				ifp->if_capenable ^= IFCAP_TXCSUM;
2052179337Syongari				if ((IFCAP_TXCSUM & ifp->if_capenable) != 0)
2053179337Syongari					ifp->if_hwassist |= JME_CSUM_FEATURES;
2054179337Syongari				else
2055179337Syongari					ifp->if_hwassist &= ~JME_CSUM_FEATURES;
2056179337Syongari			}
2057179337Syongari		}
2058179337Syongari		if ((mask & IFCAP_RXCSUM) != 0 &&
2059179337Syongari		    (IFCAP_RXCSUM & ifp->if_capabilities) != 0) {
2060179337Syongari			ifp->if_capenable ^= IFCAP_RXCSUM;
2061179337Syongari			reg = CSR_READ_4(sc, JME_RXMAC);
2062179337Syongari			reg &= ~RXMAC_CSUM_ENB;
2063179337Syongari			if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
2064179337Syongari				reg |= RXMAC_CSUM_ENB;
2065179337Syongari			CSR_WRITE_4(sc, JME_RXMAC, reg);
2066179337Syongari		}
2067179337Syongari		if ((mask & IFCAP_TSO4) != 0 &&
2068179337Syongari		    ifp->if_mtu < JME_TX_FIFO_SIZE) {
2069179337Syongari			if ((IFCAP_TSO4 & ifp->if_capabilities) != 0) {
2070179337Syongari				ifp->if_capenable ^= IFCAP_TSO4;
2071179337Syongari				if ((IFCAP_TSO4 & ifp->if_capenable) != 0)
2072179337Syongari					ifp->if_hwassist |= CSUM_TSO;
2073179337Syongari				else
2074179337Syongari					ifp->if_hwassist &= ~CSUM_TSO;
2075179337Syongari			}
2076179337Syongari		}
2077179337Syongari		if ((mask & IFCAP_WOL_MAGIC) != 0 &&
2078179337Syongari		    (IFCAP_WOL_MAGIC & ifp->if_capabilities) != 0)
2079179337Syongari			ifp->if_capenable ^= IFCAP_WOL_MAGIC;
2080179337Syongari		if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
2081179337Syongari		    (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0)
2082179337Syongari			ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
2083204225Syongari		if ((mask & IFCAP_VLAN_HWTSO) != 0 &&
2084204225Syongari		    (ifp->if_capabilities & IFCAP_VLAN_HWTSO) != 0)
2085204225Syongari			ifp->if_capenable ^= IFCAP_VLAN_HWTSO;
2086179337Syongari		if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
2087179337Syongari		    (IFCAP_VLAN_HWTAGGING & ifp->if_capabilities) != 0) {
2088179337Syongari			ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
2089179337Syongari			jme_set_vlan(sc);
2090179337Syongari		}
2091179337Syongari		JME_UNLOCK(sc);
2092179337Syongari		VLAN_CAPABILITIES(ifp);
2093179337Syongari		break;
2094179337Syongari	default:
2095179337Syongari		error = ether_ioctl(ifp, cmd, data);
2096179337Syongari		break;
2097179337Syongari	}
2098179337Syongari
2099179337Syongari	return (error);
2100179337Syongari}
2101179337Syongari
2102179337Syongaristatic void
2103179337Syongarijme_mac_config(struct jme_softc *sc)
2104179337Syongari{
2105179337Syongari	struct mii_data *mii;
2106183264Syongari	uint32_t ghc, gpreg, rxmac, txmac, txpause;
2107185596Syongari	uint32_t txclk;
2108179337Syongari
2109179337Syongari	JME_LOCK_ASSERT(sc);
2110179337Syongari
2111179337Syongari	mii = device_get_softc(sc->jme_miibus);
2112179337Syongari
2113179337Syongari	CSR_WRITE_4(sc, JME_GHC, GHC_RESET);
2114179337Syongari	DELAY(10);
2115179337Syongari	CSR_WRITE_4(sc, JME_GHC, 0);
2116179337Syongari	ghc = 0;
2117185596Syongari	txclk = 0;
2118179337Syongari	rxmac = CSR_READ_4(sc, JME_RXMAC);
2119179337Syongari	rxmac &= ~RXMAC_FC_ENB;
2120179337Syongari	txmac = CSR_READ_4(sc, JME_TXMAC);
2121179337Syongari	txmac &= ~(TXMAC_CARRIER_EXT | TXMAC_FRAME_BURST);
2122179337Syongari	txpause = CSR_READ_4(sc, JME_TXPFC);
2123179337Syongari	txpause &= ~TXPFC_PAUSE_ENB;
2124179337Syongari	if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0) {
2125179337Syongari		ghc |= GHC_FULL_DUPLEX;
2126179337Syongari		rxmac &= ~RXMAC_COLL_DET_ENB;
2127179337Syongari		txmac &= ~(TXMAC_COLL_ENB | TXMAC_CARRIER_SENSE |
2128179337Syongari		    TXMAC_BACKOFF | TXMAC_CARRIER_EXT |
2129179337Syongari		    TXMAC_FRAME_BURST);
2130179337Syongari		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_TXPAUSE) != 0)
2131179337Syongari			txpause |= TXPFC_PAUSE_ENB;
2132179337Syongari		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_ETH_RXPAUSE) != 0)
2133179337Syongari			rxmac |= RXMAC_FC_ENB;
2134179337Syongari		/* Disable retry transmit timer/retry limit. */
2135179337Syongari		CSR_WRITE_4(sc, JME_TXTRHD, CSR_READ_4(sc, JME_TXTRHD) &
2136179337Syongari		    ~(TXTRHD_RT_PERIOD_ENB | TXTRHD_RT_LIMIT_ENB));
2137179337Syongari	} else {
2138179337Syongari		rxmac |= RXMAC_COLL_DET_ENB;
2139179337Syongari		txmac |= TXMAC_COLL_ENB | TXMAC_CARRIER_SENSE | TXMAC_BACKOFF;
2140179337Syongari		/* Enable retry transmit timer/retry limit. */
2141179337Syongari		CSR_WRITE_4(sc, JME_TXTRHD, CSR_READ_4(sc, JME_TXTRHD) |
2142179337Syongari		    TXTRHD_RT_PERIOD_ENB | TXTRHD_RT_LIMIT_ENB);
2143179337Syongari	}
2144179337Syongari		/* Reprogram Tx/Rx MACs with resolved speed/duplex. */
2145179337Syongari	switch (IFM_SUBTYPE(mii->mii_media_active)) {
2146179337Syongari	case IFM_10_T:
2147179337Syongari		ghc |= GHC_SPEED_10;
2148185596Syongari		txclk |= GHC_TX_OFFLD_CLK_100 | GHC_TX_MAC_CLK_100;
2149179337Syongari		break;
2150179337Syongari	case IFM_100_TX:
2151179337Syongari		ghc |= GHC_SPEED_100;
2152185596Syongari		txclk |= GHC_TX_OFFLD_CLK_100 | GHC_TX_MAC_CLK_100;
2153179337Syongari		break;
2154179337Syongari	case IFM_1000_T:
2155179337Syongari		if ((sc->jme_flags & JME_FLAG_FASTETH) != 0)
2156179337Syongari			break;
2157179337Syongari		ghc |= GHC_SPEED_1000;
2158185596Syongari		txclk |= GHC_TX_OFFLD_CLK_1000 | GHC_TX_MAC_CLK_1000;
2159179337Syongari		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) == 0)
2160179337Syongari			txmac |= TXMAC_CARRIER_EXT | TXMAC_FRAME_BURST;
2161179337Syongari		break;
2162179337Syongari	default:
2163179337Syongari		break;
2164179337Syongari	}
2165182888Syongari	if (sc->jme_rev == DEVICEID_JMC250 &&
2166182888Syongari	    sc->jme_chip_rev == DEVICEREVID_JMC250_A2) {
2167183264Syongari		/*
2168183264Syongari		 * Workaround occasional packet loss issue of JMC250 A2
2169183264Syongari		 * when it runs on half-duplex media.
2170183264Syongari		 */
2171183264Syongari		gpreg = CSR_READ_4(sc, JME_GPREG1);
2172183264Syongari		if ((IFM_OPTIONS(mii->mii_media_active) & IFM_FDX) != 0)
2173183264Syongari			gpreg &= ~GPREG1_HDPX_FIX;
2174183264Syongari		else
2175183264Syongari			gpreg |= GPREG1_HDPX_FIX;
2176183264Syongari		CSR_WRITE_4(sc, JME_GPREG1, gpreg);
2177183264Syongari		/* Workaround CRC errors at 100Mbps on JMC250 A2. */
2178182888Syongari		if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {
2179182888Syongari			/* Extend interface FIFO depth. */
2180182888Syongari			jme_miibus_writereg(sc->jme_dev, sc->jme_phyaddr,
2181182888Syongari			    0x1B, 0x0000);
2182182888Syongari		} else {
2183182888Syongari			/* Select default interface FIFO depth. */
2184182888Syongari			jme_miibus_writereg(sc->jme_dev, sc->jme_phyaddr,
2185182888Syongari			    0x1B, 0x0004);
2186182888Syongari		}
2187182888Syongari	}
2188185596Syongari	if ((sc->jme_flags & JME_FLAG_TXCLK) != 0)
2189185596Syongari		ghc |= txclk;
2190179337Syongari	CSR_WRITE_4(sc, JME_GHC, ghc);
2191179337Syongari	CSR_WRITE_4(sc, JME_RXMAC, rxmac);
2192179337Syongari	CSR_WRITE_4(sc, JME_TXMAC, txmac);
2193179337Syongari	CSR_WRITE_4(sc, JME_TXPFC, txpause);
2194179337Syongari}
2195179337Syongari
2196179337Syongaristatic void
2197179337Syongarijme_link_task(void *arg, int pending)
2198179337Syongari{
2199179337Syongari	struct jme_softc *sc;
2200179337Syongari	struct mii_data *mii;
2201179337Syongari	struct ifnet *ifp;
2202179337Syongari	struct jme_txdesc *txd;
2203179337Syongari	bus_addr_t paddr;
2204179337Syongari	int i;
2205179337Syongari
2206179337Syongari	sc = (struct jme_softc *)arg;
2207179337Syongari
2208179337Syongari	JME_LOCK(sc);
2209179337Syongari	mii = device_get_softc(sc->jme_miibus);
2210179337Syongari	ifp = sc->jme_ifp;
2211179337Syongari	if (mii == NULL || ifp == NULL ||
2212179337Syongari	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
2213179337Syongari		JME_UNLOCK(sc);
2214179337Syongari		return;
2215179337Syongari	}
2216179337Syongari
2217179337Syongari	sc->jme_flags &= ~JME_FLAG_LINK;
2218179337Syongari	if ((mii->mii_media_status & IFM_AVALID) != 0) {
2219179337Syongari		switch (IFM_SUBTYPE(mii->mii_media_active)) {
2220179337Syongari		case IFM_10_T:
2221179337Syongari		case IFM_100_TX:
2222179337Syongari			sc->jme_flags |= JME_FLAG_LINK;
2223179337Syongari			break;
2224179337Syongari		case IFM_1000_T:
2225180582Syongari			if ((sc->jme_flags & JME_FLAG_FASTETH) != 0)
2226179337Syongari				break;
2227179337Syongari			sc->jme_flags |= JME_FLAG_LINK;
2228179337Syongari			break;
2229179337Syongari		default:
2230179337Syongari			break;
2231179337Syongari		}
2232179337Syongari	}
2233179337Syongari
2234179337Syongari	/*
2235179337Syongari	 * Disabling Rx/Tx MACs have a side-effect of resetting
2236179337Syongari	 * JME_TXNDA/JME_RXNDA register to the first address of
2237179337Syongari	 * Tx/Rx descriptor address. So driver should reset its
2238179337Syongari	 * internal procucer/consumer pointer and reclaim any
2239179337Syongari	 * allocated resources. Note, just saving the value of
2240179337Syongari	 * JME_TXNDA and JME_RXNDA registers before stopping MAC
2241179337Syongari	 * and restoring JME_TXNDA/JME_RXNDA register is not
2242179337Syongari	 * sufficient to make sure correct MAC state because
2243179337Syongari	 * stopping MAC operation can take a while and hardware
2244179337Syongari	 * might have updated JME_TXNDA/JME_RXNDA registers
2245179337Syongari	 * during the stop operation.
2246179337Syongari	 */
2247179337Syongari	/* Block execution of task. */
2248179337Syongari	taskqueue_block(sc->jme_tq);
2249179337Syongari	/* Disable interrupts and stop driver. */
2250179337Syongari	CSR_WRITE_4(sc, JME_INTR_MASK_CLR, JME_INTRS);
2251179337Syongari	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
2252179337Syongari	callout_stop(&sc->jme_tick_ch);
2253179337Syongari	sc->jme_watchdog_timer = 0;
2254179337Syongari
2255179337Syongari	/* Stop receiver/transmitter. */
2256179337Syongari	jme_stop_rx(sc);
2257179337Syongari	jme_stop_tx(sc);
2258179337Syongari
2259179337Syongari	/* XXX Drain all queued tasks. */
2260179337Syongari	JME_UNLOCK(sc);
2261179337Syongari	taskqueue_drain(sc->jme_tq, &sc->jme_int_task);
2262179337Syongari	JME_LOCK(sc);
2263179337Syongari
2264179337Syongari	if (sc->jme_cdata.jme_rxhead != NULL)
2265179337Syongari		m_freem(sc->jme_cdata.jme_rxhead);
2266179337Syongari	JME_RXCHAIN_RESET(sc);
2267179337Syongari	jme_txeof(sc);
2268179337Syongari	if (sc->jme_cdata.jme_tx_cnt != 0) {
2269179337Syongari		/* Remove queued packets for transmit. */
2270179337Syongari		for (i = 0; i < JME_TX_RING_CNT; i++) {
2271179337Syongari			txd = &sc->jme_cdata.jme_txdesc[i];
2272179337Syongari			if (txd->tx_m != NULL) {
2273179337Syongari				bus_dmamap_sync(
2274179337Syongari				    sc->jme_cdata.jme_tx_tag,
2275179337Syongari				    txd->tx_dmamap,
2276179337Syongari				    BUS_DMASYNC_POSTWRITE);
2277179337Syongari				bus_dmamap_unload(
2278179337Syongari				    sc->jme_cdata.jme_tx_tag,
2279179337Syongari				    txd->tx_dmamap);
2280179337Syongari				m_freem(txd->tx_m);
2281179337Syongari				txd->tx_m = NULL;
2282179337Syongari				txd->tx_ndesc = 0;
2283272066Sglebius				if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2284179337Syongari			}
2285179337Syongari		}
2286179337Syongari	}
2287179337Syongari
2288179337Syongari	/*
2289179337Syongari	 * Reuse configured Rx descriptors and reset
2290217353Sjhb	 * producer/consumer index.
2291179337Syongari	 */
2292179337Syongari	sc->jme_cdata.jme_rx_cons = 0;
2293216362Syongari	sc->jme_morework = 0;
2294179337Syongari	jme_init_tx_ring(sc);
2295179337Syongari	/* Initialize shadow status block. */
2296179337Syongari	jme_init_ssb(sc);
2297179337Syongari
2298179337Syongari	/* Program MAC with resolved speed/duplex/flow-control. */
2299179337Syongari	if ((sc->jme_flags & JME_FLAG_LINK) != 0) {
2300179337Syongari		jme_mac_config(sc);
2301185597Syongari		jme_stats_clear(sc);
2302179337Syongari
2303179337Syongari		CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr);
2304179337Syongari		CSR_WRITE_4(sc, JME_TXCSR, sc->jme_txcsr);
2305179337Syongari
2306179337Syongari		/* Set Tx ring address to the hardware. */
2307179337Syongari		paddr = JME_TX_RING_ADDR(sc, 0);
2308179337Syongari		CSR_WRITE_4(sc, JME_TXDBA_HI, JME_ADDR_HI(paddr));
2309179337Syongari		CSR_WRITE_4(sc, JME_TXDBA_LO, JME_ADDR_LO(paddr));
2310179337Syongari
2311179337Syongari		/* Set Rx ring address to the hardware. */
2312179337Syongari		paddr = JME_RX_RING_ADDR(sc, 0);
2313179337Syongari		CSR_WRITE_4(sc, JME_RXDBA_HI, JME_ADDR_HI(paddr));
2314179337Syongari		CSR_WRITE_4(sc, JME_RXDBA_LO, JME_ADDR_LO(paddr));
2315179337Syongari
2316179337Syongari		/* Restart receiver/transmitter. */
2317179337Syongari		CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr | RXCSR_RX_ENB |
2318179337Syongari		    RXCSR_RXQ_START);
2319179337Syongari		CSR_WRITE_4(sc, JME_TXCSR, sc->jme_txcsr | TXCSR_TX_ENB);
2320216551Syongari		/* Lastly enable TX/RX clock. */
2321216551Syongari		if ((sc->jme_flags & JME_FLAG_TXCLK) != 0)
2322216551Syongari			CSR_WRITE_4(sc, JME_GHC,
2323216551Syongari			    CSR_READ_4(sc, JME_GHC) & ~GHC_TX_MAC_CLK_DIS);
2324216551Syongari		if ((sc->jme_flags & JME_FLAG_RXCLK) != 0)
2325216551Syongari			CSR_WRITE_4(sc, JME_GPREG1,
2326216551Syongari			    CSR_READ_4(sc, JME_GPREG1) & ~GPREG1_RX_MAC_CLK_DIS);
2327179337Syongari	}
2328179337Syongari
2329179337Syongari	ifp->if_drv_flags |= IFF_DRV_RUNNING;
2330179337Syongari	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2331179337Syongari	callout_reset(&sc->jme_tick_ch, hz, jme_tick, sc);
2332179337Syongari	/* Unblock execution of task. */
2333179337Syongari	taskqueue_unblock(sc->jme_tq);
2334179337Syongari	/* Reenable interrupts. */
2335179337Syongari	CSR_WRITE_4(sc, JME_INTR_MASK_SET, JME_INTRS);
2336179337Syongari
2337179337Syongari	JME_UNLOCK(sc);
2338179337Syongari}
2339179337Syongari
2340179337Syongaristatic int
2341179337Syongarijme_intr(void *arg)
2342179337Syongari{
2343179337Syongari	struct jme_softc *sc;
2344179337Syongari	uint32_t status;
2345179337Syongari
2346179337Syongari	sc = (struct jme_softc *)arg;
2347179337Syongari
2348179337Syongari	status = CSR_READ_4(sc, JME_INTR_REQ_STATUS);
2349179337Syongari	if (status == 0 || status == 0xFFFFFFFF)
2350179337Syongari		return (FILTER_STRAY);
2351179337Syongari	/* Disable interrupts. */
2352179337Syongari	CSR_WRITE_4(sc, JME_INTR_MASK_CLR, JME_INTRS);
2353179337Syongari	taskqueue_enqueue(sc->jme_tq, &sc->jme_int_task);
2354179337Syongari
2355179337Syongari	return (FILTER_HANDLED);
2356179337Syongari}
2357179337Syongari
2358179337Syongaristatic void
2359179337Syongarijme_int_task(void *arg, int pending)
2360179337Syongari{
2361179337Syongari	struct jme_softc *sc;
2362179337Syongari	struct ifnet *ifp;
2363179337Syongari	uint32_t status;
2364179337Syongari	int more;
2365179337Syongari
2366179337Syongari	sc = (struct jme_softc *)arg;
2367179337Syongari	ifp = sc->jme_ifp;
2368179337Syongari
2369217353Sjhb	JME_LOCK(sc);
2370179337Syongari	status = CSR_READ_4(sc, JME_INTR_STATUS);
2371216362Syongari	if (sc->jme_morework != 0) {
2372216362Syongari		sc->jme_morework = 0;
2373179337Syongari		status |= INTR_RXQ_COAL | INTR_RXQ_COAL_TO;
2374179337Syongari	}
2375179337Syongari	if ((status & JME_INTRS) == 0 || status == 0xFFFFFFFF)
2376179337Syongari		goto done;
2377179337Syongari	/* Reset PCC counter/timer and Ack interrupts. */
2378179337Syongari	status &= ~(INTR_TXQ_COMP | INTR_RXQ_COMP);
2379179337Syongari	if ((status & (INTR_TXQ_COAL | INTR_TXQ_COAL_TO)) != 0)
2380179337Syongari		status |= INTR_TXQ_COAL | INTR_TXQ_COAL_TO | INTR_TXQ_COMP;
2381179337Syongari	if ((status & (INTR_RXQ_COAL | INTR_RXQ_COAL_TO)) != 0)
2382179337Syongari		status |= INTR_RXQ_COAL | INTR_RXQ_COAL_TO | INTR_RXQ_COMP;
2383179337Syongari	CSR_WRITE_4(sc, JME_INTR_STATUS, status);
2384179337Syongari	more = 0;
2385179337Syongari	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0) {
2386179337Syongari		if ((status & (INTR_RXQ_COAL | INTR_RXQ_COAL_TO)) != 0) {
2387179337Syongari			more = jme_rxintr(sc, sc->jme_process_limit);
2388179337Syongari			if (more != 0)
2389216362Syongari				sc->jme_morework = 1;
2390179337Syongari		}
2391179337Syongari		if ((status & INTR_RXQ_DESC_EMPTY) != 0) {
2392179337Syongari			/*
2393179337Syongari			 * Notify hardware availability of new Rx
2394179337Syongari			 * buffers.
2395179337Syongari			 * Reading RXCSR takes very long time under
2396179337Syongari			 * heavy load so cache RXCSR value and writes
2397179337Syongari			 * the ORed value with the kick command to
2398179337Syongari			 * the RXCSR. This saves one register access
2399179337Syongari			 * cycle.
2400179337Syongari			 */
2401179337Syongari			CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr |
2402179337Syongari			    RXCSR_RX_ENB | RXCSR_RXQ_START);
2403179337Syongari		}
2404179337Syongari		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
2405217353Sjhb			jme_start_locked(ifp);
2406179337Syongari	}
2407179337Syongari
2408179337Syongari	if (more != 0 || (CSR_READ_4(sc, JME_INTR_STATUS) & JME_INTRS) != 0) {
2409179337Syongari		taskqueue_enqueue(sc->jme_tq, &sc->jme_int_task);
2410217353Sjhb		JME_UNLOCK(sc);
2411179337Syongari		return;
2412179337Syongari	}
2413179337Syongaridone:
2414217353Sjhb	JME_UNLOCK(sc);
2415217353Sjhb
2416179337Syongari	/* Reenable interrupts. */
2417179337Syongari	CSR_WRITE_4(sc, JME_INTR_MASK_SET, JME_INTRS);
2418179337Syongari}
2419179337Syongari
2420179337Syongaristatic void
2421179337Syongarijme_txeof(struct jme_softc *sc)
2422179337Syongari{
2423179337Syongari	struct ifnet *ifp;
2424179337Syongari	struct jme_txdesc *txd;
2425179337Syongari	uint32_t status;
2426179337Syongari	int cons, nsegs;
2427179337Syongari
2428179337Syongari	JME_LOCK_ASSERT(sc);
2429179337Syongari
2430179337Syongari	ifp = sc->jme_ifp;
2431179337Syongari
2432179337Syongari	cons = sc->jme_cdata.jme_tx_cons;
2433179337Syongari	if (cons == sc->jme_cdata.jme_tx_prod)
2434179337Syongari		return;
2435179337Syongari
2436179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_tx_ring_tag,
2437179337Syongari	    sc->jme_cdata.jme_tx_ring_map,
2438179337Syongari	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2439179337Syongari
2440179337Syongari	/*
2441179337Syongari	 * Go through our Tx list and free mbufs for those
2442179337Syongari	 * frames which have been transmitted.
2443179337Syongari	 */
2444179337Syongari	for (; cons != sc->jme_cdata.jme_tx_prod;) {
2445179337Syongari		txd = &sc->jme_cdata.jme_txdesc[cons];
2446179337Syongari		status = le32toh(txd->tx_desc->flags);
2447179337Syongari		if ((status & JME_TD_OWN) == JME_TD_OWN)
2448179337Syongari			break;
2449179337Syongari
2450179337Syongari		if ((status & (JME_TD_TMOUT | JME_TD_RETRY_EXP)) != 0)
2451272066Sglebius			if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
2452179337Syongari		else {
2453272066Sglebius			if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2454179337Syongari			if ((status & JME_TD_COLLISION) != 0)
2455272066Sglebius				if_inc_counter(ifp, IFCOUNTER_COLLISIONS,
2456179337Syongari				    le32toh(txd->tx_desc->buflen) &
2457272066Sglebius				    JME_TD_BUF_LEN_MASK);
2458179337Syongari		}
2459179337Syongari		/*
2460179337Syongari		 * Only the first descriptor of multi-descriptor
2461179337Syongari		 * transmission is updated so driver have to skip entire
2462179337Syongari		 * chained buffers for the transmiited frame. In other
2463179337Syongari		 * words, JME_TD_OWN bit is valid only at the first
2464179337Syongari		 * descriptor of a multi-descriptor transmission.
2465179337Syongari		 */
2466179337Syongari		for (nsegs = 0; nsegs < txd->tx_ndesc; nsegs++) {
2467179337Syongari			sc->jme_rdata.jme_tx_ring[cons].flags = 0;
2468179337Syongari			JME_DESC_INC(cons, JME_TX_RING_CNT);
2469179337Syongari		}
2470179337Syongari
2471179337Syongari		/* Reclaim transferred mbufs. */
2472179337Syongari		bus_dmamap_sync(sc->jme_cdata.jme_tx_tag, txd->tx_dmamap,
2473179337Syongari		    BUS_DMASYNC_POSTWRITE);
2474179337Syongari		bus_dmamap_unload(sc->jme_cdata.jme_tx_tag, txd->tx_dmamap);
2475179337Syongari
2476179337Syongari		KASSERT(txd->tx_m != NULL,
2477179337Syongari		    ("%s: freeing NULL mbuf!\n", __func__));
2478179337Syongari		m_freem(txd->tx_m);
2479179337Syongari		txd->tx_m = NULL;
2480179337Syongari		sc->jme_cdata.jme_tx_cnt -= txd->tx_ndesc;
2481179337Syongari		KASSERT(sc->jme_cdata.jme_tx_cnt >= 0,
2482179337Syongari		    ("%s: Active Tx desc counter was garbled\n", __func__));
2483179337Syongari		txd->tx_ndesc = 0;
2484179337Syongari		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2485179337Syongari	}
2486179337Syongari	sc->jme_cdata.jme_tx_cons = cons;
2487179337Syongari	/* Unarm watchog timer when there is no pending descriptors in queue. */
2488179337Syongari	if (sc->jme_cdata.jme_tx_cnt == 0)
2489179337Syongari		sc->jme_watchdog_timer = 0;
2490179337Syongari
2491179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_tx_ring_tag,
2492179337Syongari	    sc->jme_cdata.jme_tx_ring_map,
2493179337Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2494179337Syongari}
2495179337Syongari
2496179337Syongaristatic __inline void
2497179337Syongarijme_discard_rxbuf(struct jme_softc *sc, int cons)
2498179337Syongari{
2499179337Syongari	struct jme_desc *desc;
2500179337Syongari
2501179337Syongari	desc = &sc->jme_rdata.jme_rx_ring[cons];
2502179337Syongari	desc->flags = htole32(JME_RD_OWN | JME_RD_INTR | JME_RD_64BIT);
2503179337Syongari	desc->buflen = htole32(MCLBYTES);
2504179337Syongari}
2505179337Syongari
2506179337Syongari/* Receive a frame. */
2507179337Syongaristatic void
2508179337Syongarijme_rxeof(struct jme_softc *sc)
2509179337Syongari{
2510179337Syongari	struct ifnet *ifp;
2511179337Syongari	struct jme_desc *desc;
2512179337Syongari	struct jme_rxdesc *rxd;
2513179337Syongari	struct mbuf *mp, *m;
2514179337Syongari	uint32_t flags, status;
2515179337Syongari	int cons, count, nsegs;
2516179337Syongari
2517217353Sjhb	JME_LOCK_ASSERT(sc);
2518217353Sjhb
2519179337Syongari	ifp = sc->jme_ifp;
2520179337Syongari
2521179337Syongari	cons = sc->jme_cdata.jme_rx_cons;
2522179337Syongari	desc = &sc->jme_rdata.jme_rx_ring[cons];
2523179337Syongari	flags = le32toh(desc->flags);
2524179337Syongari	status = le32toh(desc->buflen);
2525179337Syongari	nsegs = JME_RX_NSEGS(status);
2526179337Syongari	sc->jme_cdata.jme_rxlen = JME_RX_BYTES(status) - JME_RX_PAD_BYTES;
2527179337Syongari	if ((status & JME_RX_ERR_STAT) != 0) {
2528272066Sglebius		if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2529179337Syongari		jme_discard_rxbuf(sc, sc->jme_cdata.jme_rx_cons);
2530179337Syongari#ifdef JME_SHOW_ERRORS
2531179337Syongari		device_printf(sc->jme_dev, "%s : receive error = 0x%b\n",
2532179337Syongari		    __func__, JME_RX_ERR(status), JME_RX_ERR_BITS);
2533179337Syongari#endif
2534179337Syongari		sc->jme_cdata.jme_rx_cons += nsegs;
2535179337Syongari		sc->jme_cdata.jme_rx_cons %= JME_RX_RING_CNT;
2536179337Syongari		return;
2537179337Syongari	}
2538179337Syongari
2539179337Syongari	for (count = 0; count < nsegs; count++,
2540179337Syongari	    JME_DESC_INC(cons, JME_RX_RING_CNT)) {
2541179337Syongari		rxd = &sc->jme_cdata.jme_rxdesc[cons];
2542179337Syongari		mp = rxd->rx_m;
2543179337Syongari		/* Add a new receive buffer to the ring. */
2544179337Syongari		if (jme_newbuf(sc, rxd) != 0) {
2545272066Sglebius			if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2546179337Syongari			/* Reuse buffer. */
2547180869Syongari			for (; count < nsegs; count++) {
2548180869Syongari				jme_discard_rxbuf(sc, cons);
2549180869Syongari				JME_DESC_INC(cons, JME_RX_RING_CNT);
2550180869Syongari			}
2551179337Syongari			if (sc->jme_cdata.jme_rxhead != NULL) {
2552179337Syongari				m_freem(sc->jme_cdata.jme_rxhead);
2553179337Syongari				JME_RXCHAIN_RESET(sc);
2554179337Syongari			}
2555179337Syongari			break;
2556179337Syongari		}
2557179337Syongari
2558179337Syongari		/*
2559179337Syongari		 * Assume we've received a full sized frame.
2560179337Syongari		 * Actual size is fixed when we encounter the end of
2561179337Syongari		 * multi-segmented frame.
2562179337Syongari		 */
2563179337Syongari		mp->m_len = MCLBYTES;
2564179337Syongari
2565179337Syongari		/* Chain received mbufs. */
2566179337Syongari		if (sc->jme_cdata.jme_rxhead == NULL) {
2567179337Syongari			sc->jme_cdata.jme_rxhead = mp;
2568179337Syongari			sc->jme_cdata.jme_rxtail = mp;
2569179337Syongari		} else {
2570179337Syongari			/*
2571179337Syongari			 * Receive processor can receive a maximum frame
2572179337Syongari			 * size of 65535 bytes.
2573179337Syongari			 */
2574179337Syongari			mp->m_flags &= ~M_PKTHDR;
2575179337Syongari			sc->jme_cdata.jme_rxtail->m_next = mp;
2576179337Syongari			sc->jme_cdata.jme_rxtail = mp;
2577179337Syongari		}
2578179337Syongari
2579179337Syongari		if (count == nsegs - 1) {
2580179337Syongari			/* Last desc. for this frame. */
2581179337Syongari			m = sc->jme_cdata.jme_rxhead;
2582179337Syongari			m->m_flags |= M_PKTHDR;
2583179337Syongari			m->m_pkthdr.len = sc->jme_cdata.jme_rxlen;
2584179337Syongari			if (nsegs > 1) {
2585179337Syongari				/* Set first mbuf size. */
2586179337Syongari				m->m_len = MCLBYTES - JME_RX_PAD_BYTES;
2587179337Syongari				/* Set last mbuf size. */
2588179337Syongari				mp->m_len = sc->jme_cdata.jme_rxlen -
2589179337Syongari				    ((MCLBYTES - JME_RX_PAD_BYTES) +
2590179337Syongari				    (MCLBYTES * (nsegs - 2)));
2591179337Syongari			} else
2592179337Syongari				m->m_len = sc->jme_cdata.jme_rxlen;
2593179337Syongari			m->m_pkthdr.rcvif = ifp;
2594179337Syongari
2595179337Syongari			/*
2596179337Syongari			 * Account for 10bytes auto padding which is used
2597179337Syongari			 * to align IP header on 32bit boundary. Also note,
2598179337Syongari			 * CRC bytes is automatically removed by the
2599179337Syongari			 * hardware.
2600179337Syongari			 */
2601179337Syongari			m->m_data += JME_RX_PAD_BYTES;
2602179337Syongari
2603179337Syongari			/* Set checksum information. */
2604179337Syongari			if ((ifp->if_capenable & IFCAP_RXCSUM) != 0 &&
2605179337Syongari			    (flags & JME_RD_IPV4) != 0) {
2606179337Syongari				m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
2607179337Syongari				if ((flags & JME_RD_IPCSUM) != 0)
2608179337Syongari					m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
2609179337Syongari				if (((flags & JME_RD_MORE_FRAG) == 0) &&
2610179337Syongari				    ((flags & (JME_RD_TCP | JME_RD_TCPCSUM)) ==
2611179337Syongari				    (JME_RD_TCP | JME_RD_TCPCSUM) ||
2612179337Syongari				    (flags & (JME_RD_UDP | JME_RD_UDPCSUM)) ==
2613179337Syongari				    (JME_RD_UDP | JME_RD_UDPCSUM))) {
2614179337Syongari					m->m_pkthdr.csum_flags |=
2615179337Syongari					    CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
2616179337Syongari					m->m_pkthdr.csum_data = 0xffff;
2617179337Syongari				}
2618179337Syongari			}
2619179337Syongari
2620179337Syongari			/* Check for VLAN tagged packets. */
2621179337Syongari			if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0 &&
2622179337Syongari			    (flags & JME_RD_VLAN_TAG) != 0) {
2623179337Syongari				m->m_pkthdr.ether_vtag =
2624179337Syongari				    flags & JME_RD_VLAN_MASK;
2625179337Syongari				m->m_flags |= M_VLANTAG;
2626179337Syongari			}
2627179337Syongari
2628272066Sglebius			if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
2629179337Syongari			/* Pass it on. */
2630217353Sjhb			JME_UNLOCK(sc);
2631179337Syongari			(*ifp->if_input)(ifp, m);
2632217353Sjhb			JME_LOCK(sc);
2633179337Syongari
2634179337Syongari			/* Reset mbuf chains. */
2635179337Syongari			JME_RXCHAIN_RESET(sc);
2636179337Syongari		}
2637179337Syongari	}
2638179337Syongari
2639179337Syongari	sc->jme_cdata.jme_rx_cons += nsegs;
2640179337Syongari	sc->jme_cdata.jme_rx_cons %= JME_RX_RING_CNT;
2641179337Syongari}
2642179337Syongari
2643179337Syongaristatic int
2644179337Syongarijme_rxintr(struct jme_softc *sc, int count)
2645179337Syongari{
2646179337Syongari	struct jme_desc *desc;
2647179337Syongari	int nsegs, prog, pktlen;
2648179337Syongari
2649179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_rx_ring_tag,
2650179337Syongari	    sc->jme_cdata.jme_rx_ring_map,
2651179337Syongari	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2652179337Syongari
2653179337Syongari	for (prog = 0; count > 0; prog++) {
2654179337Syongari		desc = &sc->jme_rdata.jme_rx_ring[sc->jme_cdata.jme_rx_cons];
2655179337Syongari		if ((le32toh(desc->flags) & JME_RD_OWN) == JME_RD_OWN)
2656179337Syongari			break;
2657179337Syongari		if ((le32toh(desc->buflen) & JME_RD_VALID) == 0)
2658179337Syongari			break;
2659179337Syongari		nsegs = JME_RX_NSEGS(le32toh(desc->buflen));
2660179337Syongari		/*
2661179337Syongari		 * Check number of segments against received bytes.
2662179337Syongari		 * Non-matching value would indicate that hardware
2663179337Syongari		 * is still trying to update Rx descriptors. I'm not
2664179337Syongari		 * sure whether this check is needed.
2665179337Syongari		 */
2666179337Syongari		pktlen = JME_RX_BYTES(le32toh(desc->buflen));
2667298646Spfg		if (nsegs != howmany(pktlen, MCLBYTES))
2668179337Syongari			break;
2669179337Syongari		prog++;
2670179337Syongari		/* Received a frame. */
2671179337Syongari		jme_rxeof(sc);
2672179337Syongari		count -= nsegs;
2673179337Syongari	}
2674179337Syongari
2675179337Syongari	if (prog > 0)
2676179337Syongari		bus_dmamap_sync(sc->jme_cdata.jme_rx_ring_tag,
2677179337Syongari		    sc->jme_cdata.jme_rx_ring_map,
2678179337Syongari		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2679179337Syongari
2680179337Syongari	return (count > 0 ? 0 : EAGAIN);
2681179337Syongari}
2682179337Syongari
2683179337Syongaristatic void
2684179337Syongarijme_tick(void *arg)
2685179337Syongari{
2686179337Syongari	struct jme_softc *sc;
2687179337Syongari	struct mii_data *mii;
2688179337Syongari
2689179337Syongari	sc = (struct jme_softc *)arg;
2690179337Syongari
2691179337Syongari	JME_LOCK_ASSERT(sc);
2692179337Syongari
2693179337Syongari	mii = device_get_softc(sc->jme_miibus);
2694179337Syongari	mii_tick(mii);
2695179337Syongari	/*
2696179337Syongari	 * Reclaim Tx buffers that have been completed. It's not
2697179337Syongari	 * needed here but it would release allocated mbuf chains
2698179337Syongari	 * faster and limit the maximum delay to a hz.
2699179337Syongari	 */
2700179337Syongari	jme_txeof(sc);
2701185597Syongari	jme_stats_update(sc);
2702179337Syongari	jme_watchdog(sc);
2703179337Syongari	callout_reset(&sc->jme_tick_ch, hz, jme_tick, sc);
2704179337Syongari}
2705179337Syongari
2706179337Syongaristatic void
2707179337Syongarijme_reset(struct jme_softc *sc)
2708179337Syongari{
2709216551Syongari	uint32_t ghc, gpreg;
2710179337Syongari
2711179337Syongari	/* Stop receiver, transmitter. */
2712179337Syongari	jme_stop_rx(sc);
2713179337Syongari	jme_stop_tx(sc);
2714216551Syongari
2715216551Syongari	/* Reset controller. */
2716179337Syongari	CSR_WRITE_4(sc, JME_GHC, GHC_RESET);
2717216551Syongari	CSR_READ_4(sc, JME_GHC);
2718179337Syongari	DELAY(10);
2719216551Syongari	/*
2720216551Syongari	 * Workaround Rx FIFO overruns seen under certain conditions.
2721216551Syongari	 * Explicitly synchorize TX/RX clock.  TX/RX clock should be
2722216551Syongari	 * enabled only after enabling TX/RX MACs.
2723216551Syongari	 */
2724216551Syongari	if ((sc->jme_flags & (JME_FLAG_TXCLK | JME_FLAG_RXCLK)) != 0) {
2725216551Syongari		/* Disable TX clock. */
2726216551Syongari		CSR_WRITE_4(sc, JME_GHC, GHC_RESET | GHC_TX_MAC_CLK_DIS);
2727216551Syongari		/* Disable RX clock. */
2728216551Syongari		gpreg = CSR_READ_4(sc, JME_GPREG1);
2729216551Syongari		CSR_WRITE_4(sc, JME_GPREG1, gpreg | GPREG1_RX_MAC_CLK_DIS);
2730216551Syongari		gpreg = CSR_READ_4(sc, JME_GPREG1);
2731216551Syongari		/* De-assert RESET but still disable TX clock. */
2732216551Syongari		CSR_WRITE_4(sc, JME_GHC, GHC_TX_MAC_CLK_DIS);
2733216551Syongari		ghc = CSR_READ_4(sc, JME_GHC);
2734216551Syongari
2735216551Syongari		/* Enable TX clock. */
2736216551Syongari		CSR_WRITE_4(sc, JME_GHC, ghc & ~GHC_TX_MAC_CLK_DIS);
2737216551Syongari		/* Enable RX clock. */
2738216551Syongari		CSR_WRITE_4(sc, JME_GPREG1, gpreg & ~GPREG1_RX_MAC_CLK_DIS);
2739216551Syongari		CSR_READ_4(sc, JME_GPREG1);
2740216551Syongari
2741216551Syongari		/* Disable TX/RX clock again. */
2742216551Syongari		CSR_WRITE_4(sc, JME_GHC, GHC_TX_MAC_CLK_DIS);
2743216551Syongari		CSR_WRITE_4(sc, JME_GPREG1, gpreg | GPREG1_RX_MAC_CLK_DIS);
2744216551Syongari	} else
2745216551Syongari		CSR_WRITE_4(sc, JME_GHC, 0);
2746216551Syongari	CSR_READ_4(sc, JME_GHC);
2747216551Syongari	DELAY(10);
2748179337Syongari}
2749179337Syongari
2750179337Syongaristatic void
2751179337Syongarijme_init(void *xsc)
2752179337Syongari{
2753179337Syongari	struct jme_softc *sc;
2754179337Syongari
2755179337Syongari	sc = (struct jme_softc *)xsc;
2756179337Syongari	JME_LOCK(sc);
2757179337Syongari	jme_init_locked(sc);
2758179337Syongari	JME_UNLOCK(sc);
2759179337Syongari}
2760179337Syongari
2761179337Syongaristatic void
2762179337Syongarijme_init_locked(struct jme_softc *sc)
2763179337Syongari{
2764179337Syongari	struct ifnet *ifp;
2765179337Syongari	struct mii_data *mii;
2766179337Syongari	bus_addr_t paddr;
2767179337Syongari	uint32_t reg;
2768179337Syongari	int error;
2769179337Syongari
2770179337Syongari	JME_LOCK_ASSERT(sc);
2771179337Syongari
2772179337Syongari	ifp = sc->jme_ifp;
2773179337Syongari	mii = device_get_softc(sc->jme_miibus);
2774179337Syongari
2775197585Syongari	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
2776197585Syongari		return;
2777179337Syongari	/*
2778179337Syongari	 * Cancel any pending I/O.
2779179337Syongari	 */
2780179337Syongari	jme_stop(sc);
2781179337Syongari
2782179337Syongari	/*
2783179337Syongari	 * Reset the chip to a known state.
2784179337Syongari	 */
2785179337Syongari	jme_reset(sc);
2786179337Syongari
2787179337Syongari	/* Init descriptors. */
2788179337Syongari	error = jme_init_rx_ring(sc);
2789179337Syongari        if (error != 0) {
2790179337Syongari                device_printf(sc->jme_dev,
2791179337Syongari                    "%s: initialization failed: no memory for Rx buffers.\n",
2792179337Syongari		    __func__);
2793179337Syongari                jme_stop(sc);
2794179337Syongari		return;
2795179337Syongari        }
2796179337Syongari	jme_init_tx_ring(sc);
2797179337Syongari	/* Initialize shadow status block. */
2798179337Syongari	jme_init_ssb(sc);
2799179337Syongari
2800179337Syongari	/* Reprogram the station address. */
2801216551Syongari	jme_set_macaddr(sc, IF_LLADDR(sc->jme_ifp));
2802179337Syongari
2803179337Syongari	/*
2804179337Syongari	 * Configure Tx queue.
2805179337Syongari	 *  Tx priority queue weight value : 0
2806179337Syongari	 *  Tx FIFO threshold for processing next packet : 16QW
2807179337Syongari	 *  Maximum Tx DMA length : 512
2808179337Syongari	 *  Allow Tx DMA burst.
2809179337Syongari	 */
2810179337Syongari	sc->jme_txcsr = TXCSR_TXQ_N_SEL(TXCSR_TXQ0);
2811179337Syongari	sc->jme_txcsr |= TXCSR_TXQ_WEIGHT(TXCSR_TXQ_WEIGHT_MIN);
2812179337Syongari	sc->jme_txcsr |= TXCSR_FIFO_THRESH_16QW;
2813179337Syongari	sc->jme_txcsr |= sc->jme_tx_dma_size;
2814179337Syongari	sc->jme_txcsr |= TXCSR_DMA_BURST;
2815179337Syongari	CSR_WRITE_4(sc, JME_TXCSR, sc->jme_txcsr);
2816179337Syongari
2817179337Syongari	/* Set Tx descriptor counter. */
2818179337Syongari	CSR_WRITE_4(sc, JME_TXQDC, JME_TX_RING_CNT);
2819179337Syongari
2820179337Syongari	/* Set Tx ring address to the hardware. */
2821179337Syongari	paddr = JME_TX_RING_ADDR(sc, 0);
2822179337Syongari	CSR_WRITE_4(sc, JME_TXDBA_HI, JME_ADDR_HI(paddr));
2823179337Syongari	CSR_WRITE_4(sc, JME_TXDBA_LO, JME_ADDR_LO(paddr));
2824179337Syongari
2825179337Syongari	/* Configure TxMAC parameters. */
2826179337Syongari	reg = TXMAC_IFG1_DEFAULT | TXMAC_IFG2_DEFAULT | TXMAC_IFG_ENB;
2827179337Syongari	reg |= TXMAC_THRESH_1_PKT;
2828179337Syongari	reg |= TXMAC_CRC_ENB | TXMAC_PAD_ENB;
2829179337Syongari	CSR_WRITE_4(sc, JME_TXMAC, reg);
2830179337Syongari
2831179337Syongari	/*
2832179337Syongari	 * Configure Rx queue.
2833179337Syongari	 *  FIFO full threshold for transmitting Tx pause packet : 128T
2834179337Syongari	 *  FIFO threshold for processing next packet : 128QW
2835179337Syongari	 *  Rx queue 0 select
2836179337Syongari	 *  Max Rx DMA length : 128
2837179337Syongari	 *  Rx descriptor retry : 32
2838179337Syongari	 *  Rx descriptor retry time gap : 256ns
2839179337Syongari	 *  Don't receive runt/bad frame.
2840179337Syongari	 */
2841179337Syongari	sc->jme_rxcsr = RXCSR_FIFO_FTHRESH_128T;
2842179337Syongari	/*
2843179337Syongari	 * Since Rx FIFO size is 4K bytes, receiving frames larger
2844179337Syongari	 * than 4K bytes will suffer from Rx FIFO overruns. So
2845179337Syongari	 * decrease FIFO threshold to reduce the FIFO overruns for
2846179337Syongari	 * frames larger than 4000 bytes.
2847179337Syongari	 * For best performance of standard MTU sized frames use
2848185596Syongari	 * maximum allowable FIFO threshold, 128QW. Note these do
2849185596Syongari	 * not hold on chip full mask verion >=2. For these
2850185596Syongari	 * controllers 64QW and 128QW are not valid value.
2851179337Syongari	 */
2852185596Syongari	if (CHIPMODE_REVFM(sc->jme_chip_rev) >= 2)
2853179337Syongari		sc->jme_rxcsr |= RXCSR_FIFO_THRESH_16QW;
2854185596Syongari	else {
2855185596Syongari		if ((ifp->if_mtu + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +
2856185596Syongari		    ETHER_CRC_LEN) > JME_RX_FIFO_SIZE)
2857185596Syongari			sc->jme_rxcsr |= RXCSR_FIFO_THRESH_16QW;
2858185596Syongari		else
2859185596Syongari			sc->jme_rxcsr |= RXCSR_FIFO_THRESH_128QW;
2860185596Syongari	}
2861179337Syongari	sc->jme_rxcsr |= sc->jme_rx_dma_size | RXCSR_RXQ_N_SEL(RXCSR_RXQ0);
2862179337Syongari	sc->jme_rxcsr |= RXCSR_DESC_RT_CNT(RXCSR_DESC_RT_CNT_DEFAULT);
2863179337Syongari	sc->jme_rxcsr |= RXCSR_DESC_RT_GAP_256 & RXCSR_DESC_RT_GAP_MASK;
2864179337Syongari	CSR_WRITE_4(sc, JME_RXCSR, sc->jme_rxcsr);
2865179337Syongari
2866179337Syongari	/* Set Rx descriptor counter. */
2867179337Syongari	CSR_WRITE_4(sc, JME_RXQDC, JME_RX_RING_CNT);
2868179337Syongari
2869179337Syongari	/* Set Rx ring address to the hardware. */
2870179337Syongari	paddr = JME_RX_RING_ADDR(sc, 0);
2871179337Syongari	CSR_WRITE_4(sc, JME_RXDBA_HI, JME_ADDR_HI(paddr));
2872179337Syongari	CSR_WRITE_4(sc, JME_RXDBA_LO, JME_ADDR_LO(paddr));
2873179337Syongari
2874179337Syongari	/* Clear receive filter. */
2875179337Syongari	CSR_WRITE_4(sc, JME_RXMAC, 0);
2876179337Syongari	/* Set up the receive filter. */
2877179337Syongari	jme_set_filter(sc);
2878179337Syongari	jme_set_vlan(sc);
2879179337Syongari
2880179337Syongari	/*
2881179337Syongari	 * Disable all WOL bits as WOL can interfere normal Rx
2882179337Syongari	 * operation. Also clear WOL detection status bits.
2883179337Syongari	 */
2884179337Syongari	reg = CSR_READ_4(sc, JME_PMCS);
2885179337Syongari	reg &= ~PMCS_WOL_ENB_MASK;
2886179337Syongari	CSR_WRITE_4(sc, JME_PMCS, reg);
2887179337Syongari
2888179337Syongari	reg = CSR_READ_4(sc, JME_RXMAC);
2889179337Syongari	/*
2890179337Syongari	 * Pad 10bytes right before received frame. This will greatly
2891179337Syongari	 * help Rx performance on strict-alignment architectures as
2892179337Syongari	 * it does not need to copy the frame to align the payload.
2893179337Syongari	 */
2894179337Syongari	reg |= RXMAC_PAD_10BYTES;
2895179337Syongari	if ((ifp->if_capenable & IFCAP_RXCSUM) != 0)
2896179337Syongari		reg |= RXMAC_CSUM_ENB;
2897179337Syongari	CSR_WRITE_4(sc, JME_RXMAC, reg);
2898179337Syongari
2899179337Syongari	/* Configure general purpose reg0 */
2900179337Syongari	reg = CSR_READ_4(sc, JME_GPREG0);
2901179337Syongari	reg &= ~GPREG0_PCC_UNIT_MASK;
2902179337Syongari	/* Set PCC timer resolution to micro-seconds unit. */
2903179337Syongari	reg |= GPREG0_PCC_UNIT_US;
2904179337Syongari	/*
2905179337Syongari	 * Disable all shadow register posting as we have to read
2906179337Syongari	 * JME_INTR_STATUS register in jme_int_task. Also it seems
2907179337Syongari	 * that it's hard to synchronize interrupt status between
2908179337Syongari	 * hardware and software with shadow posting due to
2909179337Syongari	 * requirements of bus_dmamap_sync(9).
2910179337Syongari	 */
2911179337Syongari	reg |= GPREG0_SH_POST_DW7_DIS | GPREG0_SH_POST_DW6_DIS |
2912179337Syongari	    GPREG0_SH_POST_DW5_DIS | GPREG0_SH_POST_DW4_DIS |
2913179337Syongari	    GPREG0_SH_POST_DW3_DIS | GPREG0_SH_POST_DW2_DIS |
2914179337Syongari	    GPREG0_SH_POST_DW1_DIS | GPREG0_SH_POST_DW0_DIS;
2915179337Syongari	/* Disable posting of DW0. */
2916179337Syongari	reg &= ~GPREG0_POST_DW0_ENB;
2917179337Syongari	/* Clear PME message. */
2918179337Syongari	reg &= ~GPREG0_PME_ENB;
2919179337Syongari	/* Set PHY address. */
2920179337Syongari	reg &= ~GPREG0_PHY_ADDR_MASK;
2921179337Syongari	reg |= sc->jme_phyaddr;
2922179337Syongari	CSR_WRITE_4(sc, JME_GPREG0, reg);
2923179337Syongari
2924179337Syongari	/* Configure Tx queue 0 packet completion coalescing. */
2925179337Syongari	reg = (sc->jme_tx_coal_to << PCCTX_COAL_TO_SHIFT) &
2926179337Syongari	    PCCTX_COAL_TO_MASK;
2927179337Syongari	reg |= (sc->jme_tx_coal_pkt << PCCTX_COAL_PKT_SHIFT) &
2928179337Syongari	    PCCTX_COAL_PKT_MASK;
2929179337Syongari	reg |= PCCTX_COAL_TXQ0;
2930179337Syongari	CSR_WRITE_4(sc, JME_PCCTX, reg);
2931179337Syongari
2932179337Syongari	/* Configure Rx queue 0 packet completion coalescing. */
2933179337Syongari	reg = (sc->jme_rx_coal_to << PCCRX_COAL_TO_SHIFT) &
2934179337Syongari	    PCCRX_COAL_TO_MASK;
2935179337Syongari	reg |= (sc->jme_rx_coal_pkt << PCCRX_COAL_PKT_SHIFT) &
2936179337Syongari	    PCCRX_COAL_PKT_MASK;
2937179337Syongari	CSR_WRITE_4(sc, JME_PCCRX0, reg);
2938179337Syongari
2939216551Syongari	/*
2940216551Syongari	 * Configure PCD(Packet Completion Deferring).  It seems PCD
2941216551Syongari	 * generates an interrupt when the time interval between two
2942216551Syongari	 * back-to-back incoming/outgoing packet is long enough for
2943216551Syongari	 * it to reach its timer value 0. The arrival of new packets
2944216551Syongari	 * after timer has started causes the PCD timer to restart.
2945216551Syongari	 * Unfortunately, it's not clear how PCD is useful at this
2946216551Syongari	 * moment, so just use the same of PCC parameters.
2947216551Syongari	 */
2948216551Syongari	if ((sc->jme_flags & JME_FLAG_PCCPCD) != 0) {
2949216551Syongari		sc->jme_rx_pcd_to = sc->jme_rx_coal_to;
2950216551Syongari		if (sc->jme_rx_coal_to > PCDRX_TO_MAX)
2951216551Syongari			sc->jme_rx_pcd_to = PCDRX_TO_MAX;
2952216551Syongari		sc->jme_tx_pcd_to = sc->jme_tx_coal_to;
2953216551Syongari		if (sc->jme_tx_coal_to > PCDTX_TO_MAX)
2954216551Syongari			sc->jme_tx_pcd_to = PCDTX_TO_MAX;
2955216551Syongari		reg = sc->jme_rx_pcd_to << PCDRX0_TO_THROTTLE_SHIFT;
2956216551Syongari		reg |= sc->jme_rx_pcd_to << PCDRX0_TO_SHIFT;
2957216551Syongari		CSR_WRITE_4(sc, PCDRX_REG(0), reg);
2958216551Syongari		reg = sc->jme_tx_pcd_to << PCDTX_TO_THROTTLE_SHIFT;
2959216551Syongari		reg |= sc->jme_tx_pcd_to << PCDTX_TO_SHIFT;
2960216551Syongari		CSR_WRITE_4(sc, JME_PCDTX, reg);
2961216551Syongari	}
2962216551Syongari
2963179337Syongari	/* Configure shadow status block but don't enable posting. */
2964179337Syongari	paddr = sc->jme_rdata.jme_ssb_block_paddr;
2965179337Syongari	CSR_WRITE_4(sc, JME_SHBASE_ADDR_HI, JME_ADDR_HI(paddr));
2966179337Syongari	CSR_WRITE_4(sc, JME_SHBASE_ADDR_LO, JME_ADDR_LO(paddr));
2967179337Syongari
2968179337Syongari	/* Disable Timer 1 and Timer 2. */
2969179337Syongari	CSR_WRITE_4(sc, JME_TIMER1, 0);
2970179337Syongari	CSR_WRITE_4(sc, JME_TIMER2, 0);
2971179337Syongari
2972179337Syongari	/* Configure retry transmit period, retry limit value. */
2973179337Syongari	CSR_WRITE_4(sc, JME_TXTRHD,
2974179337Syongari	    ((TXTRHD_RT_PERIOD_DEFAULT << TXTRHD_RT_PERIOD_SHIFT) &
2975179337Syongari	    TXTRHD_RT_PERIOD_MASK) |
2976179337Syongari	    ((TXTRHD_RT_LIMIT_DEFAULT << TXTRHD_RT_LIMIT_SHIFT) &
2977179337Syongari	    TXTRHD_RT_LIMIT_SHIFT));
2978179337Syongari
2979179337Syongari	/* Disable RSS. */
2980179337Syongari	CSR_WRITE_4(sc, JME_RSSC, RSSC_DIS_RSS);
2981179337Syongari
2982179337Syongari	/* Initialize the interrupt mask. */
2983179337Syongari	CSR_WRITE_4(sc, JME_INTR_MASK_SET, JME_INTRS);
2984179337Syongari	CSR_WRITE_4(sc, JME_INTR_STATUS, 0xFFFFFFFF);
2985179337Syongari
2986179337Syongari	/*
2987179337Syongari	 * Enabling Tx/Rx DMA engines and Rx queue processing is
2988179337Syongari	 * done after detection of valid link in jme_link_task.
2989179337Syongari	 */
2990179337Syongari
2991179337Syongari	sc->jme_flags &= ~JME_FLAG_LINK;
2992179337Syongari	/* Set the current media. */
2993179337Syongari	mii_mediachg(mii);
2994179337Syongari
2995179337Syongari	callout_reset(&sc->jme_tick_ch, hz, jme_tick, sc);
2996179337Syongari
2997179337Syongari	ifp->if_drv_flags |= IFF_DRV_RUNNING;
2998179337Syongari	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2999179337Syongari}
3000179337Syongari
3001179337Syongaristatic void
3002179337Syongarijme_stop(struct jme_softc *sc)
3003179337Syongari{
3004179337Syongari	struct ifnet *ifp;
3005179337Syongari	struct jme_txdesc *txd;
3006179337Syongari	struct jme_rxdesc *rxd;
3007179337Syongari	int i;
3008179337Syongari
3009179337Syongari	JME_LOCK_ASSERT(sc);
3010179337Syongari	/*
3011179337Syongari	 * Mark the interface down and cancel the watchdog timer.
3012179337Syongari	 */
3013179337Syongari	ifp = sc->jme_ifp;
3014179337Syongari	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3015179337Syongari	sc->jme_flags &= ~JME_FLAG_LINK;
3016179337Syongari	callout_stop(&sc->jme_tick_ch);
3017179337Syongari	sc->jme_watchdog_timer = 0;
3018179337Syongari
3019179337Syongari	/*
3020179337Syongari	 * Disable interrupts.
3021179337Syongari	 */
3022179337Syongari	CSR_WRITE_4(sc, JME_INTR_MASK_CLR, JME_INTRS);
3023179337Syongari	CSR_WRITE_4(sc, JME_INTR_STATUS, 0xFFFFFFFF);
3024179337Syongari
3025179337Syongari	/* Disable updating shadow status block. */
3026179337Syongari	CSR_WRITE_4(sc, JME_SHBASE_ADDR_LO,
3027179337Syongari	    CSR_READ_4(sc, JME_SHBASE_ADDR_LO) & ~SHBASE_POST_ENB);
3028179337Syongari
3029179337Syongari	/* Stop receiver, transmitter. */
3030179337Syongari	jme_stop_rx(sc);
3031179337Syongari	jme_stop_tx(sc);
3032179337Syongari
3033179337Syongari	 /* Reclaim Rx/Tx buffers that have been completed. */
3034179337Syongari	jme_rxintr(sc, JME_RX_RING_CNT);
3035179337Syongari	if (sc->jme_cdata.jme_rxhead != NULL)
3036179337Syongari		m_freem(sc->jme_cdata.jme_rxhead);
3037179337Syongari	JME_RXCHAIN_RESET(sc);
3038179337Syongari	jme_txeof(sc);
3039179337Syongari	/*
3040179337Syongari	 * Free RX and TX mbufs still in the queues.
3041179337Syongari	 */
3042179337Syongari	for (i = 0; i < JME_RX_RING_CNT; i++) {
3043179337Syongari		rxd = &sc->jme_cdata.jme_rxdesc[i];
3044179337Syongari		if (rxd->rx_m != NULL) {
3045179337Syongari			bus_dmamap_sync(sc->jme_cdata.jme_rx_tag,
3046179337Syongari			    rxd->rx_dmamap, BUS_DMASYNC_POSTREAD);
3047179337Syongari			bus_dmamap_unload(sc->jme_cdata.jme_rx_tag,
3048179337Syongari			    rxd->rx_dmamap);
3049179337Syongari			m_freem(rxd->rx_m);
3050179337Syongari			rxd->rx_m = NULL;
3051179337Syongari		}
3052179337Syongari        }
3053179337Syongari	for (i = 0; i < JME_TX_RING_CNT; i++) {
3054179337Syongari		txd = &sc->jme_cdata.jme_txdesc[i];
3055179337Syongari		if (txd->tx_m != NULL) {
3056179337Syongari			bus_dmamap_sync(sc->jme_cdata.jme_tx_tag,
3057179337Syongari			    txd->tx_dmamap, BUS_DMASYNC_POSTWRITE);
3058179337Syongari			bus_dmamap_unload(sc->jme_cdata.jme_tx_tag,
3059179337Syongari			    txd->tx_dmamap);
3060179337Syongari			m_freem(txd->tx_m);
3061179337Syongari			txd->tx_m = NULL;
3062179337Syongari			txd->tx_ndesc = 0;
3063179337Syongari		}
3064179337Syongari        }
3065185597Syongari	jme_stats_update(sc);
3066185597Syongari	jme_stats_save(sc);
3067179337Syongari}
3068179337Syongari
3069179337Syongaristatic void
3070179337Syongarijme_stop_tx(struct jme_softc *sc)
3071179337Syongari{
3072179337Syongari	uint32_t reg;
3073179337Syongari	int i;
3074179337Syongari
3075179337Syongari	reg = CSR_READ_4(sc, JME_TXCSR);
3076179337Syongari	if ((reg & TXCSR_TX_ENB) == 0)
3077179337Syongari		return;
3078179337Syongari	reg &= ~TXCSR_TX_ENB;
3079179337Syongari	CSR_WRITE_4(sc, JME_TXCSR, reg);
3080179337Syongari	for (i = JME_TIMEOUT; i > 0; i--) {
3081179337Syongari		DELAY(1);
3082179337Syongari		if ((CSR_READ_4(sc, JME_TXCSR) & TXCSR_TX_ENB) == 0)
3083179337Syongari			break;
3084179337Syongari	}
3085179337Syongari	if (i == 0)
3086179337Syongari		device_printf(sc->jme_dev, "stopping transmitter timeout!\n");
3087179337Syongari}
3088179337Syongari
3089179337Syongaristatic void
3090179337Syongarijme_stop_rx(struct jme_softc *sc)
3091179337Syongari{
3092179337Syongari	uint32_t reg;
3093179337Syongari	int i;
3094179337Syongari
3095179337Syongari	reg = CSR_READ_4(sc, JME_RXCSR);
3096179337Syongari	if ((reg & RXCSR_RX_ENB) == 0)
3097179337Syongari		return;
3098179337Syongari	reg &= ~RXCSR_RX_ENB;
3099179337Syongari	CSR_WRITE_4(sc, JME_RXCSR, reg);
3100179337Syongari	for (i = JME_TIMEOUT; i > 0; i--) {
3101179337Syongari		DELAY(1);
3102179337Syongari		if ((CSR_READ_4(sc, JME_RXCSR) & RXCSR_RX_ENB) == 0)
3103179337Syongari			break;
3104179337Syongari	}
3105179337Syongari	if (i == 0)
3106179337Syongari		device_printf(sc->jme_dev, "stopping recevier timeout!\n");
3107179337Syongari}
3108179337Syongari
3109179337Syongaristatic void
3110179337Syongarijme_init_tx_ring(struct jme_softc *sc)
3111179337Syongari{
3112179337Syongari	struct jme_ring_data *rd;
3113179337Syongari	struct jme_txdesc *txd;
3114179337Syongari	int i;
3115179337Syongari
3116179337Syongari	sc->jme_cdata.jme_tx_prod = 0;
3117179337Syongari	sc->jme_cdata.jme_tx_cons = 0;
3118179337Syongari	sc->jme_cdata.jme_tx_cnt = 0;
3119179337Syongari
3120179337Syongari	rd = &sc->jme_rdata;
3121179337Syongari	bzero(rd->jme_tx_ring, JME_TX_RING_SIZE);
3122179337Syongari	for (i = 0; i < JME_TX_RING_CNT; i++) {
3123179337Syongari		txd = &sc->jme_cdata.jme_txdesc[i];
3124179337Syongari		txd->tx_m = NULL;
3125179337Syongari		txd->tx_desc = &rd->jme_tx_ring[i];
3126179337Syongari		txd->tx_ndesc = 0;
3127179337Syongari	}
3128179337Syongari
3129179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_tx_ring_tag,
3130179337Syongari	    sc->jme_cdata.jme_tx_ring_map,
3131179337Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3132179337Syongari}
3133179337Syongari
3134179337Syongaristatic void
3135179337Syongarijme_init_ssb(struct jme_softc *sc)
3136179337Syongari{
3137179337Syongari	struct jme_ring_data *rd;
3138179337Syongari
3139179337Syongari	rd = &sc->jme_rdata;
3140179337Syongari	bzero(rd->jme_ssb_block, JME_SSB_SIZE);
3141179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_ssb_tag, sc->jme_cdata.jme_ssb_map,
3142179337Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3143179337Syongari}
3144179337Syongari
3145179337Syongaristatic int
3146179337Syongarijme_init_rx_ring(struct jme_softc *sc)
3147179337Syongari{
3148179337Syongari	struct jme_ring_data *rd;
3149179337Syongari	struct jme_rxdesc *rxd;
3150179337Syongari	int i;
3151179337Syongari
3152179337Syongari	sc->jme_cdata.jme_rx_cons = 0;
3153179337Syongari	JME_RXCHAIN_RESET(sc);
3154216362Syongari	sc->jme_morework = 0;
3155179337Syongari
3156179337Syongari	rd = &sc->jme_rdata;
3157179337Syongari	bzero(rd->jme_rx_ring, JME_RX_RING_SIZE);
3158179337Syongari	for (i = 0; i < JME_RX_RING_CNT; i++) {
3159179337Syongari		rxd = &sc->jme_cdata.jme_rxdesc[i];
3160179337Syongari		rxd->rx_m = NULL;
3161179337Syongari		rxd->rx_desc = &rd->jme_rx_ring[i];
3162179337Syongari		if (jme_newbuf(sc, rxd) != 0)
3163179337Syongari			return (ENOBUFS);
3164179337Syongari	}
3165179337Syongari
3166179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_rx_ring_tag,
3167179337Syongari	    sc->jme_cdata.jme_rx_ring_map,
3168179337Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3169179337Syongari
3170179337Syongari	return (0);
3171179337Syongari}
3172179337Syongari
3173179337Syongaristatic int
3174179337Syongarijme_newbuf(struct jme_softc *sc, struct jme_rxdesc *rxd)
3175179337Syongari{
3176179337Syongari	struct jme_desc *desc;
3177179337Syongari	struct mbuf *m;
3178179337Syongari	bus_dma_segment_t segs[1];
3179179337Syongari	bus_dmamap_t map;
3180179337Syongari	int nsegs;
3181179337Syongari
3182243857Sglebius	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
3183179337Syongari	if (m == NULL)
3184179337Syongari		return (ENOBUFS);
3185179337Syongari	/*
3186179337Syongari	 * JMC250 has 64bit boundary alignment limitation so jme(4)
3187179337Syongari	 * takes advantage of 10 bytes padding feature of hardware
3188179337Syongari	 * in order not to copy entire frame to align IP header on
3189179337Syongari	 * 32bit boundary.
3190179337Syongari	 */
3191179337Syongari	m->m_len = m->m_pkthdr.len = MCLBYTES;
3192179337Syongari
3193179337Syongari	if (bus_dmamap_load_mbuf_sg(sc->jme_cdata.jme_rx_tag,
3194179337Syongari	    sc->jme_cdata.jme_rx_sparemap, m, segs, &nsegs, 0) != 0) {
3195179337Syongari		m_freem(m);
3196179337Syongari		return (ENOBUFS);
3197179337Syongari	}
3198179337Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
3199179337Syongari
3200179337Syongari	if (rxd->rx_m != NULL) {
3201179337Syongari		bus_dmamap_sync(sc->jme_cdata.jme_rx_tag, rxd->rx_dmamap,
3202179337Syongari		    BUS_DMASYNC_POSTREAD);
3203179337Syongari		bus_dmamap_unload(sc->jme_cdata.jme_rx_tag, rxd->rx_dmamap);
3204179337Syongari	}
3205179337Syongari	map = rxd->rx_dmamap;
3206179337Syongari	rxd->rx_dmamap = sc->jme_cdata.jme_rx_sparemap;
3207179337Syongari	sc->jme_cdata.jme_rx_sparemap = map;
3208179337Syongari	bus_dmamap_sync(sc->jme_cdata.jme_rx_tag, rxd->rx_dmamap,
3209179337Syongari	    BUS_DMASYNC_PREREAD);
3210179337Syongari	rxd->rx_m = m;
3211179337Syongari
3212179337Syongari	desc = rxd->rx_desc;
3213179337Syongari	desc->buflen = htole32(segs[0].ds_len);
3214179337Syongari	desc->addr_lo = htole32(JME_ADDR_LO(segs[0].ds_addr));
3215179337Syongari	desc->addr_hi = htole32(JME_ADDR_HI(segs[0].ds_addr));
3216179337Syongari	desc->flags = htole32(JME_RD_OWN | JME_RD_INTR | JME_RD_64BIT);
3217179337Syongari
3218179337Syongari	return (0);
3219179337Syongari}
3220179337Syongari
3221179337Syongaristatic void
3222179337Syongarijme_set_vlan(struct jme_softc *sc)
3223179337Syongari{
3224179337Syongari	struct ifnet *ifp;
3225179337Syongari	uint32_t reg;
3226179337Syongari
3227179337Syongari	JME_LOCK_ASSERT(sc);
3228179337Syongari
3229179337Syongari	ifp = sc->jme_ifp;
3230179337Syongari	reg = CSR_READ_4(sc, JME_RXMAC);
3231179337Syongari	reg &= ~RXMAC_VLAN_ENB;
3232179337Syongari	if ((ifp->if_capenable & IFCAP_VLAN_HWTAGGING) != 0)
3233179337Syongari		reg |= RXMAC_VLAN_ENB;
3234179337Syongari	CSR_WRITE_4(sc, JME_RXMAC, reg);
3235179337Syongari}
3236179337Syongari
3237179337Syongaristatic void
3238179337Syongarijme_set_filter(struct jme_softc *sc)
3239179337Syongari{
3240179337Syongari	struct ifnet *ifp;
3241179337Syongari	struct ifmultiaddr *ifma;
3242179337Syongari	uint32_t crc;
3243179337Syongari	uint32_t mchash[2];
3244179337Syongari	uint32_t rxcfg;
3245179337Syongari
3246179337Syongari	JME_LOCK_ASSERT(sc);
3247179337Syongari
3248179337Syongari	ifp = sc->jme_ifp;
3249179337Syongari
3250179337Syongari	rxcfg = CSR_READ_4(sc, JME_RXMAC);
3251179337Syongari	rxcfg &= ~ (RXMAC_BROADCAST | RXMAC_PROMISC | RXMAC_MULTICAST |
3252179337Syongari	    RXMAC_ALLMULTI);
3253179337Syongari	/* Always accept frames destined to our station address. */
3254179337Syongari	rxcfg |= RXMAC_UNICAST;
3255179337Syongari	if ((ifp->if_flags & IFF_BROADCAST) != 0)
3256179337Syongari		rxcfg |= RXMAC_BROADCAST;
3257179337Syongari	if ((ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) != 0) {
3258179337Syongari		if ((ifp->if_flags & IFF_PROMISC) != 0)
3259179337Syongari			rxcfg |= RXMAC_PROMISC;
3260179337Syongari		if ((ifp->if_flags & IFF_ALLMULTI) != 0)
3261179337Syongari			rxcfg |= RXMAC_ALLMULTI;
3262179337Syongari		CSR_WRITE_4(sc, JME_MAR0, 0xFFFFFFFF);
3263179337Syongari		CSR_WRITE_4(sc, JME_MAR1, 0xFFFFFFFF);
3264179337Syongari		CSR_WRITE_4(sc, JME_RXMAC, rxcfg);
3265179337Syongari		return;
3266179337Syongari	}
3267179337Syongari
3268179337Syongari	/*
3269179337Syongari	 * Set up the multicast address filter by passing all multicast
3270179337Syongari	 * addresses through a CRC generator, and then using the low-order
3271179337Syongari	 * 6 bits as an index into the 64 bit multicast hash table.  The
3272179337Syongari	 * high order bits select the register, while the rest of the bits
3273179337Syongari	 * select the bit within the register.
3274179337Syongari	 */
3275179337Syongari	rxcfg |= RXMAC_MULTICAST;
3276179337Syongari	bzero(mchash, sizeof(mchash));
3277179337Syongari
3278195049Srwatson	if_maddr_rlock(ifp);
3279179337Syongari	TAILQ_FOREACH(ifma, &sc->jme_ifp->if_multiaddrs, ifma_link) {
3280179337Syongari		if (ifma->ifma_addr->sa_family != AF_LINK)
3281179337Syongari			continue;
3282179337Syongari		crc = ether_crc32_be(LLADDR((struct sockaddr_dl *)
3283179337Syongari		    ifma->ifma_addr), ETHER_ADDR_LEN);
3284179337Syongari
3285179337Syongari		/* Just want the 6 least significant bits. */
3286179337Syongari		crc &= 0x3f;
3287179337Syongari
3288179337Syongari		/* Set the corresponding bit in the hash table. */
3289179337Syongari		mchash[crc >> 5] |= 1 << (crc & 0x1f);
3290179337Syongari	}
3291195049Srwatson	if_maddr_runlock(ifp);
3292179337Syongari
3293179337Syongari	CSR_WRITE_4(sc, JME_MAR0, mchash[0]);
3294179337Syongari	CSR_WRITE_4(sc, JME_MAR1, mchash[1]);
3295179337Syongari	CSR_WRITE_4(sc, JME_RXMAC, rxcfg);
3296179337Syongari}
3297179337Syongari
3298185597Syongaristatic void
3299185597Syongarijme_stats_clear(struct jme_softc *sc)
3300185597Syongari{
3301185597Syongari
3302185597Syongari	JME_LOCK_ASSERT(sc);
3303185597Syongari
3304185597Syongari	if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
3305185597Syongari		return;
3306185597Syongari
3307185597Syongari	/* Disable and clear counters. */
3308185597Syongari	CSR_WRITE_4(sc, JME_STATCSR, 0xFFFFFFFF);
3309185597Syongari	/* Activate hw counters. */
3310185597Syongari	CSR_WRITE_4(sc, JME_STATCSR, 0);
3311185597Syongari	CSR_READ_4(sc, JME_STATCSR);
3312185597Syongari	bzero(&sc->jme_stats, sizeof(struct jme_hw_stats));
3313185597Syongari}
3314185597Syongari
3315185597Syongaristatic void
3316185597Syongarijme_stats_save(struct jme_softc *sc)
3317185597Syongari{
3318185597Syongari
3319185597Syongari	JME_LOCK_ASSERT(sc);
3320185597Syongari
3321185597Syongari	if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
3322185597Syongari		return;
3323185597Syongari	/* Save current counters. */
3324185597Syongari	bcopy(&sc->jme_stats, &sc->jme_ostats, sizeof(struct jme_hw_stats));
3325185597Syongari	/* Disable and clear counters. */
3326185597Syongari	CSR_WRITE_4(sc, JME_STATCSR, 0xFFFFFFFF);
3327185597Syongari}
3328185597Syongari
3329185597Syongaristatic void
3330185597Syongarijme_stats_update(struct jme_softc *sc)
3331185597Syongari{
3332185597Syongari	struct jme_hw_stats *stat, *ostat;
3333185597Syongari	uint32_t reg;
3334185597Syongari
3335185597Syongari	JME_LOCK_ASSERT(sc);
3336185597Syongari
3337185597Syongari	if ((sc->jme_flags & JME_FLAG_HWMIB) == 0)
3338185597Syongari		return;
3339185597Syongari	stat = &sc->jme_stats;
3340185597Syongari	ostat = &sc->jme_ostats;
3341185597Syongari	stat->tx_good_frames = CSR_READ_4(sc, JME_STAT_TXGOOD);
3342185597Syongari	stat->rx_good_frames = CSR_READ_4(sc, JME_STAT_RXGOOD);
3343185597Syongari	reg = CSR_READ_4(sc, JME_STAT_CRCMII);
3344185597Syongari	stat->rx_crc_errs = (reg & STAT_RX_CRC_ERR_MASK) >>
3345185597Syongari	    STAT_RX_CRC_ERR_SHIFT;
3346185597Syongari	stat->rx_mii_errs = (reg & STAT_RX_MII_ERR_MASK) >>
3347185597Syongari	    STAT_RX_MII_ERR_SHIFT;
3348185597Syongari	reg = CSR_READ_4(sc, JME_STAT_RXERR);
3349185597Syongari	stat->rx_fifo_oflows = (reg & STAT_RXERR_OFLOW_MASK) >>
3350185597Syongari	    STAT_RXERR_OFLOW_SHIFT;
3351185597Syongari	stat->rx_desc_empty = (reg & STAT_RXERR_MPTY_MASK) >>
3352185597Syongari	    STAT_RXERR_MPTY_SHIFT;
3353185597Syongari	reg = CSR_READ_4(sc, JME_STAT_FAIL);
3354185597Syongari	stat->rx_bad_frames = (reg & STAT_FAIL_RX_MASK) >> STAT_FAIL_RX_SHIFT;
3355185597Syongari	stat->tx_bad_frames = (reg & STAT_FAIL_TX_MASK) >> STAT_FAIL_TX_SHIFT;
3356185597Syongari
3357185597Syongari	/* Account for previous counters. */
3358185597Syongari	stat->rx_good_frames += ostat->rx_good_frames;
3359185597Syongari	stat->rx_crc_errs += ostat->rx_crc_errs;
3360185597Syongari	stat->rx_mii_errs += ostat->rx_mii_errs;
3361185597Syongari	stat->rx_fifo_oflows += ostat->rx_fifo_oflows;
3362185597Syongari	stat->rx_desc_empty += ostat->rx_desc_empty;
3363185597Syongari	stat->rx_bad_frames += ostat->rx_bad_frames;
3364185597Syongari	stat->tx_good_frames += ostat->tx_good_frames;
3365185597Syongari	stat->tx_bad_frames += ostat->tx_bad_frames;
3366185597Syongari}
3367185597Syongari
3368216551Syongaristatic void
3369216551Syongarijme_phy_down(struct jme_softc *sc)
3370216551Syongari{
3371216551Syongari	uint32_t reg;
3372216551Syongari
3373216551Syongari	jme_miibus_writereg(sc->jme_dev, sc->jme_phyaddr, MII_BMCR, BMCR_PDOWN);
3374216551Syongari	if (CHIPMODE_REVFM(sc->jme_chip_rev) >= 5) {
3375216551Syongari		reg = CSR_READ_4(sc, JME_PHYPOWDN);
3376216551Syongari		reg |= 0x0000000F;
3377216551Syongari		CSR_WRITE_4(sc, JME_PHYPOWDN, reg);
3378216551Syongari		reg = pci_read_config(sc->jme_dev, JME_PCI_PE1, 4);
3379216551Syongari		reg &= ~PE1_GIGA_PDOWN_MASK;
3380216551Syongari		reg |= PE1_GIGA_PDOWN_D3;
3381216551Syongari		pci_write_config(sc->jme_dev, JME_PCI_PE1, reg, 4);
3382216551Syongari	}
3383216551Syongari}
3384216551Syongari
3385216551Syongaristatic void
3386216551Syongarijme_phy_up(struct jme_softc *sc)
3387216551Syongari{
3388216551Syongari	uint32_t reg;
3389216551Syongari	uint16_t bmcr;
3390216551Syongari
3391216551Syongari	bmcr = jme_miibus_readreg(sc->jme_dev, sc->jme_phyaddr, MII_BMCR);
3392216551Syongari	bmcr &= ~BMCR_PDOWN;
3393216551Syongari	jme_miibus_writereg(sc->jme_dev, sc->jme_phyaddr, MII_BMCR, bmcr);
3394216551Syongari	if (CHIPMODE_REVFM(sc->jme_chip_rev) >= 5) {
3395216551Syongari		reg = CSR_READ_4(sc, JME_PHYPOWDN);
3396216551Syongari		reg &= ~0x0000000F;
3397216551Syongari		CSR_WRITE_4(sc, JME_PHYPOWDN, reg);
3398216551Syongari		reg = pci_read_config(sc->jme_dev, JME_PCI_PE1, 4);
3399216551Syongari		reg &= ~PE1_GIGA_PDOWN_MASK;
3400216551Syongari		reg |= PE1_GIGA_PDOWN_DIS;
3401216551Syongari		pci_write_config(sc->jme_dev, JME_PCI_PE1, reg, 4);
3402216551Syongari	}
3403216551Syongari}
3404216551Syongari
3405179337Syongaristatic int
3406179337Syongarisysctl_int_range(SYSCTL_HANDLER_ARGS, int low, int high)
3407179337Syongari{
3408179337Syongari	int error, value;
3409179337Syongari
3410179337Syongari	if (arg1 == NULL)
3411179337Syongari		return (EINVAL);
3412179337Syongari	value = *(int *)arg1;
3413179337Syongari	error = sysctl_handle_int(oidp, &value, 0, req);
3414179337Syongari	if (error || req->newptr == NULL)
3415179337Syongari		return (error);
3416179337Syongari	if (value < low || value > high)
3417179337Syongari		return (EINVAL);
3418179337Syongari        *(int *)arg1 = value;
3419179337Syongari
3420179337Syongari        return (0);
3421179337Syongari}
3422179337Syongari
3423179337Syongaristatic int
3424179337Syongarisysctl_hw_jme_tx_coal_to(SYSCTL_HANDLER_ARGS)
3425179337Syongari{
3426179337Syongari	return (sysctl_int_range(oidp, arg1, arg2, req,
3427179337Syongari	    PCCTX_COAL_TO_MIN, PCCTX_COAL_TO_MAX));
3428179337Syongari}
3429179337Syongari
3430179337Syongaristatic int
3431179337Syongarisysctl_hw_jme_tx_coal_pkt(SYSCTL_HANDLER_ARGS)
3432179337Syongari{
3433179337Syongari	return (sysctl_int_range(oidp, arg1, arg2, req,
3434179337Syongari	    PCCTX_COAL_PKT_MIN, PCCTX_COAL_PKT_MAX));
3435179337Syongari}
3436179337Syongari
3437179337Syongaristatic int
3438179337Syongarisysctl_hw_jme_rx_coal_to(SYSCTL_HANDLER_ARGS)
3439179337Syongari{
3440179337Syongari	return (sysctl_int_range(oidp, arg1, arg2, req,
3441179337Syongari	    PCCRX_COAL_TO_MIN, PCCRX_COAL_TO_MAX));
3442179337Syongari}
3443179337Syongari
3444179337Syongaristatic int
3445179337Syongarisysctl_hw_jme_rx_coal_pkt(SYSCTL_HANDLER_ARGS)
3446179337Syongari{
3447179337Syongari	return (sysctl_int_range(oidp, arg1, arg2, req,
3448179337Syongari	    PCCRX_COAL_PKT_MIN, PCCRX_COAL_PKT_MAX));
3449179337Syongari}
3450179337Syongari
3451179337Syongaristatic int
3452179337Syongarisysctl_hw_jme_proc_limit(SYSCTL_HANDLER_ARGS)
3453179337Syongari{
3454179337Syongari	return (sysctl_int_range(oidp, arg1, arg2, req,
3455179337Syongari	    JME_PROC_MIN, JME_PROC_MAX));
3456179337Syongari}
3457