if_ti.c revision 284724
1139825Simp/*-
245386Swpaul * Copyright (c) 1997, 1998, 1999
345386Swpaul *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved.
445386Swpaul *
545386Swpaul * Redistribution and use in source and binary forms, with or without
645386Swpaul * modification, are permitted provided that the following conditions
745386Swpaul * are met:
845386Swpaul * 1. Redistributions of source code must retain the above copyright
945386Swpaul *    notice, this list of conditions and the following disclaimer.
1045386Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1145386Swpaul *    notice, this list of conditions and the following disclaimer in the
1245386Swpaul *    documentation and/or other materials provided with the distribution.
1345386Swpaul * 3. All advertising materials mentioning features or use of this software
1445386Swpaul *    must display the following acknowledgement:
1545386Swpaul *	This product includes software developed by Bill Paul.
1645386Swpaul * 4. Neither the name of the author nor the names of any co-contributors
1745386Swpaul *    may be used to endorse or promote products derived from this software
1845386Swpaul *    without specific prior written permission.
1945386Swpaul *
2045386Swpaul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2145386Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2245386Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2345386Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
2445386Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2545386Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2645386Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2745386Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2845386Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2945386Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
3045386Swpaul * THE POSSIBILITY OF SUCH DAMAGE.
3145386Swpaul */
3245386Swpaul
3345386Swpaul/*
3445386Swpaul * Alteon Networks Tigon PCI gigabit ethernet driver for FreeBSD.
3545386Swpaul * Manuals, sample driver and firmware source kits are available
3645386Swpaul * from http://www.alteon.com/support/openkits.
37131652Sbms *
3845386Swpaul * Written by Bill Paul <wpaul@ctr.columbia.edu>
3945386Swpaul * Electrical Engineering Department
4045386Swpaul * Columbia University, New York City
4145386Swpaul */
4245386Swpaul
4345386Swpaul/*
4445386Swpaul * The Alteon Networks Tigon chip contains an embedded R4000 CPU,
4545386Swpaul * gigabit MAC, dual DMA channels and a PCI interface unit. NICs
4645386Swpaul * using the Tigon may have anywhere from 512K to 2MB of SRAM. The
4745386Swpaul * Tigon supports hardware IP, TCP and UCP checksumming, multicast
4845386Swpaul * filtering and jumbo (9014 byte) frames. The hardware is largely
4945386Swpaul * controlled by firmware, which must be loaded into the NIC during
5045386Swpaul * initialization.
5145386Swpaul *
5245386Swpaul * The Tigon 2 contains 2 R4000 CPUs and requires a newer firmware
5345386Swpaul * revision, which supports new features such as extended commands,
5445386Swpaul * extended jumbo receive ring desciptors and a mini receive ring.
5545386Swpaul *
5645386Swpaul * Alteon Networks is to be commended for releasing such a vast amount
5745386Swpaul * of development material for the Tigon NIC without requiring an NDA
5845386Swpaul * (although they really should have done it a long time ago). With
5945386Swpaul * any luck, the other vendors will finally wise up and follow Alteon's
6045386Swpaul * stellar example.
6145386Swpaul *
6245386Swpaul * The firmware for the Tigon 1 and 2 NICs is compiled directly into
6345386Swpaul * this driver by #including it as a C header file. This bloats the
6445386Swpaul * driver somewhat, but it's the easiest method considering that the
6545386Swpaul * driver code and firmware code need to be kept in sync. The source
6645386Swpaul * for the firmware is not provided with the FreeBSD distribution since
6745386Swpaul * compiling it requires a GNU toolchain targeted for mips-sgi-irix5.3.
6845386Swpaul *
6945386Swpaul * The following people deserve special thanks:
7045386Swpaul * - Terry Murphy of 3Com, for providing a 3c985 Tigon 1 board
7145386Swpaul *   for testing
7245386Swpaul * - Raymond Lee of Netgear, for providing a pair of Netgear
7345386Swpaul *   GA620 Tigon 2 boards for testing
7445386Swpaul * - Ulf Zimmermann, for bringing the GA260 to my attention and
7545386Swpaul *   convincing me to write this driver.
7645386Swpaul * - Andrew Gallatin for providing FreeBSD/Alpha support.
7745386Swpaul */
7845386Swpaul
79113038Sobrien#include <sys/cdefs.h>
80113038Sobrien__FBSDID("$FreeBSD: head/sys/dev/ti/if_ti.c 284724 2015-06-23 06:59:46Z dim $");
81113038Sobrien
8298849Sken#include "opt_ti.h"
8398849Sken
8445386Swpaul#include <sys/param.h>
8545386Swpaul#include <sys/systm.h>
8645386Swpaul#include <sys/sockio.h>
8745386Swpaul#include <sys/mbuf.h>
8845386Swpaul#include <sys/malloc.h>
8945386Swpaul#include <sys/kernel.h>
90129878Sphk#include <sys/module.h>
9145386Swpaul#include <sys/socket.h>
9245386Swpaul#include <sys/queue.h>
9398849Sken#include <sys/conf.h>
94153770Syongari#include <sys/sf_buf.h>
9545386Swpaul
9645386Swpaul#include <net/if.h>
97257176Sglebius#include <net/if_var.h>
9845386Swpaul#include <net/if_arp.h>
9945386Swpaul#include <net/ethernet.h>
10045386Swpaul#include <net/if_dl.h>
10145386Swpaul#include <net/if_media.h>
10283115Sbrooks#include <net/if_types.h>
10383115Sbrooks#include <net/if_vlan_var.h>
10445386Swpaul
10545386Swpaul#include <net/bpf.h>
10645386Swpaul
10745386Swpaul#include <netinet/in_systm.h>
10845386Swpaul#include <netinet/in.h>
10945386Swpaul#include <netinet/ip.h>
11045386Swpaul
11145386Swpaul#include <machine/bus.h>
11249011Swpaul#include <machine/resource.h>
11349011Swpaul#include <sys/bus.h>
11449011Swpaul#include <sys/rman.h>
11545386Swpaul
116227347Syongari#ifdef TI_SF_BUF_JUMBO
117153770Syongari#include <vm/vm.h>
11898849Sken#include <vm/vm_page.h>
119153770Syongari#endif
12098849Sken
121119288Simp#include <dev/pci/pcireg.h>
122119288Simp#include <dev/pci/pcivar.h>
12345386Swpaul
12498849Sken#include <sys/tiio.h>
125153280Sscottl#include <dev/ti/if_tireg.h>
126153280Sscottl#include <dev/ti/ti_fw.h>
127153280Sscottl#include <dev/ti/ti_fw2.h>
12845386Swpaul
129227509Syongari#include <sys/sysctl.h>
130227509Syongari
131242425Syongari#define TI_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP)
13298849Sken/*
13398849Sken * We can only turn on header splitting if we're using extended receive
13498849Sken * BDs.
13598849Sken */
136227347Syongari#if defined(TI_JUMBO_HDRSPLIT) && !defined(TI_SF_BUF_JUMBO)
137227347Syongari#error "options TI_JUMBO_HDRSPLIT requires TI_SF_BUF_JUMBO"
138227347Syongari#endif /* TI_JUMBO_HDRSPLIT && !TI_SF_BUF_JUMBO */
13945386Swpaul
14098849Skentypedef enum {
14198849Sken	TI_SWAP_HTON,
14298849Sken	TI_SWAP_NTOH
14398849Sken} ti_swap_type;
14498849Sken
14545386Swpaul/*
14645386Swpaul * Various supported device vendors/types and their names.
14745386Swpaul */
14845386Swpaul
149242625Sdimstatic const struct ti_type ti_devs[] = {
15045386Swpaul	{ ALT_VENDORID,	ALT_DEVICEID_ACENIC,
15163702Swpaul		"Alteon AceNIC 1000baseSX Gigabit Ethernet" },
15263699Swpaul	{ ALT_VENDORID,	ALT_DEVICEID_ACENIC_COPPER,
15363702Swpaul		"Alteon AceNIC 1000baseT Gigabit Ethernet" },
15445386Swpaul	{ TC_VENDORID,	TC_DEVICEID_3C985,
15545386Swpaul		"3Com 3c985-SX Gigabit Ethernet" },
15645386Swpaul	{ NG_VENDORID, NG_DEVICEID_GA620,
15764139Swpaul		"Netgear GA620 1000baseSX Gigabit Ethernet" },
15864139Swpaul	{ NG_VENDORID, NG_DEVICEID_GA620T,
15964139Swpaul		"Netgear GA620 1000baseT Gigabit Ethernet" },
16045386Swpaul	{ SGI_VENDORID, SGI_DEVICEID_TIGON,
16145386Swpaul		"Silicon Graphics Gigabit Ethernet" },
16256206Swpaul	{ DEC_VENDORID, DEC_DEVICEID_FARALLON_PN9000SX,
16356206Swpaul		"Farallon PN9000SX Gigabit Ethernet" },
16445386Swpaul	{ 0, 0, NULL }
16545386Swpaul};
16645386Swpaul
16798849Sken
16898849Skenstatic	d_open_t	ti_open;
16998849Skenstatic	d_close_t	ti_close;
17098849Skenstatic	d_ioctl_t	ti_ioctl2;
17198849Sken
17298849Skenstatic struct cdevsw ti_cdevsw = {
173126080Sphk	.d_version =	D_VERSION,
174153281Sscottl	.d_flags =	0,
175111815Sphk	.d_open =	ti_open,
176111815Sphk	.d_close =	ti_close,
177111815Sphk	.d_ioctl =	ti_ioctl2,
178111815Sphk	.d_name =	"ti",
17998849Sken};
18098849Sken
181142407Simpstatic int ti_probe(device_t);
182142407Simpstatic int ti_attach(device_t);
183142407Simpstatic int ti_detach(device_t);
184142407Simpstatic void ti_txeof(struct ti_softc *);
185142407Simpstatic void ti_rxeof(struct ti_softc *);
18645386Swpaul
187153982Syongaristatic int ti_encap(struct ti_softc *, struct mbuf **);
18845386Swpaul
189142407Simpstatic void ti_intr(void *);
190142407Simpstatic void ti_start(struct ifnet *);
191153770Syongaristatic void ti_start_locked(struct ifnet *);
192142407Simpstatic int ti_ioctl(struct ifnet *, u_long, caddr_t);
193272169Sglebiusstatic uint64_t ti_get_counter(struct ifnet *, ift_counter);
194142407Simpstatic void ti_init(void *);
195153770Syongaristatic void ti_init_locked(void *);
196142407Simpstatic void ti_init2(struct ti_softc *);
197142407Simpstatic void ti_stop(struct ti_softc *);
198199559Sjhbstatic void ti_watchdog(void *);
199173839Syongaristatic int ti_shutdown(device_t);
200142407Simpstatic int ti_ifmedia_upd(struct ifnet *);
201227093Syongaristatic int ti_ifmedia_upd_locked(struct ti_softc *);
202142407Simpstatic void ti_ifmedia_sts(struct ifnet *, struct ifmediareq *);
20345386Swpaul
204227089Syongaristatic uint32_t ti_eeprom_putbyte(struct ti_softc *, int);
205227089Syongaristatic uint8_t	ti_eeprom_getbyte(struct ti_softc *, int, uint8_t *);
206142407Simpstatic int ti_read_eeprom(struct ti_softc *, caddr_t, int, int);
20745386Swpaul
208142407Simpstatic void ti_add_mcast(struct ti_softc *, struct ether_addr *);
209142407Simpstatic void ti_del_mcast(struct ti_softc *, struct ether_addr *);
210142407Simpstatic void ti_setmulti(struct ti_softc *);
21145386Swpaul
212227089Syongaristatic void ti_mem_read(struct ti_softc *, uint32_t, uint32_t, void *);
213227089Syongaristatic void ti_mem_write(struct ti_softc *, uint32_t, uint32_t, void *);
214227089Syongaristatic void ti_mem_zero(struct ti_softc *, uint32_t, uint32_t);
215227089Syongaristatic int ti_copy_mem(struct ti_softc *, uint32_t, uint32_t, caddr_t, int,
216227087Syongari    int);
217227089Syongaristatic int ti_copy_scratch(struct ti_softc *, uint32_t, uint32_t, caddr_t,
218227087Syongari    int, int, int);
219142407Simpstatic int ti_bcopy_swap(const void *, void *, size_t, ti_swap_type);
220142407Simpstatic void ti_loadfw(struct ti_softc *);
221142407Simpstatic void ti_cmd(struct ti_softc *, struct ti_cmd_desc *);
222142407Simpstatic void ti_cmd_ext(struct ti_softc *, struct ti_cmd_desc *, caddr_t, int);
223142407Simpstatic void ti_handle_events(struct ti_softc *);
224227512Syongaristatic void ti_dma_map_addr(void *, bus_dma_segment_t *, int, int);
225227512Syongaristatic int ti_dma_alloc(struct ti_softc *);
226227512Syongaristatic void ti_dma_free(struct ti_softc *);
227227512Syongaristatic int ti_dma_ring_alloc(struct ti_softc *, bus_size_t, bus_size_t,
228227512Syongari    bus_dma_tag_t *, uint8_t **, bus_dmamap_t *, bus_addr_t *, const char *);
229227512Syongaristatic void ti_dma_ring_free(struct ti_softc *, bus_dma_tag_t *, uint8_t **,
230267580Sjhb    bus_dmamap_t, bus_addr_t *);
231227347Syongaristatic int ti_newbuf_std(struct ti_softc *, int);
232227347Syongaristatic int ti_newbuf_mini(struct ti_softc *, int);
233142407Simpstatic int ti_newbuf_jumbo(struct ti_softc *, int, struct mbuf *);
234142407Simpstatic int ti_init_rx_ring_std(struct ti_softc *);
235142407Simpstatic void ti_free_rx_ring_std(struct ti_softc *);
236142407Simpstatic int ti_init_rx_ring_jumbo(struct ti_softc *);
237142407Simpstatic void ti_free_rx_ring_jumbo(struct ti_softc *);
238142407Simpstatic int ti_init_rx_ring_mini(struct ti_softc *);
239142407Simpstatic void ti_free_rx_ring_mini(struct ti_softc *);
240142407Simpstatic void ti_free_tx_ring(struct ti_softc *);
241142407Simpstatic int ti_init_tx_ring(struct ti_softc *);
242227347Syongaristatic void ti_discard_std(struct ti_softc *, int);
243227347Syongari#ifndef TI_SF_BUF_JUMBO
244227347Syongaristatic void ti_discard_jumbo(struct ti_softc *, int);
245227347Syongari#endif
246227347Syongaristatic void ti_discard_mini(struct ti_softc *, int);
24745386Swpaul
248142407Simpstatic int ti_64bitslot_war(struct ti_softc *);
249142407Simpstatic int ti_chipinit(struct ti_softc *);
250142407Simpstatic int ti_gibinit(struct ti_softc *);
25145386Swpaul
25298849Sken#ifdef TI_JUMBO_HDRSPLIT
253227087Syongaristatic __inline void ti_hdr_split(struct mbuf *top, int hdr_len, int pkt_len,
254227087Syongari    int idx);
25598849Sken#endif /* TI_JUMBO_HDRSPLIT */
25698849Sken
257227509Syongaristatic void ti_sysctl_node(struct ti_softc *);
258227509Syongari
25949011Swpaulstatic device_method_t ti_methods[] = {
26049011Swpaul	/* Device interface */
26149011Swpaul	DEVMETHOD(device_probe,		ti_probe),
26249011Swpaul	DEVMETHOD(device_attach,	ti_attach),
26349011Swpaul	DEVMETHOD(device_detach,	ti_detach),
26449011Swpaul	DEVMETHOD(device_shutdown,	ti_shutdown),
26549011Swpaul	{ 0, 0 }
26649011Swpaul};
26749011Swpaul
26849011Swpaulstatic driver_t ti_driver = {
26951455Swpaul	"ti",
27049011Swpaul	ti_methods,
27149011Swpaul	sizeof(struct ti_softc)
27249011Swpaul};
27349011Swpaul
27449011Swpaulstatic devclass_t ti_devclass;
27549011Swpaul
276113506SmdoddDRIVER_MODULE(ti, pci, ti_driver, ti_devclass, 0, 0);
277113506SmdoddMODULE_DEPEND(ti, pci, 1, 1, 1);
278113506SmdoddMODULE_DEPEND(ti, ether, 1, 1, 1);
27949011Swpaul
28045386Swpaul/*
28145386Swpaul * Send an instruction or address to the EEPROM, check for ACK.
28245386Swpaul */
283227089Syongaristatic uint32_t
284227087Syongariti_eeprom_putbyte(struct ti_softc *sc, int byte)
28545386Swpaul{
286227087Syongari	int i, ack = 0;
28745386Swpaul
28845386Swpaul	/*
28945386Swpaul	 * Make sure we're in TX mode.
29045386Swpaul	 */
29145386Swpaul	TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN);
29245386Swpaul
29345386Swpaul	/*
29445386Swpaul	 * Feed in each bit and stobe the clock.
29545386Swpaul	 */
29645386Swpaul	for (i = 0x80; i; i >>= 1) {
29745386Swpaul		if (byte & i) {
29845386Swpaul			TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT);
29945386Swpaul		} else {
30045386Swpaul			TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT);
30145386Swpaul		}
30245386Swpaul		DELAY(1);
30345386Swpaul		TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
30445386Swpaul		DELAY(1);
30545386Swpaul		TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
30645386Swpaul	}
30745386Swpaul
30845386Swpaul	/*
30945386Swpaul	 * Turn off TX mode.
31045386Swpaul	 */
31145386Swpaul	TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN);
31245386Swpaul
31345386Swpaul	/*
31445386Swpaul	 * Check for ack.
31545386Swpaul	 */
31645386Swpaul	TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
31745386Swpaul	ack = CSR_READ_4(sc, TI_MISC_LOCAL_CTL) & TI_MLC_EE_DIN;
31845386Swpaul	TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
31945386Swpaul
320131654Sbms	return (ack);
32145386Swpaul}
32245386Swpaul
32345386Swpaul/*
32445386Swpaul * Read a byte of data stored in the EEPROM at address 'addr.'
32545386Swpaul * We have to send two address bytes since the EEPROM can hold
32645386Swpaul * more than 256 bytes of data.
32745386Swpaul */
328227089Syongaristatic uint8_t
329227089Syongariti_eeprom_getbyte(struct ti_softc *sc, int addr, uint8_t *dest)
33045386Swpaul{
331227087Syongari	int i;
332227089Syongari	uint8_t byte = 0;
33345386Swpaul
33445386Swpaul	EEPROM_START;
33545386Swpaul
33645386Swpaul	/*
33745386Swpaul	 * Send write control code to EEPROM.
33845386Swpaul	 */
33945386Swpaul	if (ti_eeprom_putbyte(sc, EEPROM_CTL_WRITE)) {
340162321Sglebius		device_printf(sc->ti_dev,
341150719Sjhb		    "failed to send write command, status: %x\n",
342150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
343131654Sbms		return (1);
34445386Swpaul	}
34545386Swpaul
34645386Swpaul	/*
34745386Swpaul	 * Send first byte of address of byte we want to read.
34845386Swpaul	 */
34945386Swpaul	if (ti_eeprom_putbyte(sc, (addr >> 8) & 0xFF)) {
350162321Sglebius		device_printf(sc->ti_dev, "failed to send address, status: %x\n",
351150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
352131654Sbms		return (1);
35345386Swpaul	}
35445386Swpaul	/*
35545386Swpaul	 * Send second byte address of byte we want to read.
35645386Swpaul	 */
35745386Swpaul	if (ti_eeprom_putbyte(sc, addr & 0xFF)) {
358162321Sglebius		device_printf(sc->ti_dev, "failed to send address, status: %x\n",
359150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
360131654Sbms		return (1);
36145386Swpaul	}
36245386Swpaul
36345386Swpaul	EEPROM_STOP;
36445386Swpaul	EEPROM_START;
36545386Swpaul	/*
36645386Swpaul	 * Send read control code to EEPROM.
36745386Swpaul	 */
36845386Swpaul	if (ti_eeprom_putbyte(sc, EEPROM_CTL_READ)) {
369162321Sglebius		device_printf(sc->ti_dev,
370150719Sjhb		    "failed to send read command, status: %x\n",
371150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
372131654Sbms		return (1);
37345386Swpaul	}
37445386Swpaul
37545386Swpaul	/*
37645386Swpaul	 * Start reading bits from EEPROM.
37745386Swpaul	 */
37845386Swpaul	TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN);
37945386Swpaul	for (i = 0x80; i; i >>= 1) {
38045386Swpaul		TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
38145386Swpaul		DELAY(1);
38245386Swpaul		if (CSR_READ_4(sc, TI_MISC_LOCAL_CTL) & TI_MLC_EE_DIN)
38345386Swpaul			byte |= i;
38445386Swpaul		TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
38545386Swpaul		DELAY(1);
38645386Swpaul	}
38745386Swpaul
38845386Swpaul	EEPROM_STOP;
38945386Swpaul
39045386Swpaul	/*
39145386Swpaul	 * No ACK generated for read, so just return byte.
39245386Swpaul	 */
39345386Swpaul
39445386Swpaul	*dest = byte;
39545386Swpaul
396131654Sbms	return (0);
39745386Swpaul}
39845386Swpaul
39945386Swpaul/*
40045386Swpaul * Read a sequence of bytes from the EEPROM.
40145386Swpaul */
402102336Salfredstatic int
403227086Syongariti_read_eeprom(struct ti_softc *sc, caddr_t dest, int off, int cnt)
40445386Swpaul{
405227087Syongari	int err = 0, i;
406227089Syongari	uint8_t byte = 0;
40745386Swpaul
40845386Swpaul	for (i = 0; i < cnt; i++) {
40945386Swpaul		err = ti_eeprom_getbyte(sc, off + i, &byte);
41045386Swpaul		if (err)
41145386Swpaul			break;
41245386Swpaul		*(dest + i) = byte;
41345386Swpaul	}
41445386Swpaul
415131654Sbms	return (err ? 1 : 0);
41645386Swpaul}
41745386Swpaul
41845386Swpaul/*
419153770Syongari * NIC memory read function.
420153770Syongari * Can be used to copy data from NIC local memory.
42145386Swpaul */
422102336Salfredstatic void
423227089Syongariti_mem_read(struct ti_softc *sc, uint32_t addr, uint32_t len, void *buf)
42445386Swpaul{
425227087Syongari	int segptr, segsize, cnt;
426227087Syongari	char *ptr;
42745386Swpaul
42845386Swpaul	segptr = addr;
42945386Swpaul	cnt = len;
43045386Swpaul	ptr = buf;
43145386Swpaul
432131654Sbms	while (cnt) {
43345386Swpaul		if (cnt < TI_WINLEN)
43445386Swpaul			segsize = cnt;
43545386Swpaul		else
43645386Swpaul			segsize = TI_WINLEN - (segptr % TI_WINLEN);
43745386Swpaul		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
438153770Syongari		bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
439227089Syongari		    TI_WINDOW + (segptr & (TI_WINLEN - 1)), (uint32_t *)ptr,
440153770Syongari		    segsize / 4);
441153770Syongari		ptr += segsize;
44245386Swpaul		segptr += segsize;
44345386Swpaul		cnt -= segsize;
44445386Swpaul	}
44545386Swpaul}
44645386Swpaul
447153770Syongari
448153770Syongari/*
449153770Syongari * NIC memory write function.
450153770Syongari * Can be used to copy data into NIC local memory.
451153770Syongari */
452153770Syongaristatic void
453227089Syongariti_mem_write(struct ti_softc *sc, uint32_t addr, uint32_t len, void *buf)
454153770Syongari{
455227087Syongari	int segptr, segsize, cnt;
456227087Syongari	char *ptr;
457153770Syongari
458153770Syongari	segptr = addr;
459153770Syongari	cnt = len;
460153770Syongari	ptr = buf;
461153770Syongari
462153770Syongari	while (cnt) {
463153770Syongari		if (cnt < TI_WINLEN)
464153770Syongari			segsize = cnt;
465153770Syongari		else
466153770Syongari			segsize = TI_WINLEN - (segptr % TI_WINLEN);
467153770Syongari		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
468153770Syongari		bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
469227089Syongari		    TI_WINDOW + (segptr & (TI_WINLEN - 1)), (uint32_t *)ptr,
470153770Syongari		    segsize / 4);
471153770Syongari		ptr += segsize;
472153770Syongari		segptr += segsize;
473153770Syongari		cnt -= segsize;
474153770Syongari	}
475153770Syongari}
476153770Syongari
477153770Syongari/*
478153770Syongari * NIC memory read function.
479153770Syongari * Can be used to clear a section of NIC local memory.
480153770Syongari */
481153770Syongaristatic void
482227089Syongariti_mem_zero(struct ti_softc *sc, uint32_t addr, uint32_t len)
483153770Syongari{
484227087Syongari	int segptr, segsize, cnt;
485153770Syongari
486153770Syongari	segptr = addr;
487153770Syongari	cnt = len;
488153770Syongari
489153770Syongari	while (cnt) {
490153770Syongari		if (cnt < TI_WINLEN)
491153770Syongari			segsize = cnt;
492153770Syongari		else
493153770Syongari			segsize = TI_WINLEN - (segptr % TI_WINLEN);
494153770Syongari		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
495153770Syongari		bus_space_set_region_4(sc->ti_btag, sc->ti_bhandle,
496153770Syongari		    TI_WINDOW + (segptr & (TI_WINLEN - 1)), 0, segsize / 4);
497153770Syongari		segptr += segsize;
498153770Syongari		cnt -= segsize;
499153770Syongari	}
500153770Syongari}
501153770Syongari
50298849Skenstatic int
503227089Syongariti_copy_mem(struct ti_softc *sc, uint32_t tigon_addr, uint32_t len,
504227086Syongari    caddr_t buf, int useraddr, int readdata)
50598849Sken{
506227087Syongari	int segptr, segsize, cnt;
507227087Syongari	caddr_t ptr;
508227089Syongari	uint32_t origwin;
509227087Syongari	int resid, segresid;
510227087Syongari	int first_pass;
51198849Sken
512153770Syongari	TI_LOCK_ASSERT(sc);
513153770Syongari
51498849Sken	/*
51598849Sken	 * At the moment, we don't handle non-aligned cases, we just bail.
51698849Sken	 * If this proves to be a problem, it will be fixed.
51798849Sken	 */
518227431Syongari	if (readdata == 0 && (tigon_addr & 0x3) != 0) {
519162321Sglebius		device_printf(sc->ti_dev, "%s: tigon address %#x isn't "
520162321Sglebius		    "word-aligned\n", __func__, tigon_addr);
521162321Sglebius		device_printf(sc->ti_dev, "%s: unaligned writes aren't "
522162321Sglebius		    "yet supported\n", __func__);
523131654Sbms		return (EINVAL);
52498849Sken	}
52598849Sken
52698849Sken	segptr = tigon_addr & ~0x3;
52798849Sken	segresid = tigon_addr - segptr;
52898849Sken
52998849Sken	/*
53098849Sken	 * This is the non-aligned amount left over that we'll need to
53198849Sken	 * copy.
53298849Sken	 */
53398849Sken	resid = len & 0x3;
53498849Sken
53598849Sken	/* Add in the left over amount at the front of the buffer */
53698849Sken	resid += segresid;
53798849Sken
53898849Sken	cnt = len & ~0x3;
53998849Sken	/*
54098849Sken	 * If resid + segresid is >= 4, add multiples of 4 to the count and
54198849Sken	 * decrease the residual by that much.
54298849Sken	 */
54398849Sken	cnt += resid & ~0x3;
54498849Sken	resid -= resid & ~0x3;
54598849Sken
54698849Sken	ptr = buf;
54798849Sken
54898849Sken	first_pass = 1;
54998849Sken
55098849Sken	/*
55198849Sken	 * Save the old window base value.
55298849Sken	 */
55398849Sken	origwin = CSR_READ_4(sc, TI_WINBASE);
55498849Sken
555131654Sbms	while (cnt) {
55698849Sken		bus_size_t ti_offset;
55798849Sken
55898849Sken		if (cnt < TI_WINLEN)
55998849Sken			segsize = cnt;
56098849Sken		else
56198849Sken			segsize = TI_WINLEN - (segptr % TI_WINLEN);
56298849Sken		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
56398849Sken
56498849Sken		ti_offset = TI_WINDOW + (segptr & (TI_WINLEN -1));
56598849Sken
56698849Sken		if (readdata) {
567227431Syongari			bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
568227505Syongari			    ti_offset, (uint32_t *)sc->ti_membuf, segsize >> 2);
56998849Sken			if (useraddr) {
57098849Sken				/*
57198849Sken				 * Yeah, this is a little on the kludgy
57298849Sken				 * side, but at least this code is only
57398849Sken				 * used for debugging.
57498849Sken				 */
575227505Syongari				ti_bcopy_swap(sc->ti_membuf, sc->ti_membuf2,
576227505Syongari				    segsize, TI_SWAP_NTOH);
57798849Sken
578153281Sscottl				TI_UNLOCK(sc);
57998849Sken				if (first_pass) {
580227505Syongari					copyout(&sc->ti_membuf2[segresid], ptr,
581227431Syongari					    segsize - segresid);
58298849Sken					first_pass = 0;
58398849Sken				} else
584227505Syongari					copyout(sc->ti_membuf2, ptr, segsize);
585153281Sscottl				TI_LOCK(sc);
58698849Sken			} else {
58798849Sken				if (first_pass) {
588227505Syongari
589227505Syongari					ti_bcopy_swap(sc->ti_membuf,
590227505Syongari					    sc->ti_membuf2, segsize,
591227505Syongari					    TI_SWAP_NTOH);
592153281Sscottl					TI_UNLOCK(sc);
593227505Syongari					bcopy(&sc->ti_membuf2[segresid], ptr,
594227431Syongari					    segsize - segresid);
595153281Sscottl					TI_LOCK(sc);
59698849Sken					first_pass = 0;
59798849Sken				} else
598227505Syongari					ti_bcopy_swap(sc->ti_membuf, ptr,
599227505Syongari					    segsize, TI_SWAP_NTOH);
60098849Sken			}
60198849Sken
60298849Sken		} else {
60398849Sken			if (useraddr) {
604153281Sscottl				TI_UNLOCK(sc);
605227505Syongari				copyin(ptr, sc->ti_membuf2, segsize);
606153281Sscottl				TI_LOCK(sc);
607227505Syongari				ti_bcopy_swap(sc->ti_membuf2, sc->ti_membuf,
608227505Syongari				    segsize, TI_SWAP_HTON);
60998849Sken			} else
610227505Syongari				ti_bcopy_swap(ptr, sc->ti_membuf, segsize,
611227431Syongari				    TI_SWAP_HTON);
61298849Sken
613227431Syongari			bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
614227505Syongari			    ti_offset, (uint32_t *)sc->ti_membuf, segsize >> 2);
61598849Sken		}
61698849Sken		segptr += segsize;
61798849Sken		ptr += segsize;
61898849Sken		cnt -= segsize;
61998849Sken	}
62098849Sken
62198849Sken	/*
62298849Sken	 * Handle leftover, non-word-aligned bytes.
62398849Sken	 */
62498849Sken	if (resid != 0) {
625227431Syongari		uint32_t tmpval, tmpval2;
626227431Syongari		bus_size_t ti_offset;
62798849Sken
62898849Sken		/*
62998849Sken		 * Set the segment pointer.
63098849Sken		 */
63198849Sken		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
63298849Sken
63398849Sken		ti_offset = TI_WINDOW + (segptr & (TI_WINLEN - 1));
63498849Sken
63598849Sken		/*
63698849Sken		 * First, grab whatever is in our source/destination.
63798849Sken		 * We'll obviously need this for reads, but also for
63898849Sken		 * writes, since we'll be doing read/modify/write.
63998849Sken		 */
64098849Sken		bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
641227431Syongari		    ti_offset, &tmpval, 1);
64298849Sken
64398849Sken		/*
64498849Sken		 * Next, translate this from little-endian to big-endian
64598849Sken		 * (at least on i386 boxes).
64698849Sken		 */
64798849Sken		tmpval2 = ntohl(tmpval);
64898849Sken
64998849Sken		if (readdata) {
65098849Sken			/*
65198849Sken			 * If we're reading, just copy the leftover number
65298849Sken			 * of bytes from the host byte order buffer to
65398849Sken			 * the user's buffer.
65498849Sken			 */
655153281Sscottl			if (useraddr) {
656153281Sscottl				TI_UNLOCK(sc);
65798849Sken				copyout(&tmpval2, ptr, resid);
658153281Sscottl				TI_LOCK(sc);
659153281Sscottl			} else
66098849Sken				bcopy(&tmpval2, ptr, resid);
66198849Sken		} else {
66298849Sken			/*
66398849Sken			 * If we're writing, first copy the bytes to be
66498849Sken			 * written into the network byte order buffer,
66598849Sken			 * leaving the rest of the buffer with whatever was
66698849Sken			 * originally in there.  Then, swap the bytes
66798849Sken			 * around into host order and write them out.
66898849Sken			 *
66998849Sken			 * XXX KDM the read side of this has been verified
67098849Sken			 * to work, but the write side of it has not been
67198849Sken			 * verified.  So user beware.
67298849Sken			 */
673153281Sscottl			if (useraddr) {
674153281Sscottl				TI_UNLOCK(sc);
67598849Sken				copyin(ptr, &tmpval2, resid);
676153281Sscottl				TI_LOCK(sc);
677153281Sscottl			} else
67898849Sken				bcopy(ptr, &tmpval2, resid);
67998849Sken
68098849Sken			tmpval = htonl(tmpval2);
68198849Sken
68298849Sken			bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
683227431Syongari			    ti_offset, &tmpval, 1);
68498849Sken		}
68598849Sken	}
68698849Sken
68798849Sken	CSR_WRITE_4(sc, TI_WINBASE, origwin);
68898849Sken
689131654Sbms	return (0);
69098849Sken}
69198849Sken
69298849Skenstatic int
693227089Syongariti_copy_scratch(struct ti_softc *sc, uint32_t tigon_addr, uint32_t len,
694227086Syongari    caddr_t buf, int useraddr, int readdata, int cpu)
69598849Sken{
696227089Syongari	uint32_t segptr;
697227087Syongari	int cnt;
698227089Syongari	uint32_t tmpval, tmpval2;
699227087Syongari	caddr_t ptr;
70098849Sken
701153770Syongari	TI_LOCK_ASSERT(sc);
702153770Syongari
70398849Sken	/*
70498849Sken	 * At the moment, we don't handle non-aligned cases, we just bail.
70598849Sken	 * If this proves to be a problem, it will be fixed.
70698849Sken	 */
70798849Sken	if (tigon_addr & 0x3) {
708162321Sglebius		device_printf(sc->ti_dev, "%s: tigon address %#x "
709162321Sglebius		    "isn't word-aligned\n", __func__, tigon_addr);
710131654Sbms		return (EINVAL);
71198849Sken	}
71298849Sken
71398849Sken	if (len & 0x3) {
714162321Sglebius		device_printf(sc->ti_dev, "%s: transfer length %d "
715162321Sglebius		    "isn't word-aligned\n", __func__, len);
716131654Sbms		return (EINVAL);
71798849Sken	}
71898849Sken
71998849Sken	segptr = tigon_addr;
72098849Sken	cnt = len;
72198849Sken	ptr = buf;
72298849Sken
72398849Sken	while (cnt) {
72498849Sken		CSR_WRITE_4(sc, CPU_REG(TI_SRAM_ADDR, cpu), segptr);
72598849Sken
72698849Sken		if (readdata) {
72798849Sken			tmpval2 = CSR_READ_4(sc, CPU_REG(TI_SRAM_DATA, cpu));
72898849Sken
72998849Sken			tmpval = ntohl(tmpval2);
73098849Sken
73198849Sken			/*
73298849Sken			 * Note:  I've used this debugging interface
73398849Sken			 * extensively with Alteon's 12.3.15 firmware,
73498849Sken			 * compiled with GCC 2.7.2.1 and binutils 2.9.1.
73598849Sken			 *
73698849Sken			 * When you compile the firmware without
73798849Sken			 * optimization, which is necessary sometimes in
73898849Sken			 * order to properly step through it, you sometimes
739131652Sbms			 * read out a bogus value of 0xc0017c instead of
74098849Sken			 * whatever was supposed to be in that scratchpad
74198849Sken			 * location.  That value is on the stack somewhere,
74298849Sken			 * but I've never been able to figure out what was
74398849Sken			 * causing the problem.
74498849Sken			 *
74598849Sken			 * The address seems to pop up in random places,
74698849Sken			 * often not in the same place on two subsequent
74798849Sken			 * reads.
74898849Sken			 *
74998849Sken			 * In any case, the underlying data doesn't seem
75098849Sken			 * to be affected, just the value read out.
75198849Sken			 *
75298849Sken			 * KDM, 3/7/2000
75398849Sken			 */
75498849Sken
75598849Sken			if (tmpval2 == 0xc0017c)
756162321Sglebius				device_printf(sc->ti_dev, "found 0xc0017c at "
757162321Sglebius				    "%#x (tmpval2)\n", segptr);
75898849Sken
75998849Sken			if (tmpval == 0xc0017c)
760162321Sglebius				device_printf(sc->ti_dev, "found 0xc0017c at "
761162321Sglebius				    "%#x (tmpval)\n", segptr);
76298849Sken
76398849Sken			if (useraddr)
76498849Sken				copyout(&tmpval, ptr, 4);
76598849Sken			else
76698849Sken				bcopy(&tmpval, ptr, 4);
76798849Sken		} else {
76898849Sken			if (useraddr)
76998849Sken				copyin(ptr, &tmpval2, 4);
77098849Sken			else
77198849Sken				bcopy(ptr, &tmpval2, 4);
77298849Sken
77398849Sken			tmpval = htonl(tmpval2);
77498849Sken
77598849Sken			CSR_WRITE_4(sc, CPU_REG(TI_SRAM_DATA, cpu), tmpval);
77698849Sken		}
77798849Sken
77898849Sken		cnt -= 4;
77998849Sken		segptr += 4;
78098849Sken		ptr += 4;
78198849Sken	}
78298849Sken
783131654Sbms	return (0);
78498849Sken}
78598849Sken
78698849Skenstatic int
787227086Syongariti_bcopy_swap(const void *src, void *dst, size_t len, ti_swap_type swap_type)
78898849Sken{
789227089Syongari	const uint8_t *tmpsrc;
790227089Syongari	uint8_t *tmpdst;
79198849Sken	size_t tmplen;
79298849Sken
79398849Sken	if (len & 0x3) {
794227431Syongari		printf("ti_bcopy_swap: length %zd isn't 32-bit aligned\n", len);
795131654Sbms		return (-1);
79698849Sken	}
79798849Sken
79898849Sken	tmpsrc = src;
79998849Sken	tmpdst = dst;
80098849Sken	tmplen = len;
80198849Sken
80298849Sken	while (tmplen) {
80398849Sken		if (swap_type == TI_SWAP_NTOH)
804227431Syongari			*(uint32_t *)tmpdst = ntohl(*(const uint32_t *)tmpsrc);
80598849Sken		else
806227431Syongari			*(uint32_t *)tmpdst = htonl(*(const uint32_t *)tmpsrc);
80798849Sken		tmpsrc += 4;
80898849Sken		tmpdst += 4;
80998849Sken		tmplen -= 4;
81098849Sken	}
81198849Sken
812131654Sbms	return (0);
81398849Sken}
81498849Sken
81545386Swpaul/*
81645386Swpaul * Load firmware image into the NIC. Check that the firmware revision
81745386Swpaul * is acceptable and see if we want the firmware for the Tigon 1 or
81845386Swpaul * Tigon 2.
81945386Swpaul */
820102336Salfredstatic void
821227086Syongariti_loadfw(struct ti_softc *sc)
82245386Swpaul{
823153770Syongari
824153770Syongari	TI_LOCK_ASSERT(sc);
825153770Syongari
826131654Sbms	switch (sc->ti_hwrev) {
82745386Swpaul	case TI_HWREV_TIGON:
82845386Swpaul		if (tigonFwReleaseMajor != TI_FIRMWARE_MAJOR ||
82945386Swpaul		    tigonFwReleaseMinor != TI_FIRMWARE_MINOR ||
83045386Swpaul		    tigonFwReleaseFix != TI_FIRMWARE_FIX) {
831162321Sglebius			device_printf(sc->ti_dev, "firmware revision mismatch; "
832150719Sjhb			    "want %d.%d.%d, got %d.%d.%d\n",
83345386Swpaul			    TI_FIRMWARE_MAJOR, TI_FIRMWARE_MINOR,
83445386Swpaul			    TI_FIRMWARE_FIX, tigonFwReleaseMajor,
83545386Swpaul			    tigonFwReleaseMinor, tigonFwReleaseFix);
83645386Swpaul			return;
83745386Swpaul		}
838153770Syongari		ti_mem_write(sc, tigonFwTextAddr, tigonFwTextLen, tigonFwText);
839153770Syongari		ti_mem_write(sc, tigonFwDataAddr, tigonFwDataLen, tigonFwData);
840153770Syongari		ti_mem_write(sc, tigonFwRodataAddr, tigonFwRodataLen,
841153770Syongari		    tigonFwRodata);
842153770Syongari		ti_mem_zero(sc, tigonFwBssAddr, tigonFwBssLen);
843153770Syongari		ti_mem_zero(sc, tigonFwSbssAddr, tigonFwSbssLen);
84445386Swpaul		CSR_WRITE_4(sc, TI_CPU_PROGRAM_COUNTER, tigonFwStartAddr);
84545386Swpaul		break;
84645386Swpaul	case TI_HWREV_TIGON_II:
84745386Swpaul		if (tigon2FwReleaseMajor != TI_FIRMWARE_MAJOR ||
84845386Swpaul		    tigon2FwReleaseMinor != TI_FIRMWARE_MINOR ||
84945386Swpaul		    tigon2FwReleaseFix != TI_FIRMWARE_FIX) {
850162321Sglebius			device_printf(sc->ti_dev, "firmware revision mismatch; "
851150719Sjhb			    "want %d.%d.%d, got %d.%d.%d\n",
85245386Swpaul			    TI_FIRMWARE_MAJOR, TI_FIRMWARE_MINOR,
85345386Swpaul			    TI_FIRMWARE_FIX, tigon2FwReleaseMajor,
85445386Swpaul			    tigon2FwReleaseMinor, tigon2FwReleaseFix);
85545386Swpaul			return;
85645386Swpaul		}
857153770Syongari		ti_mem_write(sc, tigon2FwTextAddr, tigon2FwTextLen,
858153770Syongari		    tigon2FwText);
859153770Syongari		ti_mem_write(sc, tigon2FwDataAddr, tigon2FwDataLen,
860153770Syongari		    tigon2FwData);
861153770Syongari		ti_mem_write(sc, tigon2FwRodataAddr, tigon2FwRodataLen,
862153770Syongari		    tigon2FwRodata);
863153770Syongari		ti_mem_zero(sc, tigon2FwBssAddr, tigon2FwBssLen);
864153770Syongari		ti_mem_zero(sc, tigon2FwSbssAddr, tigon2FwSbssLen);
86545386Swpaul		CSR_WRITE_4(sc, TI_CPU_PROGRAM_COUNTER, tigon2FwStartAddr);
86645386Swpaul		break;
86745386Swpaul	default:
868162321Sglebius		device_printf(sc->ti_dev,
869150719Sjhb		    "can't load firmware: unknown hardware rev\n");
87045386Swpaul		break;
87145386Swpaul	}
87245386Swpaul}
87345386Swpaul
87445386Swpaul/*
87545386Swpaul * Send the NIC a command via the command ring.
87645386Swpaul */
877102336Salfredstatic void
878227086Syongariti_cmd(struct ti_softc *sc, struct ti_cmd_desc *cmd)
87945386Swpaul{
880227087Syongari	int index;
88145386Swpaul
88245386Swpaul	index = sc->ti_cmd_saved_prodidx;
883227089Syongari	CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4), *(uint32_t *)(cmd));
88445386Swpaul	TI_INC(index, TI_CMD_RING_CNT);
88545386Swpaul	CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, index);
88645386Swpaul	sc->ti_cmd_saved_prodidx = index;
88745386Swpaul}
88845386Swpaul
88945386Swpaul/*
89045386Swpaul * Send the NIC an extended command. The 'len' parameter specifies the
89145386Swpaul * number of command slots to include after the initial command.
89245386Swpaul */
893102336Salfredstatic void
894227086Syongariti_cmd_ext(struct ti_softc *sc, struct ti_cmd_desc *cmd, caddr_t arg, int len)
89545386Swpaul{
896227087Syongari	int index;
897227087Syongari	int i;
89845386Swpaul
89945386Swpaul	index = sc->ti_cmd_saved_prodidx;
900227089Syongari	CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4), *(uint32_t *)(cmd));
90145386Swpaul	TI_INC(index, TI_CMD_RING_CNT);
90245386Swpaul	for (i = 0; i < len; i++) {
90345386Swpaul		CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4),
904227089Syongari		    *(uint32_t *)(&arg[i * 4]));
90545386Swpaul		TI_INC(index, TI_CMD_RING_CNT);
90645386Swpaul	}
90745386Swpaul	CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, index);
90845386Swpaul	sc->ti_cmd_saved_prodidx = index;
90945386Swpaul}
91045386Swpaul
91145386Swpaul/*
91245386Swpaul * Handle events that have triggered interrupts.
91345386Swpaul */
914102336Salfredstatic void
915227086Syongariti_handle_events(struct ti_softc *sc)
91645386Swpaul{
917227087Syongari	struct ti_event_desc *e;
91845386Swpaul
919227512Syongari	if (sc->ti_rdata.ti_event_ring == NULL)
92045386Swpaul		return;
92145386Swpaul
922227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_event_ring_tag,
923227512Syongari	    sc->ti_cdata.ti_event_ring_map, BUS_DMASYNC_POSTREAD);
92445386Swpaul	while (sc->ti_ev_saved_considx != sc->ti_ev_prodidx.ti_idx) {
925227512Syongari		e = &sc->ti_rdata.ti_event_ring[sc->ti_ev_saved_considx];
926153770Syongari		switch (TI_EVENT_EVENT(e)) {
92745386Swpaul		case TI_EV_LINKSTAT_CHANGED:
928153770Syongari			sc->ti_linkstat = TI_EVENT_CODE(e);
929227092Syongari			if (sc->ti_linkstat == TI_EV_CODE_LINK_UP) {
930227092Syongari				if_link_state_change(sc->ti_ifp, LINK_STATE_UP);
931227092Syongari				sc->ti_ifp->if_baudrate = IF_Mbps(100);
932227092Syongari				if (bootverbose)
933227092Syongari					device_printf(sc->ti_dev,
934227092Syongari					    "10/100 link up\n");
935227092Syongari			} else if (sc->ti_linkstat == TI_EV_CODE_GIG_LINK_UP) {
936227092Syongari				if_link_state_change(sc->ti_ifp, LINK_STATE_UP);
937227092Syongari				sc->ti_ifp->if_baudrate = IF_Gbps(1UL);
938227092Syongari				if (bootverbose)
939227092Syongari					device_printf(sc->ti_dev,
940227092Syongari					    "gigabit link up\n");
941227092Syongari			} else if (sc->ti_linkstat == TI_EV_CODE_LINK_DOWN) {
942227092Syongari				if_link_state_change(sc->ti_ifp,
943227092Syongari				    LINK_STATE_DOWN);
944227092Syongari				sc->ti_ifp->if_baudrate = 0;
945227092Syongari				if (bootverbose)
946227092Syongari					device_printf(sc->ti_dev,
947227092Syongari					    "link down\n");
948227092Syongari			}
94945386Swpaul			break;
95045386Swpaul		case TI_EV_ERROR:
951153770Syongari			if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_INVAL_CMD)
952162321Sglebius				device_printf(sc->ti_dev, "invalid command\n");
953153770Syongari			else if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_UNIMP_CMD)
954162321Sglebius				device_printf(sc->ti_dev, "unknown command\n");
955153770Syongari			else if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_BADCFG)
956162321Sglebius				device_printf(sc->ti_dev, "bad config data\n");
95745386Swpaul			break;
95845386Swpaul		case TI_EV_FIRMWARE_UP:
95945386Swpaul			ti_init2(sc);
96045386Swpaul			break;
96145386Swpaul		case TI_EV_STATS_UPDATED:
96245386Swpaul		case TI_EV_RESET_JUMBO_RING:
96345386Swpaul		case TI_EV_MCAST_UPDATED:
96445386Swpaul			/* Who cares. */
96545386Swpaul			break;
96645386Swpaul		default:
967162321Sglebius			device_printf(sc->ti_dev, "unknown event: %d\n",
968153770Syongari			    TI_EVENT_EVENT(e));
96945386Swpaul			break;
97045386Swpaul		}
97145386Swpaul		/* Advance the consumer index. */
97245386Swpaul		TI_INC(sc->ti_ev_saved_considx, TI_EVENT_RING_CNT);
97345386Swpaul		CSR_WRITE_4(sc, TI_GCR_EVENTCONS_IDX, sc->ti_ev_saved_considx);
97445386Swpaul	}
975227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_event_ring_tag,
976227512Syongari	    sc->ti_cdata.ti_event_ring_map, BUS_DMASYNC_PREREAD);
97745386Swpaul}
97845386Swpaul
979227512Syongaristruct ti_dmamap_arg {
980227512Syongari	bus_addr_t	ti_busaddr;
981227512Syongari};
982227512Syongari
983227512Syongaristatic void
984227512Syongariti_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
985227512Syongari{
986227512Syongari	struct ti_dmamap_arg *ctx;
987227512Syongari
988227512Syongari	if (error)
989227512Syongari		return;
990227512Syongari
991227512Syongari	KASSERT(nseg == 1, ("%s: %d segments returned!", __func__, nseg));
992227512Syongari
993227512Syongari	ctx = arg;
994227512Syongari	ctx->ti_busaddr = segs->ds_addr;
995227512Syongari}
996227512Syongari
997153396Sscottlstatic int
998227512Syongariti_dma_ring_alloc(struct ti_softc *sc, bus_size_t alignment, bus_size_t maxsize,
999227512Syongari    bus_dma_tag_t *tag, uint8_t **ring, bus_dmamap_t *map, bus_addr_t *paddr,
1000227512Syongari    const char *msg)
1001153396Sscottl{
1002227512Syongari	struct ti_dmamap_arg ctx;
1003227512Syongari	int error;
1004153396Sscottl
1005227512Syongari	error = bus_dma_tag_create(sc->ti_cdata.ti_parent_tag,
1006227512Syongari	    alignment, 0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL,
1007227512Syongari	    NULL, maxsize, 1, maxsize, 0, NULL, NULL, tag);
1008227512Syongari	if (error != 0) {
1009227512Syongari		device_printf(sc->ti_dev,
1010227512Syongari		    "could not create %s dma tag\n", msg);
1011227512Syongari		return (error);
1012153396Sscottl	}
1013227512Syongari	/* Allocate DMA'able memory for ring. */
1014227512Syongari	error = bus_dmamem_alloc(*tag, (void **)ring,
1015227512Syongari	    BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, map);
1016227512Syongari	if (error != 0) {
1017227512Syongari		device_printf(sc->ti_dev,
1018227512Syongari		    "could not allocate DMA'able memory for %s\n", msg);
1019227512Syongari		return (error);
1020227512Syongari	}
1021227512Syongari	/* Load the address of the ring. */
1022227512Syongari	ctx.ti_busaddr = 0;
1023227512Syongari	error = bus_dmamap_load(*tag, *map, *ring, maxsize, ti_dma_map_addr,
1024227512Syongari	    &ctx, BUS_DMA_NOWAIT);
1025227512Syongari	if (error != 0) {
1026227512Syongari		device_printf(sc->ti_dev,
1027227512Syongari		    "could not load DMA'able memory for %s\n", msg);
1028227512Syongari		return (error);
1029227512Syongari	}
1030227512Syongari	*paddr = ctx.ti_busaddr;
1031227512Syongari	return (0);
1032227512Syongari}
1033227512Syongari
1034227512Syongaristatic void
1035227512Syongariti_dma_ring_free(struct ti_softc *sc, bus_dma_tag_t *tag, uint8_t **ring,
1036267580Sjhb    bus_dmamap_t map, bus_addr_t *paddr)
1037227512Syongari{
1038227512Syongari
1039267580Sjhb	if (*paddr != 0) {
1040267580Sjhb		bus_dmamap_unload(*tag, map);
1041267580Sjhb		*paddr = 0;
1042267580Sjhb	}
1043267580Sjhb	if (*ring != NULL) {
1044267580Sjhb		bus_dmamem_free(*tag, *ring, map);
1045227512Syongari		*ring = NULL;
1046227512Syongari	}
1047227512Syongari	if (*tag) {
1048227512Syongari		bus_dma_tag_destroy(*tag);
1049227512Syongari		*tag = NULL;
1050227512Syongari	}
1051227512Syongari}
1052227512Syongari
1053227512Syongaristatic int
1054227512Syongariti_dma_alloc(struct ti_softc *sc)
1055227512Syongari{
1056227512Syongari	bus_addr_t lowaddr;
1057227512Syongari	int i, error;
1058227512Syongari
1059227512Syongari	lowaddr = BUS_SPACE_MAXADDR;
1060227512Syongari	if (sc->ti_dac == 0)
1061227512Syongari		lowaddr = BUS_SPACE_MAXADDR_32BIT;
1062227512Syongari
1063227512Syongari	error = bus_dma_tag_create(bus_get_dma_tag(sc->ti_dev), 1, 0, lowaddr,
1064227512Syongari	    BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, 0,
1065227512Syongari	    BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL,
1066227512Syongari	    &sc->ti_cdata.ti_parent_tag);
1067227512Syongari	if (error != 0) {
1068227512Syongari		device_printf(sc->ti_dev,
1069227512Syongari		    "could not allocate parent dma tag\n");
1070227512Syongari		return (ENOMEM);
1071227512Syongari	}
1072227512Syongari
1073227512Syongari	error = ti_dma_ring_alloc(sc, TI_RING_ALIGN, sizeof(struct ti_gib),
1074227512Syongari	    &sc->ti_cdata.ti_gib_tag, (uint8_t **)&sc->ti_rdata.ti_info,
1075227512Syongari	    &sc->ti_cdata.ti_gib_map, &sc->ti_rdata.ti_info_paddr, "GIB");
1076227512Syongari	if (error)
1077227512Syongari		return (error);
1078227512Syongari
1079227512Syongari	/* Producer/consumer status */
1080227512Syongari	error = ti_dma_ring_alloc(sc, TI_RING_ALIGN, sizeof(struct ti_status),
1081227512Syongari	    &sc->ti_cdata.ti_status_tag, (uint8_t **)&sc->ti_rdata.ti_status,
1082227512Syongari	    &sc->ti_cdata.ti_status_map, &sc->ti_rdata.ti_status_paddr,
1083227512Syongari	    "event ring");
1084227512Syongari	if (error)
1085227512Syongari		return (error);
1086227512Syongari
1087227512Syongari	/* Event ring */
1088227512Syongari	error = ti_dma_ring_alloc(sc, TI_RING_ALIGN, TI_EVENT_RING_SZ,
1089227512Syongari	    &sc->ti_cdata.ti_event_ring_tag,
1090227512Syongari	    (uint8_t **)&sc->ti_rdata.ti_event_ring,
1091227512Syongari	    &sc->ti_cdata.ti_event_ring_map, &sc->ti_rdata.ti_event_ring_paddr,
1092227512Syongari	    "event ring");
1093227512Syongari	if (error)
1094227512Syongari		return (error);
1095227512Syongari
1096227512Syongari	/* Command ring lives in shared memory so no need to create DMA area. */
1097227512Syongari
1098227512Syongari	/* Standard RX ring */
1099227512Syongari	error = ti_dma_ring_alloc(sc, TI_RING_ALIGN, TI_STD_RX_RING_SZ,
1100227512Syongari	    &sc->ti_cdata.ti_rx_std_ring_tag,
1101227512Syongari	    (uint8_t **)&sc->ti_rdata.ti_rx_std_ring,
1102227512Syongari	    &sc->ti_cdata.ti_rx_std_ring_map,
1103227512Syongari	    &sc->ti_rdata.ti_rx_std_ring_paddr, "RX ring");
1104227512Syongari	if (error)
1105227512Syongari		return (error);
1106227512Syongari
1107227512Syongari	/* Jumbo RX ring */
1108227512Syongari	error = ti_dma_ring_alloc(sc, TI_JUMBO_RING_ALIGN, TI_JUMBO_RX_RING_SZ,
1109227512Syongari	    &sc->ti_cdata.ti_rx_jumbo_ring_tag,
1110227512Syongari	    (uint8_t **)&sc->ti_rdata.ti_rx_jumbo_ring,
1111227512Syongari	    &sc->ti_cdata.ti_rx_jumbo_ring_map,
1112227512Syongari	    &sc->ti_rdata.ti_rx_jumbo_ring_paddr, "jumbo RX ring");
1113227512Syongari	if (error)
1114227512Syongari		return (error);
1115227512Syongari
1116227512Syongari	/* RX return ring */
1117227512Syongari	error = ti_dma_ring_alloc(sc, TI_RING_ALIGN, TI_RX_RETURN_RING_SZ,
1118227512Syongari	    &sc->ti_cdata.ti_rx_return_ring_tag,
1119227512Syongari	    (uint8_t **)&sc->ti_rdata.ti_rx_return_ring,
1120227512Syongari	    &sc->ti_cdata.ti_rx_return_ring_map,
1121227512Syongari	    &sc->ti_rdata.ti_rx_return_ring_paddr, "RX return ring");
1122227512Syongari	if (error)
1123227512Syongari		return (error);
1124227512Syongari
1125227512Syongari	/* Create DMA tag for standard RX mbufs. */
1126227512Syongari	error = bus_dma_tag_create(sc->ti_cdata.ti_parent_tag, 1, 0,
1127227512Syongari	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES, 1,
1128227512Syongari	    MCLBYTES, 0, NULL, NULL, &sc->ti_cdata.ti_rx_std_tag);
1129227512Syongari	if (error) {
1130227512Syongari		device_printf(sc->ti_dev, "could not allocate RX dma tag\n");
1131227512Syongari		return (error);
1132227512Syongari	}
1133227512Syongari
1134227512Syongari	/* Create DMA tag for jumbo RX mbufs. */
1135227512Syongari#ifdef TI_SF_BUF_JUMBO
1136227512Syongari	/*
1137227512Syongari	 * The VM system will take care of providing aligned pages.  Alignment
1138227512Syongari	 * is set to 1 here so that busdma resources won't be wasted.
1139227512Syongari	 */
1140227512Syongari	error = bus_dma_tag_create(sc->ti_cdata.ti_parent_tag, 1, 0,
1141227512Syongari	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, PAGE_SIZE * 4, 4,
1142227512Syongari	    PAGE_SIZE, 0, NULL, NULL, &sc->ti_cdata.ti_rx_jumbo_tag);
1143227512Syongari#else
1144227512Syongari	error = bus_dma_tag_create(sc->ti_cdata.ti_parent_tag, 1, 0,
1145227512Syongari	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MJUM9BYTES, 1,
1146227512Syongari	    MJUM9BYTES, 0, NULL, NULL, &sc->ti_cdata.ti_rx_jumbo_tag);
1147227512Syongari#endif
1148227512Syongari	if (error) {
1149227512Syongari		device_printf(sc->ti_dev,
1150227512Syongari		    "could not allocate jumbo RX dma tag\n");
1151227512Syongari		return (error);
1152227512Syongari	}
1153227512Syongari
1154227512Syongari	/* Create DMA tag for TX mbufs. */
1155227512Syongari	error = bus_dma_tag_create(sc->ti_cdata.ti_parent_tag, 1,
1156227512Syongari	    0, BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL,
1157227512Syongari	    MCLBYTES * TI_MAXTXSEGS, TI_MAXTXSEGS, MCLBYTES, 0, NULL, NULL,
1158227512Syongari	    &sc->ti_cdata.ti_tx_tag);
1159227512Syongari	if (error) {
1160227512Syongari		device_printf(sc->ti_dev, "could not allocate TX dma tag\n");
1161227512Syongari		return (ENOMEM);
1162227512Syongari	}
1163227512Syongari
1164227512Syongari	/* Create DMA maps for RX buffers. */
1165153396Sscottl	for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
1166227512Syongari		error = bus_dmamap_create(sc->ti_cdata.ti_rx_std_tag, 0,
1167227512Syongari		    &sc->ti_cdata.ti_rx_std_maps[i]);
1168227512Syongari		if (error) {
1169227347Syongari			device_printf(sc->ti_dev,
1170227512Syongari			    "could not create DMA map for RX\n");
1171227512Syongari			return (error);
1172227347Syongari		}
1173153396Sscottl	}
1174227512Syongari	error = bus_dmamap_create(sc->ti_cdata.ti_rx_std_tag, 0,
1175227512Syongari	    &sc->ti_cdata.ti_rx_std_sparemap);
1176227512Syongari	if (error) {
1177227347Syongari		device_printf(sc->ti_dev,
1178227512Syongari		    "could not create spare DMA map for RX\n");
1179227512Syongari		return (error);
1180227347Syongari	}
1181153396Sscottl
1182227512Syongari	/* Create DMA maps for jumbo RX buffers. */
1183153396Sscottl	for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
1184227512Syongari		error = bus_dmamap_create(sc->ti_cdata.ti_rx_jumbo_tag, 0,
1185227512Syongari		    &sc->ti_cdata.ti_rx_jumbo_maps[i]);
1186227512Syongari		if (error) {
1187227347Syongari			device_printf(sc->ti_dev,
1188227512Syongari			    "could not create DMA map for jumbo RX\n");
1189227512Syongari			return (error);
1190227347Syongari		}
1191153396Sscottl	}
1192227512Syongari	error = bus_dmamap_create(sc->ti_cdata.ti_rx_jumbo_tag, 0,
1193227512Syongari	    &sc->ti_cdata.ti_rx_jumbo_sparemap);
1194227512Syongari	if (error) {
1195227347Syongari		device_printf(sc->ti_dev,
1196227512Syongari		    "could not create spare DMA map for jumbo RX\n");
1197227512Syongari		return (error);
1198227347Syongari	}
1199227319Syongari
1200227512Syongari	/* Create DMA maps for TX buffers. */
1201227512Syongari	for (i = 0; i < TI_TX_RING_CNT; i++) {
1202227512Syongari		error = bus_dmamap_create(sc->ti_cdata.ti_tx_tag, 0,
1203227512Syongari		    &sc->ti_cdata.ti_txdesc[i].tx_dmamap);
1204227512Syongari		if (error) {
1205227512Syongari			device_printf(sc->ti_dev,
1206227512Syongari			    "could not create DMA map for TX\n");
1207227512Syongari			return (ENOMEM);
1208227512Syongari		}
1209227512Syongari	}
1210227512Syongari
1211227512Syongari	/* Mini ring and TX ring is not available on Tigon 1. */
1212227319Syongari	if (sc->ti_hwrev == TI_HWREV_TIGON)
1213227319Syongari		return (0);
1214227319Syongari
1215227512Syongari	/* TX ring */
1216227512Syongari	error = ti_dma_ring_alloc(sc, TI_RING_ALIGN, TI_TX_RING_SZ,
1217227512Syongari	    &sc->ti_cdata.ti_tx_ring_tag, (uint8_t **)&sc->ti_rdata.ti_tx_ring,
1218227512Syongari	    &sc->ti_cdata.ti_tx_ring_map, &sc->ti_rdata.ti_tx_ring_paddr,
1219227512Syongari	    "TX ring");
1220227512Syongari	if (error)
1221227512Syongari		return (error);
1222227512Syongari
1223227512Syongari	/* Mini RX ring */
1224227512Syongari	error = ti_dma_ring_alloc(sc, TI_RING_ALIGN, TI_MINI_RX_RING_SZ,
1225227512Syongari	    &sc->ti_cdata.ti_rx_mini_ring_tag,
1226227512Syongari	    (uint8_t **)&sc->ti_rdata.ti_rx_mini_ring,
1227227512Syongari	    &sc->ti_cdata.ti_rx_mini_ring_map,
1228227512Syongari	    &sc->ti_rdata.ti_rx_mini_ring_paddr, "mini RX ring");
1229227512Syongari	if (error)
1230227512Syongari		return (error);
1231227512Syongari
1232227512Syongari	/* Create DMA tag for mini RX mbufs. */
1233227512Syongari	error = bus_dma_tag_create(sc->ti_cdata.ti_parent_tag, 1, 0,
1234227512Syongari	    BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR, NULL, NULL, MHLEN, 1,
1235227512Syongari	    MHLEN, 0, NULL, NULL, &sc->ti_cdata.ti_rx_mini_tag);
1236227512Syongari	if (error) {
1237227512Syongari		device_printf(sc->ti_dev,
1238227512Syongari		    "could not allocate mini RX dma tag\n");
1239227512Syongari		return (error);
1240227512Syongari	}
1241227512Syongari
1242227512Syongari	/* Create DMA maps for mini RX buffers. */
1243153396Sscottl	for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
1244227512Syongari		error = bus_dmamap_create(sc->ti_cdata.ti_rx_mini_tag, 0,
1245227512Syongari		    &sc->ti_cdata.ti_rx_mini_maps[i]);
1246227512Syongari		if (error) {
1247227347Syongari			device_printf(sc->ti_dev,
1248227512Syongari			    "could not create DMA map for mini RX\n");
1249227512Syongari			return (error);
1250227347Syongari		}
1251153396Sscottl	}
1252227512Syongari	error = bus_dmamap_create(sc->ti_cdata.ti_rx_mini_tag, 0,
1253227512Syongari	    &sc->ti_cdata.ti_rx_mini_sparemap);
1254227512Syongari	if (error) {
1255227347Syongari		device_printf(sc->ti_dev,
1256227512Syongari		    "could not create spare DMA map for mini RX\n");
1257227512Syongari		return (error);
1258227347Syongari	}
1259153396Sscottl
1260153396Sscottl	return (0);
1261153396Sscottl}
1262153396Sscottl
1263153396Sscottlstatic void
1264227512Syongariti_dma_free(struct ti_softc *sc)
1265153396Sscottl{
1266153396Sscottl	int i;
1267153396Sscottl
1268227512Syongari	/* Destroy DMA maps for RX buffers. */
1269227512Syongari	for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
1270227512Syongari		if (sc->ti_cdata.ti_rx_std_maps[i]) {
1271227512Syongari			bus_dmamap_destroy(sc->ti_cdata.ti_rx_std_tag,
1272227512Syongari			    sc->ti_cdata.ti_rx_std_maps[i]);
1273227512Syongari			sc->ti_cdata.ti_rx_std_maps[i] = NULL;
1274227347Syongari		}
1275227347Syongari	}
1276227512Syongari	if (sc->ti_cdata.ti_rx_std_sparemap) {
1277227512Syongari		bus_dmamap_destroy(sc->ti_cdata.ti_rx_std_tag,
1278227512Syongari		    sc->ti_cdata.ti_rx_std_sparemap);
1279227512Syongari		sc->ti_cdata.ti_rx_std_sparemap = NULL;
1280227512Syongari	}
1281227512Syongari	if (sc->ti_cdata.ti_rx_std_tag) {
1282227512Syongari		bus_dma_tag_destroy(sc->ti_cdata.ti_rx_std_tag);
1283227512Syongari		sc->ti_cdata.ti_rx_std_tag = NULL;
1284227512Syongari	}
1285153396Sscottl
1286227512Syongari	/* Destroy DMA maps for jumbo RX buffers. */
1287227512Syongari	for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
1288227512Syongari		if (sc->ti_cdata.ti_rx_jumbo_maps[i]) {
1289227512Syongari			bus_dmamap_destroy(sc->ti_cdata.ti_rx_jumbo_tag,
1290227512Syongari			    sc->ti_cdata.ti_rx_jumbo_maps[i]);
1291227512Syongari			sc->ti_cdata.ti_rx_jumbo_maps[i] = NULL;
1292227347Syongari		}
1293227347Syongari	}
1294227512Syongari	if (sc->ti_cdata.ti_rx_jumbo_sparemap) {
1295227512Syongari		bus_dmamap_destroy(sc->ti_cdata.ti_rx_jumbo_tag,
1296227512Syongari		    sc->ti_cdata.ti_rx_jumbo_sparemap);
1297227512Syongari		sc->ti_cdata.ti_rx_jumbo_sparemap = NULL;
1298227512Syongari	}
1299227512Syongari	if (sc->ti_cdata.ti_rx_jumbo_tag) {
1300227512Syongari		bus_dma_tag_destroy(sc->ti_cdata.ti_rx_jumbo_tag);
1301227512Syongari		sc->ti_cdata.ti_rx_jumbo_tag = NULL;
1302227512Syongari	}
1303153396Sscottl
1304227512Syongari	/* Destroy DMA maps for mini RX buffers. */
1305227512Syongari	for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
1306227512Syongari		if (sc->ti_cdata.ti_rx_mini_maps[i]) {
1307227512Syongari			bus_dmamap_destroy(sc->ti_cdata.ti_rx_mini_tag,
1308227512Syongari			    sc->ti_cdata.ti_rx_mini_maps[i]);
1309227512Syongari			sc->ti_cdata.ti_rx_mini_maps[i] = NULL;
1310227347Syongari		}
1311227347Syongari	}
1312227512Syongari	if (sc->ti_cdata.ti_rx_mini_sparemap) {
1313227512Syongari		bus_dmamap_destroy(sc->ti_cdata.ti_rx_mini_tag,
1314227512Syongari		    sc->ti_cdata.ti_rx_mini_sparemap);
1315227512Syongari		sc->ti_cdata.ti_rx_mini_sparemap = NULL;
1316227512Syongari	}
1317227512Syongari	if (sc->ti_cdata.ti_rx_mini_tag) {
1318227512Syongari		bus_dma_tag_destroy(sc->ti_cdata.ti_rx_mini_tag);
1319227512Syongari		sc->ti_cdata.ti_rx_mini_tag = NULL;
1320227512Syongari	}
1321227347Syongari
1322227512Syongari	/* Destroy DMA maps for TX buffers. */
1323227512Syongari	for (i = 0; i < TI_TX_RING_CNT; i++) {
1324227512Syongari		if (sc->ti_cdata.ti_txdesc[i].tx_dmamap) {
1325227512Syongari			bus_dmamap_destroy(sc->ti_cdata.ti_tx_tag,
1326227512Syongari			    sc->ti_cdata.ti_txdesc[i].tx_dmamap);
1327227512Syongari			sc->ti_cdata.ti_txdesc[i].tx_dmamap = NULL;
1328227347Syongari		}
1329227347Syongari	}
1330227512Syongari	if (sc->ti_cdata.ti_tx_tag) {
1331227512Syongari		bus_dma_tag_destroy(sc->ti_cdata.ti_tx_tag);
1332227512Syongari		sc->ti_cdata.ti_tx_tag = NULL;
1333153288Sscottl	}
133445386Swpaul
1335227512Syongari	/* Destroy standard RX ring. */
1336227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_rx_std_ring_tag,
1337227512Syongari	    (void *)&sc->ti_rdata.ti_rx_std_ring,
1338267580Sjhb	    sc->ti_cdata.ti_rx_std_ring_map,
1339267580Sjhb	    &sc->ti_rdata.ti_rx_std_ring_paddr);
1340227512Syongari	/* Destroy jumbo RX ring. */
1341227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_rx_jumbo_ring_tag,
1342227512Syongari	    (void *)&sc->ti_rdata.ti_rx_jumbo_ring,
1343267580Sjhb	    sc->ti_cdata.ti_rx_jumbo_ring_map,
1344267580Sjhb	    &sc->ti_rdata.ti_rx_jumbo_ring_paddr);
1345227512Syongari	/* Destroy mini RX ring. */
1346227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_rx_mini_ring_tag,
1347227512Syongari	    (void *)&sc->ti_rdata.ti_rx_mini_ring,
1348267580Sjhb	    sc->ti_cdata.ti_rx_mini_ring_map,
1349267580Sjhb	    &sc->ti_rdata.ti_rx_mini_ring_paddr);
1350227512Syongari	/* Destroy RX return ring. */
1351227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_rx_return_ring_tag,
1352227512Syongari	    (void *)&sc->ti_rdata.ti_rx_return_ring,
1353267580Sjhb	    sc->ti_cdata.ti_rx_return_ring_map,
1354267580Sjhb	    &sc->ti_rdata.ti_rx_return_ring_paddr);
1355227512Syongari	/* Destroy TX ring. */
1356227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_tx_ring_tag,
1357267580Sjhb	    (void *)&sc->ti_rdata.ti_tx_ring, sc->ti_cdata.ti_tx_ring_map,
1358267580Sjhb	    &sc->ti_rdata.ti_tx_ring_paddr);
1359227512Syongari	/* Destroy status block. */
1360227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_status_tag,
1361267580Sjhb	    (void *)&sc->ti_rdata.ti_status, sc->ti_cdata.ti_status_map,
1362267580Sjhb	    &sc->ti_rdata.ti_status_paddr);
1363227512Syongari	/* Destroy event ring. */
1364227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_event_ring_tag,
1365227512Syongari	    (void *)&sc->ti_rdata.ti_event_ring,
1366267580Sjhb	    sc->ti_cdata.ti_event_ring_map, &sc->ti_rdata.ti_event_ring_paddr);
1367227512Syongari	/* Destroy GIB */
1368227512Syongari	ti_dma_ring_free(sc, &sc->ti_cdata.ti_gib_tag,
1369267580Sjhb	    (void *)&sc->ti_rdata.ti_info, sc->ti_cdata.ti_gib_map,
1370267580Sjhb	    &sc->ti_rdata.ti_info_paddr);
1371153396Sscottl
1372227512Syongari	/* Destroy the parent tag. */
1373227512Syongari	if (sc->ti_cdata.ti_parent_tag) {
1374227512Syongari		bus_dma_tag_destroy(sc->ti_cdata.ti_parent_tag);
1375227512Syongari		sc->ti_cdata.ti_parent_tag = NULL;
1376153396Sscottl	}
1377153396Sscottl}
1378153396Sscottl
137945386Swpaul/*
138045386Swpaul * Intialize a standard receive ring descriptor.
138145386Swpaul */
1382102336Salfredstatic int
1383227347Syongariti_newbuf_std(struct ti_softc *sc, int i)
138445386Swpaul{
1385227087Syongari	bus_dmamap_t map;
1386227347Syongari	bus_dma_segment_t segs[1];
1387227347Syongari	struct mbuf *m;
1388227087Syongari	struct ti_rx_desc *r;
1389227347Syongari	int error, nsegs;
139045386Swpaul
1391243857Sglebius	m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
1392227347Syongari	if (m == NULL)
1393227347Syongari		return (ENOBUFS);
1394227347Syongari	m->m_len = m->m_pkthdr.len = MCLBYTES;
1395227347Syongari	m_adj(m, ETHER_ALIGN);
139645386Swpaul
1397227512Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_cdata.ti_rx_std_tag,
1398227347Syongari	    sc->ti_cdata.ti_rx_std_sparemap, m, segs, &nsegs, 0);
1399227347Syongari	if (error != 0) {
1400227347Syongari		m_freem(m);
1401227347Syongari		return (error);
1402227347Syongari        }
1403227347Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
1404227347Syongari
1405227347Syongari	if (sc->ti_cdata.ti_rx_std_chain[i] != NULL) {
1406227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_std_tag,
1407227347Syongari		    sc->ti_cdata.ti_rx_std_maps[i], BUS_DMASYNC_POSTREAD);
1408227512Syongari		bus_dmamap_unload(sc->ti_cdata.ti_rx_std_tag,
1409227347Syongari		    sc->ti_cdata.ti_rx_std_maps[i]);
141045386Swpaul	}
141145386Swpaul
1412227347Syongari	map = sc->ti_cdata.ti_rx_std_maps[i];
1413227347Syongari	sc->ti_cdata.ti_rx_std_maps[i] = sc->ti_cdata.ti_rx_std_sparemap;
1414227347Syongari	sc->ti_cdata.ti_rx_std_sparemap = map;
1415227347Syongari	sc->ti_cdata.ti_rx_std_chain[i] = m;
1416227347Syongari
1417227512Syongari	r = &sc->ti_rdata.ti_rx_std_ring[i];
1418227347Syongari	ti_hostaddr64(&r->ti_addr, segs[0].ds_addr);
1419227347Syongari	r->ti_len = segs[0].ds_len;
142045386Swpaul	r->ti_type = TI_BDTYPE_RECV_BD;
142145386Swpaul	r->ti_flags = 0;
1422227347Syongari	r->ti_vlan_tag = 0;
1423227347Syongari	r->ti_tcp_udp_cksum = 0;
1424227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
142558698Sjlemon		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
142645386Swpaul	r->ti_idx = i;
142745386Swpaul
1428227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_std_tag,
1429227512Syongari	    sc->ti_cdata.ti_rx_std_maps[i], BUS_DMASYNC_PREREAD);
1430131654Sbms	return (0);
143145386Swpaul}
143245386Swpaul
143345386Swpaul/*
143445386Swpaul * Intialize a mini receive ring descriptor. This only applies to
143545386Swpaul * the Tigon 2.
143645386Swpaul */
1437102336Salfredstatic int
1438227347Syongariti_newbuf_mini(struct ti_softc *sc, int i)
143945386Swpaul{
1440227087Syongari	bus_dmamap_t map;
1441227347Syongari	bus_dma_segment_t segs[1];
1442227347Syongari	struct mbuf *m;
1443227087Syongari	struct ti_rx_desc *r;
1444227347Syongari	int error, nsegs;
144545386Swpaul
1446243857Sglebius	MGETHDR(m, M_NOWAIT, MT_DATA);
1447227347Syongari	if (m == NULL)
1448227347Syongari		return (ENOBUFS);
1449227347Syongari	m->m_len = m->m_pkthdr.len = MHLEN;
1450227347Syongari	m_adj(m, ETHER_ALIGN);
1451227347Syongari
1452227512Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_cdata.ti_rx_mini_tag,
1453227347Syongari	    sc->ti_cdata.ti_rx_mini_sparemap, m, segs, &nsegs, 0);
1454227347Syongari	if (error != 0) {
1455227347Syongari		m_freem(m);
1456227347Syongari		return (error);
1457227347Syongari        }
1458227347Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
1459227347Syongari
1460227347Syongari	if (sc->ti_cdata.ti_rx_mini_chain[i] != NULL) {
1461227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_mini_tag,
1462227347Syongari		    sc->ti_cdata.ti_rx_mini_maps[i], BUS_DMASYNC_POSTREAD);
1463227512Syongari		bus_dmamap_unload(sc->ti_cdata.ti_rx_mini_tag,
1464227347Syongari		    sc->ti_cdata.ti_rx_mini_maps[i]);
146545386Swpaul	}
146649036Swpaul
1467227347Syongari	map = sc->ti_cdata.ti_rx_mini_maps[i];
1468227347Syongari	sc->ti_cdata.ti_rx_mini_maps[i] = sc->ti_cdata.ti_rx_mini_sparemap;
1469227347Syongari	sc->ti_cdata.ti_rx_mini_sparemap = map;
1470227347Syongari	sc->ti_cdata.ti_rx_mini_chain[i] = m;
1471227347Syongari
1472227512Syongari	r = &sc->ti_rdata.ti_rx_mini_ring[i];
1473227347Syongari	ti_hostaddr64(&r->ti_addr, segs[0].ds_addr);
1474227347Syongari	r->ti_len = segs[0].ds_len;
147545386Swpaul	r->ti_type = TI_BDTYPE_RECV_BD;
147645386Swpaul	r->ti_flags = TI_BDFLAG_MINI_RING;
1477227347Syongari	r->ti_vlan_tag = 0;
1478227347Syongari	r->ti_tcp_udp_cksum = 0;
1479227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
148058698Sjlemon		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
148145386Swpaul	r->ti_idx = i;
148245386Swpaul
1483227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_mini_tag,
1484227512Syongari	    sc->ti_cdata.ti_rx_mini_maps[i], BUS_DMASYNC_PREREAD);
1485131654Sbms	return (0);
148645386Swpaul}
148745386Swpaul
1488227347Syongari#ifndef TI_SF_BUF_JUMBO
148998849Sken
149045386Swpaul/*
149145386Swpaul * Initialize a jumbo receive ring descriptor. This allocates
149245386Swpaul * a jumbo buffer from the pool managed internally by the driver.
149345386Swpaul */
1494102336Salfredstatic int
1495227347Syongariti_newbuf_jumbo(struct ti_softc *sc, int i, struct mbuf *dummy)
149645386Swpaul{
1497227087Syongari	bus_dmamap_t map;
1498227347Syongari	bus_dma_segment_t segs[1];
1499227347Syongari	struct mbuf *m;
1500227087Syongari	struct ti_rx_desc *r;
1501227347Syongari	int error, nsegs;
150245386Swpaul
1503227347Syongari	(void)dummy;
150445386Swpaul
1505243857Sglebius	m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1506227347Syongari	if (m == NULL)
1507227347Syongari		return (ENOBUFS);
1508227347Syongari	m->m_len = m->m_pkthdr.len = MJUM9BYTES;
1509227347Syongari	m_adj(m, ETHER_ALIGN);
151045386Swpaul
1511227512Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_cdata.ti_rx_jumbo_tag,
1512227347Syongari	    sc->ti_cdata.ti_rx_jumbo_sparemap, m, segs, &nsegs, 0);
1513227347Syongari	if (error != 0) {
1514227347Syongari		m_freem(m);
1515227347Syongari		return (error);
1516227347Syongari        }
1517227347Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
151845386Swpaul
1519227347Syongari	if (sc->ti_cdata.ti_rx_jumbo_chain[i] != NULL) {
1520227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_tag,
1521227347Syongari		    sc->ti_cdata.ti_rx_jumbo_maps[i], BUS_DMASYNC_POSTREAD);
1522227512Syongari		bus_dmamap_unload(sc->ti_cdata.ti_rx_jumbo_tag,
1523227347Syongari		    sc->ti_cdata.ti_rx_jumbo_maps[i]);
152445386Swpaul	}
152545386Swpaul
1526227347Syongari	map = sc->ti_cdata.ti_rx_jumbo_maps[i];
1527227347Syongari	sc->ti_cdata.ti_rx_jumbo_maps[i] = sc->ti_cdata.ti_rx_jumbo_sparemap;
1528227347Syongari	sc->ti_cdata.ti_rx_jumbo_sparemap = map;
1529227347Syongari	sc->ti_cdata.ti_rx_jumbo_chain[i] = m;
1530227347Syongari
1531227512Syongari	r = &sc->ti_rdata.ti_rx_jumbo_ring[i];
1532227347Syongari	ti_hostaddr64(&r->ti_addr, segs[0].ds_addr);
1533227347Syongari	r->ti_len = segs[0].ds_len;
153445386Swpaul	r->ti_type = TI_BDTYPE_RECV_JUMBO_BD;
153545386Swpaul	r->ti_flags = TI_BDFLAG_JUMBO_RING;
1536227347Syongari	r->ti_vlan_tag = 0;
1537227347Syongari	r->ti_tcp_udp_cksum = 0;
1538227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
153958698Sjlemon		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
154045386Swpaul	r->ti_idx = i;
154145386Swpaul
1542227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_tag,
1543227512Syongari	    sc->ti_cdata.ti_rx_jumbo_maps[i], BUS_DMASYNC_PREREAD);
1544131654Sbms	return (0);
154545386Swpaul}
154645386Swpaul
154798849Sken#else
154898849Sken
154998849Sken#if (PAGE_SIZE == 4096)
155098849Sken#define NPAYLOAD 2
155198849Sken#else
155298849Sken#define NPAYLOAD 1
1553131652Sbms#endif
155498849Sken
155598849Sken#define TCP_HDR_LEN (52 + sizeof(struct ether_header))
155698849Sken#define UDP_HDR_LEN (28 + sizeof(struct ether_header))
155798849Sken#define NFS_HDR_LEN (UDP_HDR_LEN)
1558227087Syongaristatic int HDR_LEN = TCP_HDR_LEN;
155998849Sken
1560131655Sbms/*
1561131655Sbms * Initialize a jumbo receive ring descriptor. This allocates
1562131655Sbms * a jumbo buffer from the pool managed internally by the driver.
1563131655Sbms */
156498849Skenstatic int
1565227086Syongariti_newbuf_jumbo(struct ti_softc *sc, int idx, struct mbuf *m_old)
156698849Sken{
1567227087Syongari	bus_dmamap_t map;
1568227087Syongari	struct mbuf *cur, *m_new = NULL;
1569227087Syongari	struct mbuf *m[3] = {NULL, NULL, NULL};
1570227087Syongari	struct ti_rx_desc_ext *r;
1571227087Syongari	vm_page_t frame;
1572227087Syongari	/* 1 extra buf to make nobufs easy*/
1573227087Syongari	struct sf_buf *sf[3] = {NULL, NULL, NULL};
1574227087Syongari	int i;
1575227087Syongari	bus_dma_segment_t segs[4];
1576227087Syongari	int nsegs;
157798849Sken
157898849Sken	if (m_old != NULL) {
157998849Sken		m_new = m_old;
158098849Sken		cur = m_old->m_next;
158198849Sken		for (i = 0; i <= NPAYLOAD; i++){
158298849Sken			m[i] = cur;
158398849Sken			cur = cur->m_next;
158498849Sken		}
158598849Sken	} else {
158698849Sken		/* Allocate the mbufs. */
1587243857Sglebius		MGETHDR(m_new, M_NOWAIT, MT_DATA);
158898849Sken		if (m_new == NULL) {
1589162321Sglebius			device_printf(sc->ti_dev, "mbuf allocation failed "
1590150719Sjhb			    "-- packet dropped!\n");
159198849Sken			goto nobufs;
159298849Sken		}
1593243857Sglebius		MGET(m[NPAYLOAD], M_NOWAIT, MT_DATA);
159498849Sken		if (m[NPAYLOAD] == NULL) {
1595162321Sglebius			device_printf(sc->ti_dev, "cluster mbuf allocation "
1596162321Sglebius			    "failed -- packet dropped!\n");
159798849Sken			goto nobufs;
159898849Sken		}
1599276750Srwatson		if (!(MCLGET(m[NPAYLOAD], M_NOWAIT))) {
1600162321Sglebius			device_printf(sc->ti_dev, "mbuf allocation failed "
1601150719Sjhb			    "-- packet dropped!\n");
160298849Sken			goto nobufs;
160398849Sken		}
160498849Sken		m[NPAYLOAD]->m_len = MCLBYTES;
160598849Sken
160698849Sken		for (i = 0; i < NPAYLOAD; i++){
1607243857Sglebius			MGET(m[i], M_NOWAIT, MT_DATA);
160898849Sken			if (m[i] == NULL) {
1609162321Sglebius				device_printf(sc->ti_dev, "mbuf allocation "
1610162321Sglebius				    "failed -- packet dropped!\n");
161198849Sken				goto nobufs;
161298849Sken			}
1613228522Salc			frame = vm_page_alloc(NULL, 0,
1614138424Salc			    VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ |
1615138424Salc			    VM_ALLOC_WIRED);
1616138424Salc			if (frame == NULL) {
1617162321Sglebius				device_printf(sc->ti_dev, "buffer allocation "
1618150719Sjhb				    "failed -- packet dropped!\n");
161998849Sken				printf("      index %d page %d\n", idx, i);
1620131655Sbms				goto nobufs;
162198849Sken			}
1622138424Salc			sf[i] = sf_buf_alloc(frame, SFB_NOWAIT);
1623138424Salc			if (sf[i] == NULL) {
1624267548Sattilio				vm_page_unwire(frame, PQ_INACTIVE);
1625138424Salc				vm_page_free(frame);
1626162321Sglebius				device_printf(sc->ti_dev, "buffer allocation "
1627150719Sjhb				    "failed -- packet dropped!\n");
1628138424Salc				printf("      index %d page %d\n", idx, i);
1629138424Salc				goto nobufs;
1630138424Salc			}
163198849Sken		}
163298849Sken		for (i = 0; i < NPAYLOAD; i++){
1633131655Sbms		/* Attach the buffer to the mbuf. */
1634138424Salc			m[i]->m_data = (void *)sf_buf_kva(sf[i]);
163598849Sken			m[i]->m_len = PAGE_SIZE;
1636138424Salc			MEXTADD(m[i], sf_buf_kva(sf[i]), PAGE_SIZE,
1637175872Sphk			    sf_buf_mext, (void*)sf_buf_kva(sf[i]), sf[i],
1638175872Sphk			    0, EXT_DISPOSABLE);
163998849Sken			m[i]->m_next = m[i+1];
164098849Sken		}
164198849Sken		/* link the buffers to the header */
164298849Sken		m_new->m_next = m[0];
164398849Sken		m_new->m_data += ETHER_ALIGN;
164498849Sken		if (sc->ti_hdrsplit)
164598849Sken			m_new->m_len = MHLEN - ETHER_ALIGN;
164698849Sken		else
1647131655Sbms			m_new->m_len = HDR_LEN;
164898849Sken		m_new->m_pkthdr.len = NPAYLOAD * PAGE_SIZE + m_new->m_len;
164998849Sken	}
165098849Sken
165198849Sken	/* Set up the descriptor. */
1652227512Syongari	r = &sc->ti_rdata.ti_rx_jumbo_ring[idx];
165398849Sken	sc->ti_cdata.ti_rx_jumbo_chain[idx] = m_new;
1654153396Sscottl	map = sc->ti_cdata.ti_rx_jumbo_maps[i];
1655227512Syongari	if (bus_dmamap_load_mbuf_sg(sc->ti_cdata.ti_rx_jumbo_tag, map, m_new,
1656227512Syongari	    segs, &nsegs, 0))
1657153396Sscottl		return (ENOBUFS);
1658153396Sscottl	if ((nsegs < 1) || (nsegs > 4))
1659153396Sscottl		return (ENOBUFS);
1660153396Sscottl	ti_hostaddr64(&r->ti_addr0, segs[0].ds_addr);
166198849Sken	r->ti_len0 = m_new->m_len;
166298849Sken
1663153396Sscottl	ti_hostaddr64(&r->ti_addr1, segs[1].ds_addr);
166498849Sken	r->ti_len1 = PAGE_SIZE;
166598849Sken
1666153396Sscottl	ti_hostaddr64(&r->ti_addr2, segs[2].ds_addr);
166798849Sken	r->ti_len2 = m[1]->m_ext.ext_size; /* could be PAGE_SIZE or MCLBYTES */
166898849Sken
166998849Sken	if (PAGE_SIZE == 4096) {
1670153396Sscottl		ti_hostaddr64(&r->ti_addr3, segs[3].ds_addr);
167198849Sken		r->ti_len3 = MCLBYTES;
167298849Sken	} else {
167398849Sken		r->ti_len3 = 0;
167498849Sken	}
1675131655Sbms	r->ti_type = TI_BDTYPE_RECV_JUMBO_BD;
167698849Sken
1677131655Sbms	r->ti_flags = TI_BDFLAG_JUMBO_RING|TI_RCB_FLAG_USE_EXT_RX_BD;
167898849Sken
1679227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
168098849Sken		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM|TI_BDFLAG_IP_CKSUM;
168198849Sken
1682131655Sbms	r->ti_idx = idx;
168398849Sken
1684227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_tag, map, BUS_DMASYNC_PREREAD);
1685131655Sbms	return (0);
168698849Sken
1687131655Sbmsnobufs:
168898849Sken
168998849Sken	/*
169098849Sken	 * Warning! :
169198849Sken	 * This can only be called before the mbufs are strung together.
1692131652Sbms	 * If the mbufs are strung together, m_freem() will free the chain,
169398849Sken	 * so that the later mbufs will be freed multiple times.
169498849Sken	 */
1695131655Sbms	if (m_new)
1696131655Sbms		m_freem(m_new);
169798849Sken
1698131655Sbms	for (i = 0; i < 3; i++) {
1699131655Sbms		if (m[i])
1700131655Sbms			m_freem(m[i]);
1701138424Salc		if (sf[i])
1702138424Salc			sf_buf_mext((void *)sf_buf_kva(sf[i]), sf[i]);
1703131655Sbms	}
1704131655Sbms	return (ENOBUFS);
170598849Sken}
170698849Sken#endif
170798849Sken
170845386Swpaul/*
170945386Swpaul * The standard receive ring has 512 entries in it. At 2K per mbuf cluster,
171045386Swpaul * that's 1MB or memory, which is a lot. For now, we fill only the first
171145386Swpaul * 256 ring entries and hope that our CPU is fast enough to keep up with
171245386Swpaul * the NIC.
171345386Swpaul */
1714102336Salfredstatic int
1715227086Syongariti_init_rx_ring_std(struct ti_softc *sc)
171645386Swpaul{
1717227087Syongari	int i;
1718227087Syongari	struct ti_cmd_desc cmd;
171945386Swpaul
1720227347Syongari	for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
1721227347Syongari		if (ti_newbuf_std(sc, i) != 0)
1722131654Sbms			return (ENOBUFS);
172345386Swpaul	};
172445386Swpaul
1725227347Syongari	sc->ti_std = TI_STD_RX_RING_CNT - 1;
1726227347Syongari	TI_UPDATE_STDPROD(sc, TI_STD_RX_RING_CNT - 1);
172745386Swpaul
1728131654Sbms	return (0);
172945386Swpaul}
173045386Swpaul
1731102336Salfredstatic void
1732227086Syongariti_free_rx_ring_std(struct ti_softc *sc)
173345386Swpaul{
1734227087Syongari	bus_dmamap_t map;
1735227087Syongari	int i;
173645386Swpaul
173745386Swpaul	for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
173845386Swpaul		if (sc->ti_cdata.ti_rx_std_chain[i] != NULL) {
1739153770Syongari			map = sc->ti_cdata.ti_rx_std_maps[i];
1740227512Syongari			bus_dmamap_sync(sc->ti_cdata.ti_rx_std_tag, map,
1741153770Syongari			    BUS_DMASYNC_POSTREAD);
1742227512Syongari			bus_dmamap_unload(sc->ti_cdata.ti_rx_std_tag, map);
174345386Swpaul			m_freem(sc->ti_cdata.ti_rx_std_chain[i]);
174445386Swpaul			sc->ti_cdata.ti_rx_std_chain[i] = NULL;
174545386Swpaul		}
174645386Swpaul	}
1747227512Syongari	bzero(sc->ti_rdata.ti_rx_std_ring, TI_STD_RX_RING_SZ);
1748227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_std_ring_tag,
1749227512Syongari	    sc->ti_cdata.ti_rx_std_ring_map, BUS_DMASYNC_PREWRITE);
175045386Swpaul}
175145386Swpaul
1752102336Salfredstatic int
1753227086Syongariti_init_rx_ring_jumbo(struct ti_softc *sc)
175445386Swpaul{
1755227087Syongari	struct ti_cmd_desc cmd;
1756227087Syongari	int i;
175745386Swpaul
175863699Swpaul	for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
1759227347Syongari		if (ti_newbuf_jumbo(sc, i, NULL) != 0)
1760131654Sbms			return (ENOBUFS);
176145386Swpaul	};
176245386Swpaul
1763227347Syongari	sc->ti_jumbo = TI_JUMBO_RX_RING_CNT - 1;
1764227347Syongari	TI_UPDATE_JUMBOPROD(sc, TI_JUMBO_RX_RING_CNT - 1);
176545386Swpaul
1766131654Sbms	return (0);
176745386Swpaul}
176845386Swpaul
1769102336Salfredstatic void
1770227086Syongariti_free_rx_ring_jumbo(struct ti_softc *sc)
177145386Swpaul{
1772227087Syongari	bus_dmamap_t map;
1773227087Syongari	int i;
177445386Swpaul
177545386Swpaul	for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
177645386Swpaul		if (sc->ti_cdata.ti_rx_jumbo_chain[i] != NULL) {
1777153770Syongari			map = sc->ti_cdata.ti_rx_jumbo_maps[i];
1778227512Syongari			bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_tag, map,
1779153770Syongari			    BUS_DMASYNC_POSTREAD);
1780227512Syongari			bus_dmamap_unload(sc->ti_cdata.ti_rx_jumbo_tag, map);
178145386Swpaul			m_freem(sc->ti_cdata.ti_rx_jumbo_chain[i]);
178245386Swpaul			sc->ti_cdata.ti_rx_jumbo_chain[i] = NULL;
178345386Swpaul		}
178445386Swpaul	}
1785227512Syongari	bzero(sc->ti_rdata.ti_rx_jumbo_ring, TI_JUMBO_RX_RING_SZ);
1786227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_ring_tag,
1787227512Syongari	    sc->ti_cdata.ti_rx_jumbo_ring_map, BUS_DMASYNC_PREWRITE);
178845386Swpaul}
178945386Swpaul
1790102336Salfredstatic int
1791227086Syongariti_init_rx_ring_mini(struct ti_softc *sc)
179245386Swpaul{
1793227087Syongari	int i;
179445386Swpaul
1795227347Syongari	for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
1796227347Syongari		if (ti_newbuf_mini(sc, i) != 0)
1797131654Sbms			return (ENOBUFS);
179845386Swpaul	};
179945386Swpaul
1800227347Syongari	sc->ti_mini = TI_MINI_RX_RING_CNT - 1;
1801227347Syongari	TI_UPDATE_MINIPROD(sc, TI_MINI_RX_RING_CNT - 1);
180245386Swpaul
1803131654Sbms	return (0);
180445386Swpaul}
180545386Swpaul
1806102336Salfredstatic void
1807227086Syongariti_free_rx_ring_mini(struct ti_softc *sc)
180845386Swpaul{
1809227087Syongari	bus_dmamap_t map;
1810227087Syongari	int i;
181145386Swpaul
1812227512Syongari	if (sc->ti_rdata.ti_rx_mini_ring == NULL)
1813227512Syongari		return;
1814227512Syongari
181545386Swpaul	for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
181645386Swpaul		if (sc->ti_cdata.ti_rx_mini_chain[i] != NULL) {
1817153770Syongari			map = sc->ti_cdata.ti_rx_mini_maps[i];
1818227512Syongari			bus_dmamap_sync(sc->ti_cdata.ti_rx_mini_tag, map,
1819153770Syongari			    BUS_DMASYNC_POSTREAD);
1820227512Syongari			bus_dmamap_unload(sc->ti_cdata.ti_rx_mini_tag, map);
182145386Swpaul			m_freem(sc->ti_cdata.ti_rx_mini_chain[i]);
182245386Swpaul			sc->ti_cdata.ti_rx_mini_chain[i] = NULL;
182345386Swpaul		}
182445386Swpaul	}
1825227512Syongari	bzero(sc->ti_rdata.ti_rx_mini_ring, TI_MINI_RX_RING_SZ);
1826227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_mini_ring_tag,
1827227512Syongari	    sc->ti_cdata.ti_rx_mini_ring_map, BUS_DMASYNC_PREWRITE);
182845386Swpaul}
182945386Swpaul
1830102336Salfredstatic void
1831227086Syongariti_free_tx_ring(struct ti_softc *sc)
183245386Swpaul{
1833227087Syongari	struct ti_txdesc *txd;
1834227087Syongari	int i;
183545386Swpaul
1836227512Syongari	if (sc->ti_rdata.ti_tx_ring == NULL)
183745386Swpaul		return;
183845386Swpaul
183945386Swpaul	for (i = 0; i < TI_TX_RING_CNT; i++) {
1840153982Syongari		txd = &sc->ti_cdata.ti_txdesc[i];
1841153982Syongari		if (txd->tx_m != NULL) {
1842227512Syongari			bus_dmamap_sync(sc->ti_cdata.ti_tx_tag, txd->tx_dmamap,
1843153770Syongari			    BUS_DMASYNC_POSTWRITE);
1844227512Syongari			bus_dmamap_unload(sc->ti_cdata.ti_tx_tag,
1845227512Syongari			    txd->tx_dmamap);
1846153982Syongari			m_freem(txd->tx_m);
1847153982Syongari			txd->tx_m = NULL;
184845386Swpaul		}
184945386Swpaul	}
1850227512Syongari	bzero(sc->ti_rdata.ti_tx_ring, TI_TX_RING_SZ);
1851227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_tx_ring_tag,
1852227512Syongari	    sc->ti_cdata.ti_tx_ring_map, BUS_DMASYNC_PREWRITE);
185345386Swpaul}
185445386Swpaul
1855102336Salfredstatic int
1856227086Syongariti_init_tx_ring(struct ti_softc *sc)
185745386Swpaul{
1858227087Syongari	struct ti_txdesc *txd;
1859227087Syongari	int i;
1860153982Syongari
1861153982Syongari	STAILQ_INIT(&sc->ti_cdata.ti_txfreeq);
1862153982Syongari	STAILQ_INIT(&sc->ti_cdata.ti_txbusyq);
1863153982Syongari	for (i = 0; i < TI_TX_RING_CNT; i++) {
1864153982Syongari		txd = &sc->ti_cdata.ti_txdesc[i];
1865153982Syongari		STAILQ_INSERT_TAIL(&sc->ti_cdata.ti_txfreeq, txd, tx_q);
1866153982Syongari	}
186748011Swpaul	sc->ti_txcnt = 0;
186845386Swpaul	sc->ti_tx_saved_considx = 0;
1869153778Sscottl	sc->ti_tx_saved_prodidx = 0;
187045386Swpaul	CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, 0);
1871131654Sbms	return (0);
187245386Swpaul}
187345386Swpaul
187445386Swpaul/*
187545386Swpaul * The Tigon 2 firmware has a new way to add/delete multicast addresses,
187645386Swpaul * but we have to support the old way too so that Tigon 1 cards will
187745386Swpaul * work.
187845386Swpaul */
1879105219Sphkstatic void
1880227086Syongariti_add_mcast(struct ti_softc *sc, struct ether_addr *addr)
188145386Swpaul{
1882227087Syongari	struct ti_cmd_desc cmd;
1883227089Syongari	uint16_t *m;
1884227089Syongari	uint32_t ext[2] = {0, 0};
188545386Swpaul
1886227089Syongari	m = (uint16_t *)&addr->octet[0];
188745386Swpaul
1888131654Sbms	switch (sc->ti_hwrev) {
188945386Swpaul	case TI_HWREV_TIGON:
189045386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR0, htons(m[0]));
189145386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR1, (htons(m[1]) << 16) | htons(m[2]));
189245386Swpaul		TI_DO_CMD(TI_CMD_ADD_MCAST_ADDR, 0, 0);
189345386Swpaul		break;
189445386Swpaul	case TI_HWREV_TIGON_II:
189545386Swpaul		ext[0] = htons(m[0]);
189645386Swpaul		ext[1] = (htons(m[1]) << 16) | htons(m[2]);
189745386Swpaul		TI_DO_CMD_EXT(TI_CMD_EXT_ADD_MCAST, 0, 0, (caddr_t)&ext, 2);
189845386Swpaul		break;
189945386Swpaul	default:
1900162321Sglebius		device_printf(sc->ti_dev, "unknown hwrev\n");
190145386Swpaul		break;
190245386Swpaul	}
190345386Swpaul}
190445386Swpaul
1905105219Sphkstatic void
1906227086Syongariti_del_mcast(struct ti_softc *sc, struct ether_addr *addr)
190745386Swpaul{
1908227087Syongari	struct ti_cmd_desc cmd;
1909227089Syongari	uint16_t *m;
1910227089Syongari	uint32_t ext[2] = {0, 0};
191145386Swpaul
1912227089Syongari	m = (uint16_t *)&addr->octet[0];
191345386Swpaul
1914131654Sbms	switch (sc->ti_hwrev) {
191545386Swpaul	case TI_HWREV_TIGON:
191645386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR0, htons(m[0]));
191745386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR1, (htons(m[1]) << 16) | htons(m[2]));
191845386Swpaul		TI_DO_CMD(TI_CMD_DEL_MCAST_ADDR, 0, 0);
191945386Swpaul		break;
192045386Swpaul	case TI_HWREV_TIGON_II:
192145386Swpaul		ext[0] = htons(m[0]);
192245386Swpaul		ext[1] = (htons(m[1]) << 16) | htons(m[2]);
192345386Swpaul		TI_DO_CMD_EXT(TI_CMD_EXT_DEL_MCAST, 0, 0, (caddr_t)&ext, 2);
192445386Swpaul		break;
192545386Swpaul	default:
1926162321Sglebius		device_printf(sc->ti_dev, "unknown hwrev\n");
192745386Swpaul		break;
192845386Swpaul	}
192945386Swpaul}
193045386Swpaul
193145386Swpaul/*
193245386Swpaul * Configure the Tigon's multicast address filter.
193345386Swpaul *
193445386Swpaul * The actual multicast table management is a bit of a pain, thanks to
193545386Swpaul * slight brain damage on the part of both Alteon and us. With our
193645386Swpaul * multicast code, we are only alerted when the multicast address table
193745386Swpaul * changes and at that point we only have the current list of addresses:
193845386Swpaul * we only know the current state, not the previous state, so we don't
193945386Swpaul * actually know what addresses were removed or added. The firmware has
194045386Swpaul * state, but we can't get our grubby mits on it, and there is no 'delete
194145386Swpaul * all multicast addresses' command. Hence, we have to maintain our own
194245386Swpaul * state so we know what addresses have been programmed into the NIC at
194345386Swpaul * any given time.
194445386Swpaul */
1945102336Salfredstatic void
1946227086Syongariti_setmulti(struct ti_softc *sc)
194745386Swpaul{
1948227087Syongari	struct ifnet *ifp;
1949227087Syongari	struct ifmultiaddr *ifma;
1950227087Syongari	struct ti_cmd_desc cmd;
1951227087Syongari	struct ti_mc_entry *mc;
1952227089Syongari	uint32_t intrs;
195345386Swpaul
1954153770Syongari	TI_LOCK_ASSERT(sc);
1955153770Syongari
1956147256Sbrooks	ifp = sc->ti_ifp;
195745386Swpaul
195845386Swpaul	if (ifp->if_flags & IFF_ALLMULTI) {
195945386Swpaul		TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_ENB, 0);
196045386Swpaul		return;
196145386Swpaul	} else {
196245386Swpaul		TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_DIS, 0);
196345386Swpaul	}
196445386Swpaul
196545386Swpaul	/* Disable interrupts. */
196645386Swpaul	intrs = CSR_READ_4(sc, TI_MB_HOSTINTR);
196745386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
196845386Swpaul
196945386Swpaul	/* First, zot all the existing filters. */
197071999Sphk	while (SLIST_FIRST(&sc->ti_mc_listhead) != NULL) {
197171999Sphk		mc = SLIST_FIRST(&sc->ti_mc_listhead);
197245386Swpaul		ti_del_mcast(sc, &mc->mc_addr);
197345386Swpaul		SLIST_REMOVE_HEAD(&sc->ti_mc_listhead, mc_entries);
197445386Swpaul		free(mc, M_DEVBUF);
197545386Swpaul	}
197645386Swpaul
197745386Swpaul	/* Now program new ones. */
1978195049Srwatson	if_maddr_rlock(ifp);
197972084Sphk	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
198045386Swpaul		if (ifma->ifma_addr->sa_family != AF_LINK)
198145386Swpaul			continue;
198245386Swpaul		mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF, M_NOWAIT);
1983144165Ssam		if (mc == NULL) {
1984162321Sglebius			device_printf(sc->ti_dev,
1985162321Sglebius			    "no memory for mcast filter entry\n");
1986144165Ssam			continue;
1987144165Ssam		}
198845386Swpaul		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
198945386Swpaul		    (char *)&mc->mc_addr, ETHER_ADDR_LEN);
199045386Swpaul		SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries);
199145386Swpaul		ti_add_mcast(sc, &mc->mc_addr);
199245386Swpaul	}
1993195049Srwatson	if_maddr_runlock(ifp);
199445386Swpaul
199545386Swpaul	/* Re-enable interrupts. */
199645386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
199745386Swpaul}
199845386Swpaul
199945386Swpaul/*
200045386Swpaul * Check to see if the BIOS has configured us for a 64 bit slot when
200145386Swpaul * we aren't actually in one. If we detect this condition, we can work
200245386Swpaul * around it on the Tigon 2 by setting a bit in the PCI state register,
200345386Swpaul * but for the Tigon 1 we must give up and abort the interface attach.
200445386Swpaul */
2005227431Syongaristatic int
2006227431Syongariti_64bitslot_war(struct ti_softc *sc)
200745386Swpaul{
2008227087Syongari
200945386Swpaul	if (!(CSR_READ_4(sc, TI_PCI_STATE) & TI_PCISTATE_32BIT_BUS)) {
201045386Swpaul		CSR_WRITE_4(sc, 0x600, 0);
201145386Swpaul		CSR_WRITE_4(sc, 0x604, 0);
201245386Swpaul		CSR_WRITE_4(sc, 0x600, 0x5555AAAA);
201345386Swpaul		if (CSR_READ_4(sc, 0x604) == 0x5555AAAA) {
201445386Swpaul			if (sc->ti_hwrev == TI_HWREV_TIGON)
2015131654Sbms				return (EINVAL);
201645386Swpaul			else {
201745386Swpaul				TI_SETBIT(sc, TI_PCI_STATE,
201845386Swpaul				    TI_PCISTATE_32BIT_BUS);
2019131654Sbms				return (0);
202045386Swpaul			}
202145386Swpaul		}
202245386Swpaul	}
202345386Swpaul
2024131654Sbms	return (0);
202545386Swpaul}
202645386Swpaul
202745386Swpaul/*
202845386Swpaul * Do endian, PCI and DMA initialization. Also check the on-board ROM
202945386Swpaul * self-test results.
203045386Swpaul */
2031102336Salfredstatic int
2032227086Syongariti_chipinit(struct ti_softc *sc)
203345386Swpaul{
2034227089Syongari	uint32_t cacheline;
2035227089Syongari	uint32_t pci_writemax = 0;
2036227089Syongari	uint32_t hdrsplit;
203745386Swpaul
203845386Swpaul	/* Initialize link to down state. */
203945386Swpaul	sc->ti_linkstat = TI_EV_CODE_LINK_DOWN;
204045386Swpaul
204145386Swpaul	/* Set endianness before we access any non-PCI registers. */
2042153770Syongari#if 0 && BYTE_ORDER == BIG_ENDIAN
204345386Swpaul	CSR_WRITE_4(sc, TI_MISC_HOST_CTL,
204445386Swpaul	    TI_MHC_BIGENDIAN_INIT | (TI_MHC_BIGENDIAN_INIT << 24));
204545386Swpaul#else
204645386Swpaul	CSR_WRITE_4(sc, TI_MISC_HOST_CTL,
204745386Swpaul	    TI_MHC_LITTLEENDIAN_INIT | (TI_MHC_LITTLEENDIAN_INIT << 24));
204845386Swpaul#endif
204945386Swpaul
205045386Swpaul	/* Check the ROM failed bit to see if self-tests passed. */
205145386Swpaul	if (CSR_READ_4(sc, TI_CPU_STATE) & TI_CPUSTATE_ROMFAIL) {
2052162321Sglebius		device_printf(sc->ti_dev, "board self-diagnostics failed!\n");
2053131654Sbms		return (ENODEV);
205445386Swpaul	}
205545386Swpaul
205645386Swpaul	/* Halt the CPU. */
205745386Swpaul	TI_SETBIT(sc, TI_CPU_STATE, TI_CPUSTATE_HALT);
205845386Swpaul
205945386Swpaul	/* Figure out the hardware revision. */
2060131654Sbms	switch (CSR_READ_4(sc, TI_MISC_HOST_CTL) & TI_MHC_CHIP_REV_MASK) {
206145386Swpaul	case TI_REV_TIGON_I:
206245386Swpaul		sc->ti_hwrev = TI_HWREV_TIGON;
206345386Swpaul		break;
206445386Swpaul	case TI_REV_TIGON_II:
206545386Swpaul		sc->ti_hwrev = TI_HWREV_TIGON_II;
206645386Swpaul		break;
206745386Swpaul	default:
2068162321Sglebius		device_printf(sc->ti_dev, "unsupported chip revision\n");
2069131654Sbms		return (ENODEV);
207045386Swpaul	}
207145386Swpaul
207245386Swpaul	/* Do special setup for Tigon 2. */
207345386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON_II) {
207445386Swpaul		TI_SETBIT(sc, TI_CPU_CTL_B, TI_CPUSTATE_HALT);
207576033Swpaul		TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_SRAM_BANK_512K);
207645386Swpaul		TI_SETBIT(sc, TI_MISC_CONF, TI_MCR_SRAM_SYNCHRONOUS);
207745386Swpaul	}
207845386Swpaul
207998849Sken	/*
208098849Sken	 * We don't have firmware source for the Tigon 1, so Tigon 1 boards
208198849Sken	 * can't do header splitting.
208298849Sken	 */
208398849Sken#ifdef TI_JUMBO_HDRSPLIT
208498849Sken	if (sc->ti_hwrev != TI_HWREV_TIGON)
208598849Sken		sc->ti_hdrsplit = 1;
208698849Sken	else
2087162321Sglebius		device_printf(sc->ti_dev,
2088150719Sjhb		    "can't do header splitting on a Tigon I board\n");
208998849Sken#endif /* TI_JUMBO_HDRSPLIT */
209098849Sken
209145386Swpaul	/* Set up the PCI state register. */
209245386Swpaul	CSR_WRITE_4(sc, TI_PCI_STATE, TI_PCI_READ_CMD|TI_PCI_WRITE_CMD);
209345386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON_II) {
209445386Swpaul		TI_SETBIT(sc, TI_PCI_STATE, TI_PCISTATE_USE_MEM_RD_MULT);
209545386Swpaul	}
209645386Swpaul
209745386Swpaul	/* Clear the read/write max DMA parameters. */
209845386Swpaul	TI_CLRBIT(sc, TI_PCI_STATE, (TI_PCISTATE_WRITE_MAXDMA|
209945386Swpaul	    TI_PCISTATE_READ_MAXDMA));
210045386Swpaul
210145386Swpaul	/* Get cache line size. */
210245386Swpaul	cacheline = CSR_READ_4(sc, TI_PCI_BIST) & 0xFF;
210345386Swpaul
210445386Swpaul	/*
210545386Swpaul	 * If the system has set enabled the PCI memory write
210645386Swpaul	 * and invalidate command in the command register, set
210745386Swpaul	 * the write max parameter accordingly. This is necessary
210845386Swpaul	 * to use MWI with the Tigon 2.
210945386Swpaul	 */
211045386Swpaul	if (CSR_READ_4(sc, TI_PCI_CMDSTAT) & PCIM_CMD_MWIEN) {
2111131654Sbms		switch (cacheline) {
211245386Swpaul		case 1:
211345386Swpaul		case 4:
211445386Swpaul		case 8:
211545386Swpaul		case 16:
211645386Swpaul		case 32:
211745386Swpaul		case 64:
211845386Swpaul			break;
211945386Swpaul		default:
212045386Swpaul		/* Disable PCI memory write and invalidate. */
212145386Swpaul			if (bootverbose)
2122162321Sglebius				device_printf(sc->ti_dev, "cache line size %d"
2123162321Sglebius				    " not supported; disabling PCI MWI\n",
2124150719Sjhb				    cacheline);
212545386Swpaul			CSR_WRITE_4(sc, TI_PCI_CMDSTAT, CSR_READ_4(sc,
212645386Swpaul			    TI_PCI_CMDSTAT) & ~PCIM_CMD_MWIEN);
212745386Swpaul			break;
212845386Swpaul		}
212945386Swpaul	}
213045386Swpaul
213145386Swpaul	TI_SETBIT(sc, TI_PCI_STATE, pci_writemax);
213245386Swpaul
213345386Swpaul	/* This sets the min dma param all the way up (0xff). */
213445386Swpaul	TI_SETBIT(sc, TI_PCI_STATE, TI_PCISTATE_MINDMA);
213545386Swpaul
213698849Sken	if (sc->ti_hdrsplit)
213798849Sken		hdrsplit = TI_OPMODE_JUMBO_HDRSPLIT;
213898849Sken	else
213998849Sken		hdrsplit = 0;
214098849Sken
214145386Swpaul	/* Configure DMA variables. */
214245386Swpaul#if BYTE_ORDER == BIG_ENDIAN
214345386Swpaul	CSR_WRITE_4(sc, TI_GCR_OPMODE, TI_OPMODE_BYTESWAP_BD |
214445386Swpaul	    TI_OPMODE_BYTESWAP_DATA | TI_OPMODE_WORDSWAP_BD |
214545386Swpaul	    TI_OPMODE_WARN_ENB | TI_OPMODE_FATAL_ENB |
214698849Sken	    TI_OPMODE_DONT_FRAG_JUMBO | hdrsplit);
214798849Sken#else /* BYTE_ORDER */
214845386Swpaul	CSR_WRITE_4(sc, TI_GCR_OPMODE, TI_OPMODE_BYTESWAP_DATA|
214945386Swpaul	    TI_OPMODE_WORDSWAP_BD|TI_OPMODE_DONT_FRAG_JUMBO|
215098849Sken	    TI_OPMODE_WARN_ENB|TI_OPMODE_FATAL_ENB | hdrsplit);
215198849Sken#endif /* BYTE_ORDER */
215245386Swpaul
215345386Swpaul	/*
215445386Swpaul	 * Only allow 1 DMA channel to be active at a time.
215545386Swpaul	 * I don't think this is a good idea, but without it
215645386Swpaul	 * the firmware racks up lots of nicDmaReadRingFull
215758698Sjlemon	 * errors.  This is not compatible with hardware checksums.
215845386Swpaul	 */
2159227095Syongari	if ((sc->ti_ifp->if_capenable & (IFCAP_TXCSUM | IFCAP_RXCSUM)) == 0)
216058698Sjlemon		TI_SETBIT(sc, TI_GCR_OPMODE, TI_OPMODE_1_DMA_ACTIVE);
216145386Swpaul
216245386Swpaul	/* Recommended settings from Tigon manual. */
216345386Swpaul	CSR_WRITE_4(sc, TI_GCR_DMA_WRITECFG, TI_DMA_STATE_THRESH_8W);
216445386Swpaul	CSR_WRITE_4(sc, TI_GCR_DMA_READCFG, TI_DMA_STATE_THRESH_8W);
216545386Swpaul
216645386Swpaul	if (ti_64bitslot_war(sc)) {
2167162321Sglebius		device_printf(sc->ti_dev, "bios thinks we're in a 64 bit slot, "
2168150719Sjhb		    "but we aren't");
2169131654Sbms		return (EINVAL);
217045386Swpaul	}
217145386Swpaul
2172131654Sbms	return (0);
217345386Swpaul}
217445386Swpaul
217545386Swpaul/*
217645386Swpaul * Initialize the general information block and firmware, and
217745386Swpaul * start the CPU(s) running.
217845386Swpaul */
2179102336Salfredstatic int
2180227086Syongariti_gibinit(struct ti_softc *sc)
218145386Swpaul{
2182227087Syongari	struct ifnet *ifp;
2183227087Syongari	struct ti_rcb *rcb;
2184227087Syongari	int i;
218545386Swpaul
2186153770Syongari	TI_LOCK_ASSERT(sc);
2187153770Syongari
2188147256Sbrooks	ifp = sc->ti_ifp;
218945386Swpaul
219045386Swpaul	/* Disable interrupts for now. */
219145386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
219245386Swpaul
2193227512Syongari	/* Tell the chip where to find the general information block. */
2194227512Syongari	CSR_WRITE_4(sc, TI_GCR_GENINFO_HI,
2195227512Syongari	    (uint64_t)sc->ti_rdata.ti_info_paddr >> 32);
2196227512Syongari	CSR_WRITE_4(sc, TI_GCR_GENINFO_LO,
2197227512Syongari	    sc->ti_rdata.ti_info_paddr & 0xFFFFFFFF);
219845386Swpaul
219945386Swpaul	/* Load the firmware into SRAM. */
220045386Swpaul	ti_loadfw(sc);
220145386Swpaul
220245386Swpaul	/* Set up the contents of the general info and ring control blocks. */
220345386Swpaul
220445386Swpaul	/* Set up the event ring and producer pointer. */
2205227512Syongari	bzero(sc->ti_rdata.ti_event_ring, TI_EVENT_RING_SZ);
2206227512Syongari	rcb = &sc->ti_rdata.ti_info->ti_ev_rcb;
2207227512Syongari	ti_hostaddr64(&rcb->ti_hostaddr, sc->ti_rdata.ti_event_ring_paddr);
220845386Swpaul	rcb->ti_flags = 0;
2209227512Syongari	ti_hostaddr64(&sc->ti_rdata.ti_info->ti_ev_prodidx_ptr,
2210227512Syongari	    sc->ti_rdata.ti_status_paddr +
2211227512Syongari	    offsetof(struct ti_status, ti_ev_prodidx_r));
221245386Swpaul	sc->ti_ev_prodidx.ti_idx = 0;
221345386Swpaul	CSR_WRITE_4(sc, TI_GCR_EVENTCONS_IDX, 0);
221445386Swpaul	sc->ti_ev_saved_considx = 0;
221545386Swpaul
221645386Swpaul	/* Set up the command ring and producer mailbox. */
2217227512Syongari	rcb = &sc->ti_rdata.ti_info->ti_cmd_rcb;
2218227512Syongari	ti_hostaddr64(&rcb->ti_hostaddr, TI_GCR_NIC_ADDR(TI_GCR_CMDRING));
221945386Swpaul	rcb->ti_flags = 0;
222045386Swpaul	rcb->ti_max_len = 0;
222145386Swpaul	for (i = 0; i < TI_CMD_RING_CNT; i++) {
222245386Swpaul		CSR_WRITE_4(sc, TI_GCR_CMDRING + (i * 4), 0);
222345386Swpaul	}
222445386Swpaul	CSR_WRITE_4(sc, TI_GCR_CMDCONS_IDX, 0);
222545386Swpaul	CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, 0);
222645386Swpaul	sc->ti_cmd_saved_prodidx = 0;
222745386Swpaul
222845386Swpaul	/*
222945386Swpaul	 * Assign the address of the stats refresh buffer.
223045386Swpaul	 * We re-use the current stats buffer for this to
223145386Swpaul	 * conserve memory.
223245386Swpaul	 */
2233227512Syongari	bzero(&sc->ti_rdata.ti_info->ti_stats, sizeof(struct ti_stats));
2234227512Syongari	ti_hostaddr64(&sc->ti_rdata.ti_info->ti_refresh_stats_ptr,
2235227512Syongari	    sc->ti_rdata.ti_info_paddr + offsetof(struct ti_gib, ti_stats));
223645386Swpaul
223745386Swpaul	/* Set up the standard receive ring. */
2238227512Syongari	rcb = &sc->ti_rdata.ti_info->ti_std_rx_rcb;
2239227512Syongari	ti_hostaddr64(&rcb->ti_hostaddr, sc->ti_rdata.ti_rx_std_ring_paddr);
224045386Swpaul	rcb->ti_max_len = TI_FRAMELEN;
224145386Swpaul	rcb->ti_flags = 0;
2242227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
224358698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
224458698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
2245227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2246227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
224745386Swpaul
224845386Swpaul	/* Set up the jumbo receive ring. */
2249227512Syongari	rcb = &sc->ti_rdata.ti_info->ti_jumbo_rx_rcb;
2250227512Syongari	ti_hostaddr64(&rcb->ti_hostaddr, sc->ti_rdata.ti_rx_jumbo_ring_paddr);
225198849Sken
2252227347Syongari#ifndef TI_SF_BUF_JUMBO
2253227347Syongari	rcb->ti_max_len = MJUM9BYTES - ETHER_ALIGN;
225445386Swpaul	rcb->ti_flags = 0;
225598849Sken#else
225698849Sken	rcb->ti_max_len = PAGE_SIZE;
225798849Sken	rcb->ti_flags = TI_RCB_FLAG_USE_EXT_RX_BD;
225898849Sken#endif
2259227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
226058698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
226158698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
2262227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2263227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
226445386Swpaul
226545386Swpaul	/*
226645386Swpaul	 * Set up the mini ring. Only activated on the
226745386Swpaul	 * Tigon 2 but the slot in the config block is
226845386Swpaul	 * still there on the Tigon 1.
226945386Swpaul	 */
2270227512Syongari	rcb = &sc->ti_rdata.ti_info->ti_mini_rx_rcb;
2271227512Syongari	ti_hostaddr64(&rcb->ti_hostaddr, sc->ti_rdata.ti_rx_mini_ring_paddr);
227251352Swpaul	rcb->ti_max_len = MHLEN - ETHER_ALIGN;
227345386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
227445386Swpaul		rcb->ti_flags = TI_RCB_FLAG_RING_DISABLED;
227545386Swpaul	else
227645386Swpaul		rcb->ti_flags = 0;
2277227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
227858698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
227958698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
2280227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2281227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
228245386Swpaul
228345386Swpaul	/*
228445386Swpaul	 * Set up the receive return ring.
228545386Swpaul	 */
2286227512Syongari	rcb = &sc->ti_rdata.ti_info->ti_return_rcb;
2287227512Syongari	ti_hostaddr64(&rcb->ti_hostaddr, sc->ti_rdata.ti_rx_return_ring_paddr);
228845386Swpaul	rcb->ti_flags = 0;
228945386Swpaul	rcb->ti_max_len = TI_RETURN_RING_CNT;
2290227512Syongari	ti_hostaddr64(&sc->ti_rdata.ti_info->ti_return_prodidx_ptr,
2291227512Syongari	    sc->ti_rdata.ti_status_paddr +
2292227512Syongari	    offsetof(struct ti_status, ti_return_prodidx_r));
229345386Swpaul
229445386Swpaul	/*
229545386Swpaul	 * Set up the tx ring. Note: for the Tigon 2, we have the option
229645386Swpaul	 * of putting the transmit ring in the host's address space and
229745386Swpaul	 * letting the chip DMA it instead of leaving the ring in the NIC's
229845386Swpaul	 * memory and accessing it through the shared memory region. We
229945386Swpaul	 * do this for the Tigon 2, but it doesn't work on the Tigon 1,
230045386Swpaul	 * so we have to revert to the shared memory scheme if we detect
230145386Swpaul	 * a Tigon 1 chip.
230245386Swpaul	 */
230345386Swpaul	CSR_WRITE_4(sc, TI_WINBASE, TI_TX_RING_BASE);
2304227512Syongari	if (sc->ti_rdata.ti_tx_ring != NULL)
2305227512Syongari		bzero(sc->ti_rdata.ti_tx_ring, TI_TX_RING_SZ);
2306227512Syongari	rcb = &sc->ti_rdata.ti_info->ti_tx_rcb;
230745386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
230845386Swpaul		rcb->ti_flags = 0;
230945386Swpaul	else
231045386Swpaul		rcb->ti_flags = TI_RCB_FLAG_HOST_RING;
2311227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2312227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
2313227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_TXCSUM)
231458698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
231558698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
231645386Swpaul	rcb->ti_max_len = TI_TX_RING_CNT;
231745386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
2318227512Syongari		ti_hostaddr64(&rcb->ti_hostaddr, TI_TX_RING_BASE);
231945386Swpaul	else
2320227512Syongari		ti_hostaddr64(&rcb->ti_hostaddr,
2321227512Syongari		    sc->ti_rdata.ti_tx_ring_paddr);
2322227512Syongari	ti_hostaddr64(&sc->ti_rdata.ti_info->ti_tx_considx_ptr,
2323227512Syongari	    sc->ti_rdata.ti_status_paddr +
2324227512Syongari	    offsetof(struct ti_status, ti_tx_considx_r));
232545386Swpaul
2326227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_gib_tag, sc->ti_cdata.ti_gib_map,
2327227512Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2328227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_status_tag, sc->ti_cdata.ti_status_map,
2329227512Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2330227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_event_ring_tag,
2331227512Syongari	    sc->ti_cdata.ti_event_ring_map,
2332227512Syongari	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2333227512Syongari	if (sc->ti_rdata.ti_tx_ring != NULL)
2334227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_tx_ring_tag,
2335227512Syongari		    sc->ti_cdata.ti_tx_ring_map, BUS_DMASYNC_PREWRITE);
2336153770Syongari
2337227509Syongari	/* Set up tunables */
233898849Sken#if 0
2339227512Syongari	if (ifp->if_mtu > ETHERMTU + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN)
234045386Swpaul		CSR_WRITE_4(sc, TI_GCR_RX_COAL_TICKS,
234145386Swpaul		    (sc->ti_rx_coal_ticks / 10));
234245386Swpaul	else
234398849Sken#endif
234445386Swpaul		CSR_WRITE_4(sc, TI_GCR_RX_COAL_TICKS, sc->ti_rx_coal_ticks);
234545386Swpaul	CSR_WRITE_4(sc, TI_GCR_TX_COAL_TICKS, sc->ti_tx_coal_ticks);
234645386Swpaul	CSR_WRITE_4(sc, TI_GCR_STAT_TICKS, sc->ti_stat_ticks);
234745386Swpaul	CSR_WRITE_4(sc, TI_GCR_RX_MAX_COAL_BD, sc->ti_rx_max_coal_bds);
234845386Swpaul	CSR_WRITE_4(sc, TI_GCR_TX_MAX_COAL_BD, sc->ti_tx_max_coal_bds);
234945386Swpaul	CSR_WRITE_4(sc, TI_GCR_TX_BUFFER_RATIO, sc->ti_tx_buf_ratio);
235045386Swpaul
235145386Swpaul	/* Turn interrupts on. */
235245386Swpaul	CSR_WRITE_4(sc, TI_GCR_MASK_INTRS, 0);
235345386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
235445386Swpaul
235545386Swpaul	/* Start CPU. */
235645386Swpaul	TI_CLRBIT(sc, TI_CPU_STATE, (TI_CPUSTATE_HALT|TI_CPUSTATE_STEP));
235745386Swpaul
2358131654Sbms	return (0);
235945386Swpaul}
236045386Swpaul
236145386Swpaul/*
236245386Swpaul * Probe for a Tigon chip. Check the PCI vendor and device IDs
236345386Swpaul * against our list and return its name if we find a match.
236445386Swpaul */
2365102336Salfredstatic int
2366227086Syongariti_probe(device_t dev)
236745386Swpaul{
2368227087Syongari	const struct ti_type *t;
236945386Swpaul
237045386Swpaul	t = ti_devs;
237145386Swpaul
2372131654Sbms	while (t->ti_name != NULL) {
237349011Swpaul		if ((pci_get_vendor(dev) == t->ti_vid) &&
237449011Swpaul		    (pci_get_device(dev) == t->ti_did)) {
237549011Swpaul			device_set_desc(dev, t->ti_name);
2376142398Simp			return (BUS_PROBE_DEFAULT);
237749011Swpaul		}
237845386Swpaul		t++;
237945386Swpaul	}
238045386Swpaul
2381131654Sbms	return (ENXIO);
238245386Swpaul}
238345386Swpaul
238498849Skenstatic int
2385227086Syongariti_attach(device_t dev)
238645386Swpaul{
2387227087Syongari	struct ifnet *ifp;
2388227087Syongari	struct ti_softc *sc;
2389227087Syongari	int error = 0, rid;
2390227087Syongari	u_char eaddr[6];
239145386Swpaul
239249011Swpaul	sc = device_get_softc(dev);
2393153396Sscottl	sc->ti_dev = dev;
239445386Swpaul
239593818Sjhb	mtx_init(&sc->ti_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
2396153770Syongari	    MTX_DEF);
2397199559Sjhb	callout_init_mtx(&sc->ti_watchdog, &sc->ti_mtx, 0);
2398113609Snjl	ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts);
2399147805Sscottl	ifp = sc->ti_ifp = if_alloc(IFT_ETHER);
2400147805Sscottl	if (ifp == NULL) {
2401150719Sjhb		device_printf(dev, "can not if_alloc()\n");
2402147805Sscottl		error = ENOSPC;
2403147805Sscottl		goto fail;
2404147805Sscottl	}
2405227095Syongari	sc->ti_ifp->if_hwassist = TI_CSUM_FEATURES;
2406227095Syongari	sc->ti_ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_RXCSUM;
2407147256Sbrooks	sc->ti_ifp->if_capenable = sc->ti_ifp->if_capabilities;
240869583Swpaul
240945386Swpaul	/*
241045386Swpaul	 * Map control/status registers.
241145386Swpaul	 */
241272813Swpaul	pci_enable_busmaster(dev);
241345386Swpaul
2414227311Syongari	rid = PCIR_BAR(0);
2415127135Snjl	sc->ti_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
2416178588Smarius	    RF_ACTIVE);
241749011Swpaul
241849011Swpaul	if (sc->ti_res == NULL) {
2419150719Sjhb		device_printf(dev, "couldn't map memory\n");
242049011Swpaul		error = ENXIO;
242145386Swpaul		goto fail;
242245386Swpaul	}
242345386Swpaul
242449035Swpaul	sc->ti_btag = rman_get_bustag(sc->ti_res);
242549035Swpaul	sc->ti_bhandle = rman_get_bushandle(sc->ti_res);
242649035Swpaul
242749011Swpaul	/* Allocate interrupt */
242849011Swpaul	rid = 0;
2429131652Sbms
2430127135Snjl	sc->ti_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
243149011Swpaul	    RF_SHAREABLE | RF_ACTIVE);
243245386Swpaul
243349011Swpaul	if (sc->ti_irq == NULL) {
2434150719Sjhb		device_printf(dev, "couldn't map interrupt\n");
243549011Swpaul		error = ENXIO;
243645386Swpaul		goto fail;
243745386Swpaul	}
243845386Swpaul
243945386Swpaul	if (ti_chipinit(sc)) {
2440150719Sjhb		device_printf(dev, "chip initialization failed\n");
244149011Swpaul		error = ENXIO;
244245386Swpaul		goto fail;
244345386Swpaul	}
244445386Swpaul
244545386Swpaul	/* Zero out the NIC's on-board SRAM. */
2446153770Syongari	ti_mem_zero(sc, 0x2000, 0x100000 - 0x2000);
244745386Swpaul
244845386Swpaul	/* Init again -- zeroing memory may have clobbered some registers. */
244945386Swpaul	if (ti_chipinit(sc)) {
2450150719Sjhb		device_printf(dev, "chip initialization failed\n");
245149011Swpaul		error = ENXIO;
245245386Swpaul		goto fail;
245345386Swpaul	}
245445386Swpaul
245545386Swpaul	/*
245645386Swpaul	 * Get station address from the EEPROM. Note: the manual states
245745386Swpaul	 * that the MAC address is at offset 0x8c, however the data is
245845386Swpaul	 * stored as two longwords (since that's how it's loaded into
245972645Sasmodai	 * the NIC). This means the MAC address is actually preceded
246045386Swpaul	 * by two zero bytes. We need to skip over those.
246145386Swpaul	 */
2462227512Syongari	if (ti_read_eeprom(sc, eaddr, TI_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) {
2463150719Sjhb		device_printf(dev, "failed to read station address\n");
246449011Swpaul		error = ENXIO;
246545386Swpaul		goto fail;
246645386Swpaul	}
246745386Swpaul
2468227505Syongari	/* Allocate working area for memory dump. */
2469227505Syongari	sc->ti_membuf = malloc(sizeof(uint8_t) * TI_WINLEN, M_DEVBUF, M_NOWAIT);
2470227505Syongari	sc->ti_membuf2 = malloc(sizeof(uint8_t) * TI_WINLEN, M_DEVBUF,
2471227505Syongari	    M_NOWAIT);
2472227505Syongari	if (sc->ti_membuf == NULL || sc->ti_membuf2 == NULL) {
2473227505Syongari		device_printf(dev, "cannot allocate memory buffer\n");
2474227505Syongari		error = ENOMEM;
2475227505Syongari		goto fail;
2476227505Syongari	}
2477227512Syongari	if ((error = ti_dma_alloc(sc)) != 0)
2478143903Sscottl		goto fail;
247945386Swpaul
248063699Swpaul	/*
248163699Swpaul	 * We really need a better way to tell a 1000baseTX card
248263699Swpaul	 * from a 1000baseSX one, since in theory there could be
248363699Swpaul	 * OEMed 1000baseTX cards from lame vendors who aren't
248463699Swpaul	 * clever enough to change the PCI ID. For the moment
248563699Swpaul	 * though, the AceNIC is the only copper card available.
248663699Swpaul	 */
248763699Swpaul	if (pci_get_vendor(dev) == ALT_VENDORID &&
248863699Swpaul	    pci_get_device(dev) == ALT_DEVICEID_ACENIC_COPPER)
248963699Swpaul		sc->ti_copper = 1;
249064139Swpaul	/* Ok, it's not the only copper card available. */
249164139Swpaul	if (pci_get_vendor(dev) == NG_VENDORID &&
249264139Swpaul	    pci_get_device(dev) == NG_DEVICEID_GA620T)
249364139Swpaul		sc->ti_copper = 1;
249463699Swpaul
2495227509Syongari	/* Set default tunable values. */
2496227509Syongari	ti_sysctl_node(sc);
249745386Swpaul
249845386Swpaul	/* Set up ifnet structure */
249945386Swpaul	ifp->if_softc = sc;
2500121816Sbrooks	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
2501153281Sscottl	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
250245386Swpaul	ifp->if_ioctl = ti_ioctl;
250345386Swpaul	ifp->if_start = ti_start;
250445386Swpaul	ifp->if_init = ti_init;
2505272169Sglebius	ifp->if_get_counter = ti_get_counter;
2506227092Syongari	ifp->if_baudrate = IF_Gbps(1UL);
2507227099Syongari	ifp->if_snd.ifq_drv_maxlen = TI_TX_RING_CNT - 1;
2508227099Syongari	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
2509227099Syongari	IFQ_SET_READY(&ifp->if_snd);
251045386Swpaul
251145386Swpaul	/* Set up ifmedia support. */
251263699Swpaul	if (sc->ti_copper) {
251363699Swpaul		/*
251463699Swpaul		 * Copper cards allow manual 10/100 mode selection,
251563699Swpaul		 * but not manual 1000baseTX mode selection. Why?
251663699Swpaul		 * Becuase currently there's no way to specify the
251763699Swpaul		 * master/slave setting through the firmware interface,
251863699Swpaul		 * so Alteon decided to just bag it and handle it
251963699Swpaul		 * via autonegotiation.
252063699Swpaul		 */
252163699Swpaul		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
252263699Swpaul		ifmedia_add(&sc->ifmedia,
252363699Swpaul		    IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
252463699Swpaul		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
252563699Swpaul		ifmedia_add(&sc->ifmedia,
252663699Swpaul		    IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
252795673Sphk		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_1000_T, 0, NULL);
252863699Swpaul		ifmedia_add(&sc->ifmedia,
252995673Sphk		    IFM_ETHER|IFM_1000_T|IFM_FDX, 0, NULL);
253063699Swpaul	} else {
253163699Swpaul		/* Fiber cards don't support 10/100 modes. */
253263699Swpaul		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL);
253363699Swpaul		ifmedia_add(&sc->ifmedia,
253463699Swpaul		    IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL);
253563699Swpaul	}
253645386Swpaul	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
253745386Swpaul	ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
253845386Swpaul
253945386Swpaul	/*
254098849Sken	 * We're assuming here that card initialization is a sequential
254198849Sken	 * thing.  If it isn't, multiple cards probing at the same time
254298849Sken	 * could stomp on the list of softcs here.
254398849Sken	 */
254498849Sken
254598849Sken	/* Register the device */
2546227311Syongari	sc->dev = make_dev(&ti_cdevsw, device_get_unit(dev), UID_ROOT,
2547227311Syongari	    GID_OPERATOR, 0600, "ti%d", device_get_unit(dev));
2548120980Sphk	sc->dev->si_drv1 = sc;
254998849Sken
255098849Sken	/*
255163090Sarchie	 * Call MI attach routine.
255245386Swpaul	 */
2553147256Sbrooks	ether_ifattach(ifp, eaddr);
255445386Swpaul
2555227095Syongari	/* VLAN capability setup. */
2556227095Syongari	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM |
2557227095Syongari	    IFCAP_VLAN_HWTAGGING;
2558227095Syongari	ifp->if_capenable = ifp->if_capabilities;
2559227095Syongari	/* Tell the upper layer we support VLAN over-sized frames. */
2560227095Syongari	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
2561227095Syongari
2562227092Syongari	/* Driver supports link state tracking. */
2563227092Syongari	ifp->if_capabilities |= IFCAP_LINKSTATE;
2564227092Syongari	ifp->if_capenable |= IFCAP_LINKSTATE;
2565227092Syongari
2566113609Snjl	/* Hook interrupt last to avoid having to lock softc */
2567153281Sscottl	error = bus_setup_intr(dev, sc->ti_irq, INTR_TYPE_NET|INTR_MPSAFE,
2568166901Spiso	   NULL, ti_intr, sc, &sc->ti_intrhand);
2569112872Snjl
2570112872Snjl	if (error) {
2571150719Sjhb		device_printf(dev, "couldn't set up irq\n");
2572112872Snjl		goto fail;
2573112872Snjl	}
2574112872Snjl
257545386Swpaulfail:
2576153770Syongari	if (error)
2577112872Snjl		ti_detach(dev);
2578112872Snjl
2579131654Sbms	return (error);
258045386Swpaul}
258145386Swpaul
258298849Sken/*
2583113609Snjl * Shutdown hardware and free up resources. This can be called any
2584113609Snjl * time after the mutex has been initialized. It is called in both
2585113609Snjl * the error case in attach and the normal detach case so it needs
2586113609Snjl * to be careful about only freeing resources that have actually been
2587113609Snjl * allocated.
2588113609Snjl */
2589102336Salfredstatic int
2590227086Syongariti_detach(device_t dev)
259149011Swpaul{
2592227087Syongari	struct ti_softc *sc;
2593227087Syongari	struct ifnet *ifp;
259449011Swpaul
259549011Swpaul	sc = device_get_softc(dev);
2596144407Sscottl	if (sc->dev)
2597144407Sscottl		destroy_dev(sc->dev);
2598112930Sphk	KASSERT(mtx_initialized(&sc->ti_mtx), ("ti mutex not initialized"));
2599147256Sbrooks	ifp = sc->ti_ifp;
2600199559Sjhb	if (device_is_attached(dev)) {
2601199559Sjhb		ether_ifdetach(ifp);
2602199559Sjhb		TI_LOCK(sc);
2603153770Syongari		ti_stop(sc);
2604199559Sjhb		TI_UNLOCK(sc);
2605199559Sjhb	}
260649011Swpaul
2607113609Snjl	/* These should only be active if attach succeeded */
2608199559Sjhb	callout_drain(&sc->ti_watchdog);
2609199559Sjhb	bus_generic_detach(dev);
2610227512Syongari	ti_dma_free(sc);
2611113609Snjl	ifmedia_removeall(&sc->ifmedia);
261249011Swpaul
2613112872Snjl	if (sc->ti_intrhand)
2614112872Snjl		bus_teardown_intr(dev, sc->ti_irq, sc->ti_intrhand);
2615112872Snjl	if (sc->ti_irq)
2616112872Snjl		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ti_irq);
2617112872Snjl	if (sc->ti_res) {
2618227311Syongari		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
2619112872Snjl		    sc->ti_res);
2620112872Snjl	}
2621151297Sru	if (ifp)
2622151297Sru		if_free(ifp);
2623227505Syongari	if (sc->ti_membuf)
2624227505Syongari		free(sc->ti_membuf, M_DEVBUF);
2625227505Syongari	if (sc->ti_membuf2)
2626227505Syongari		free(sc->ti_membuf2, M_DEVBUF);
262749011Swpaul
262867087Swpaul	mtx_destroy(&sc->ti_mtx);
262949011Swpaul
2630131654Sbms	return (0);
263149011Swpaul}
263249011Swpaul
263398849Sken#ifdef TI_JUMBO_HDRSPLIT
263445386Swpaul/*
263598849Sken * If hdr_len is 0, that means that header splitting wasn't done on
263698849Sken * this packet for some reason.  The two most likely reasons are that
263798849Sken * the protocol isn't a supported protocol for splitting, or this
263898849Sken * packet had a fragment offset that wasn't 0.
263998849Sken *
264098849Sken * The header length, if it is non-zero, will always be the length of
264198849Sken * the headers on the packet, but that length could be longer than the
264298849Sken * first mbuf.  So we take the minimum of the two as the actual
2643131652Sbms * length.
264498849Sken */
264598849Skenstatic __inline void
264698849Skenti_hdr_split(struct mbuf *top, int hdr_len, int pkt_len, int idx)
264798849Sken{
264898849Sken	int i = 0;
264998849Sken	int lengths[4] = {0, 0, 0, 0};
265098849Sken	struct mbuf *m, *mp;
265198849Sken
265298849Sken	if (hdr_len != 0)
265398849Sken		top->m_len = min(hdr_len, top->m_len);
265498849Sken	pkt_len -= top->m_len;
265598849Sken	lengths[i++] = top->m_len;
265698849Sken
265798849Sken	mp = top;
265898849Sken	for (m = top->m_next; m && pkt_len; m = m->m_next) {
265998849Sken		m->m_len = m->m_ext.ext_size = min(m->m_len, pkt_len);
266098849Sken		pkt_len -= m->m_len;
266198849Sken		lengths[i++] = m->m_len;
266298849Sken		mp = m;
266398849Sken	}
266498849Sken
266598849Sken#if 0
266698849Sken	if (hdr_len != 0)
266798849Sken		printf("got split packet: ");
266898849Sken	else
266998849Sken		printf("got non-split packet: ");
2670131652Sbms
267198849Sken	printf("%d,%d,%d,%d = %d\n", lengths[0],
267298849Sken	    lengths[1], lengths[2], lengths[3],
267398849Sken	    lengths[0] + lengths[1] + lengths[2] +
267498849Sken	    lengths[3]);
267598849Sken#endif
267698849Sken
267798849Sken	if (pkt_len)
267898849Sken		panic("header splitting didn't");
2679131652Sbms
268098849Sken	if (m) {
268198849Sken		m_freem(m);
268298849Sken		mp->m_next = NULL;
268398849Sken
268498849Sken	}
268598849Sken	if (mp->m_next != NULL)
268698849Sken		panic("ti_hdr_split: last mbuf in chain should be null");
268798849Sken}
268898849Sken#endif /* TI_JUMBO_HDRSPLIT */
268998849Sken
2690227347Syongaristatic void
2691227347Syongariti_discard_std(struct ti_softc *sc, int i)
2692227347Syongari{
2693227347Syongari
2694227347Syongari	struct ti_rx_desc *r;
2695227347Syongari
2696227512Syongari	r = &sc->ti_rdata.ti_rx_std_ring[i];
2697227347Syongari	r->ti_len = MCLBYTES - ETHER_ALIGN;
2698227347Syongari	r->ti_type = TI_BDTYPE_RECV_BD;
2699227347Syongari	r->ti_flags = 0;
2700227347Syongari	r->ti_vlan_tag = 0;
2701227347Syongari	r->ti_tcp_udp_cksum = 0;
2702227347Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
2703227347Syongari		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
2704227347Syongari	r->ti_idx = i;
2705227347Syongari}
2706227347Syongari
2707227347Syongaristatic void
2708227347Syongariti_discard_mini(struct ti_softc *sc, int i)
2709227347Syongari{
2710227347Syongari
2711227347Syongari	struct ti_rx_desc *r;
2712227347Syongari
2713227512Syongari	r = &sc->ti_rdata.ti_rx_mini_ring[i];
2714227347Syongari	r->ti_len = MHLEN - ETHER_ALIGN;
2715227347Syongari	r->ti_type = TI_BDTYPE_RECV_BD;
2716227347Syongari	r->ti_flags = TI_BDFLAG_MINI_RING;
2717227347Syongari	r->ti_vlan_tag = 0;
2718227347Syongari	r->ti_tcp_udp_cksum = 0;
2719227347Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
2720227347Syongari		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
2721227347Syongari	r->ti_idx = i;
2722227347Syongari}
2723227347Syongari
2724227347Syongari#ifndef TI_SF_BUF_JUMBO
2725227347Syongaristatic void
2726227347Syongariti_discard_jumbo(struct ti_softc *sc, int i)
2727227347Syongari{
2728227347Syongari
2729227347Syongari	struct ti_rx_desc *r;
2730227347Syongari
2731227512Syongari	r = &sc->ti_rdata.ti_rx_jumbo_ring[i];
2732227347Syongari	r->ti_len = MJUM9BYTES - ETHER_ALIGN;
2733227347Syongari	r->ti_type = TI_BDTYPE_RECV_JUMBO_BD;
2734227347Syongari	r->ti_flags = TI_BDFLAG_JUMBO_RING;
2735227347Syongari	r->ti_vlan_tag = 0;
2736227347Syongari	r->ti_tcp_udp_cksum = 0;
2737227347Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
2738227347Syongari		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
2739227347Syongari	r->ti_idx = i;
2740227347Syongari}
2741227347Syongari#endif
2742227347Syongari
274398849Sken/*
274445386Swpaul * Frame reception handling. This is called if there's a frame
274545386Swpaul * on the receive return list.
274645386Swpaul *
274745386Swpaul * Note: we have to be able to handle three possibilities here:
274845386Swpaul * 1) the frame is from the mini receive ring (can only happen)
274945386Swpaul *    on Tigon 2 boards)
275045386Swpaul * 2) the frame is from the jumbo recieve ring
275145386Swpaul * 3) the frame is from the standard receive ring
275245386Swpaul */
275345386Swpaul
2754102336Salfredstatic void
2755227086Syongariti_rxeof(struct ti_softc *sc)
275645386Swpaul{
2757227087Syongari	struct ifnet *ifp;
2758227347Syongari#ifdef TI_SF_BUF_JUMBO
2759227087Syongari	bus_dmamap_t map;
2760227347Syongari#endif
2761227087Syongari	struct ti_cmd_desc cmd;
2762227347Syongari	int jumbocnt, minicnt, stdcnt, ti_len;
276345386Swpaul
2764122689Ssam	TI_LOCK_ASSERT(sc);
2765122689Ssam
2766147256Sbrooks	ifp = sc->ti_ifp;
276745386Swpaul
2768227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_std_ring_tag,
2769227512Syongari	    sc->ti_cdata.ti_rx_std_ring_map, BUS_DMASYNC_POSTWRITE);
2770227512Syongari	if (ifp->if_mtu > ETHERMTU + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN)
2771227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_ring_tag,
2772227512Syongari		    sc->ti_cdata.ti_rx_jumbo_ring_map, BUS_DMASYNC_POSTWRITE);
2773227512Syongari	if (sc->ti_rdata.ti_rx_mini_ring != NULL)
2774227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_mini_ring_tag,
2775227512Syongari		    sc->ti_cdata.ti_rx_mini_ring_map, BUS_DMASYNC_POSTWRITE);
2776227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_return_ring_tag,
2777227512Syongari	    sc->ti_cdata.ti_rx_return_ring_map, BUS_DMASYNC_POSTREAD);
2778227512Syongari
2779227318Syongari	jumbocnt = minicnt = stdcnt = 0;
2780131654Sbms	while (sc->ti_rx_saved_considx != sc->ti_return_prodidx.ti_idx) {
2781227087Syongari		struct ti_rx_desc *cur_rx;
2782227318Syongari		uint32_t rxidx;
2783227087Syongari		struct mbuf *m = NULL;
2784227089Syongari		uint16_t vlan_tag = 0;
2785227087Syongari		int have_tag = 0;
278645386Swpaul
278745386Swpaul		cur_rx =
2788227512Syongari		    &sc->ti_rdata.ti_rx_return_ring[sc->ti_rx_saved_considx];
278945386Swpaul		rxidx = cur_rx->ti_idx;
2790227347Syongari		ti_len = cur_rx->ti_len;
279145386Swpaul		TI_INC(sc->ti_rx_saved_considx, TI_RETURN_RING_CNT);
279245386Swpaul
279345386Swpaul		if (cur_rx->ti_flags & TI_BDFLAG_VLAN_TAG) {
279445386Swpaul			have_tag = 1;
2795227094Syongari			vlan_tag = cur_rx->ti_vlan_tag;
279645386Swpaul		}
279745386Swpaul
279845386Swpaul		if (cur_rx->ti_flags & TI_BDFLAG_JUMBO_RING) {
2799227318Syongari			jumbocnt++;
280045386Swpaul			TI_INC(sc->ti_jumbo, TI_JUMBO_RX_RING_CNT);
280145386Swpaul			m = sc->ti_cdata.ti_rx_jumbo_chain[rxidx];
2802227347Syongari#ifndef TI_SF_BUF_JUMBO
2803227347Syongari			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
2804272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2805227347Syongari				ti_discard_jumbo(sc, rxidx);
2806227347Syongari				continue;
2807227347Syongari			}
2808227347Syongari			if (ti_newbuf_jumbo(sc, rxidx, NULL) != 0) {
2809272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2810227347Syongari				ti_discard_jumbo(sc, rxidx);
2811227347Syongari				continue;
2812227347Syongari			}
2813227347Syongari			m->m_len = ti_len;
2814227347Syongari#else /* !TI_SF_BUF_JUMBO */
281545386Swpaul			sc->ti_cdata.ti_rx_jumbo_chain[rxidx] = NULL;
2816153396Sscottl			map = sc->ti_cdata.ti_rx_jumbo_maps[rxidx];
2817227512Syongari			bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_tag, map,
2818153396Sscottl			    BUS_DMASYNC_POSTREAD);
2819227512Syongari			bus_dmamap_unload(sc->ti_cdata.ti_rx_jumbo_tag, map);
282045386Swpaul			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
2821272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
282245386Swpaul				ti_newbuf_jumbo(sc, sc->ti_jumbo, m);
282345386Swpaul				continue;
282445386Swpaul			}
282548597Swpaul			if (ti_newbuf_jumbo(sc, sc->ti_jumbo, NULL) == ENOBUFS) {
2826272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
282748597Swpaul				ti_newbuf_jumbo(sc, sc->ti_jumbo, m);
282848597Swpaul				continue;
282948597Swpaul			}
283098849Sken#ifdef TI_JUMBO_HDRSPLIT
283198849Sken			if (sc->ti_hdrsplit)
283298849Sken				ti_hdr_split(m, TI_HOSTADDR(cur_rx->ti_addr),
2833227347Syongari					     ti_len, rxidx);
283498849Sken			else
283598849Sken#endif /* TI_JUMBO_HDRSPLIT */
2836227347Syongari			m_adj(m, ti_len - m->m_pkthdr.len);
2837227347Syongari#endif /* TI_SF_BUF_JUMBO */
283845386Swpaul		} else if (cur_rx->ti_flags & TI_BDFLAG_MINI_RING) {
2839227318Syongari			minicnt++;
284045386Swpaul			TI_INC(sc->ti_mini, TI_MINI_RX_RING_CNT);
284145386Swpaul			m = sc->ti_cdata.ti_rx_mini_chain[rxidx];
284245386Swpaul			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
2843272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2844227347Syongari				ti_discard_mini(sc, rxidx);
284545386Swpaul				continue;
284645386Swpaul			}
2847227347Syongari			if (ti_newbuf_mini(sc, rxidx) != 0) {
2848272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2849227347Syongari				ti_discard_mini(sc, rxidx);
285048597Swpaul				continue;
285148597Swpaul			}
2852227347Syongari			m->m_len = ti_len;
285345386Swpaul		} else {
2854227318Syongari			stdcnt++;
285545386Swpaul			TI_INC(sc->ti_std, TI_STD_RX_RING_CNT);
285645386Swpaul			m = sc->ti_cdata.ti_rx_std_chain[rxidx];
285745386Swpaul			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
2858272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
2859227347Syongari				ti_discard_std(sc, rxidx);
286045386Swpaul				continue;
286145386Swpaul			}
2862227347Syongari			if (ti_newbuf_std(sc, rxidx) != 0) {
2863272169Sglebius				if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
2864227347Syongari				ti_discard_std(sc, rxidx);
286548597Swpaul				continue;
286648597Swpaul			}
2867227347Syongari			m->m_len = ti_len;
286845386Swpaul		}
286945386Swpaul
2870227347Syongari		m->m_pkthdr.len = ti_len;
2871272169Sglebius		if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
287245386Swpaul		m->m_pkthdr.rcvif = ifp;
287345386Swpaul
2874227095Syongari		if (ifp->if_capenable & IFCAP_RXCSUM) {
2875227095Syongari			if (cur_rx->ti_flags & TI_BDFLAG_IP_CKSUM) {
2876227095Syongari				m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
2877227095Syongari				if ((cur_rx->ti_ip_cksum ^ 0xffff) == 0)
2878227095Syongari					m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
2879227095Syongari			}
2880227095Syongari			if (cur_rx->ti_flags & TI_BDFLAG_TCP_UDP_CKSUM) {
2881227095Syongari				m->m_pkthdr.csum_data =
2882227095Syongari				    cur_rx->ti_tcp_udp_cksum;
2883227095Syongari				m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
2884227095Syongari			}
288558698Sjlemon		}
288645386Swpaul
288745386Swpaul		/*
2888106936Ssam		 * If we received a packet with a vlan tag,
2889106936Ssam		 * tag it before passing the packet upward.
289045386Swpaul		 */
2891153512Sglebius		if (have_tag) {
2892162375Sandre			m->m_pkthdr.ether_vtag = vlan_tag;
2893162375Sandre			m->m_flags |= M_VLANTAG;
2894153512Sglebius		}
2895122689Ssam		TI_UNLOCK(sc);
2896106936Ssam		(*ifp->if_input)(ifp, m);
2897122689Ssam		TI_LOCK(sc);
289845386Swpaul	}
289945386Swpaul
2900227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_rx_return_ring_tag,
2901227512Syongari	    sc->ti_cdata.ti_rx_return_ring_map, BUS_DMASYNC_PREREAD);
290245386Swpaul	/* Only necessary on the Tigon 1. */
290345386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
290445386Swpaul		CSR_WRITE_4(sc, TI_GCR_RXRETURNCONS_IDX,
290545386Swpaul		    sc->ti_rx_saved_considx);
290645386Swpaul
2907227512Syongari	if (stdcnt > 0) {
2908227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_std_ring_tag,
2909227512Syongari		    sc->ti_cdata.ti_rx_std_ring_map, BUS_DMASYNC_PREWRITE);
2910227318Syongari		TI_UPDATE_STDPROD(sc, sc->ti_std);
2911227512Syongari	}
2912227512Syongari	if (minicnt > 0) {
2913227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_mini_ring_tag,
2914227512Syongari		    sc->ti_cdata.ti_rx_mini_ring_map, BUS_DMASYNC_PREWRITE);
2915227318Syongari		TI_UPDATE_MINIPROD(sc, sc->ti_mini);
2916227512Syongari	}
2917227512Syongari	if (jumbocnt > 0) {
2918227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_rx_jumbo_ring_tag,
2919227512Syongari		    sc->ti_cdata.ti_rx_jumbo_ring_map, BUS_DMASYNC_PREWRITE);
2920227318Syongari		TI_UPDATE_JUMBOPROD(sc, sc->ti_jumbo);
2921227512Syongari	}
292245386Swpaul}
292345386Swpaul
2924102336Salfredstatic void
2925227086Syongariti_txeof(struct ti_softc *sc)
292645386Swpaul{
2927227087Syongari	struct ti_txdesc *txd;
2928227087Syongari	struct ti_tx_desc txdesc;
2929227087Syongari	struct ti_tx_desc *cur_tx = NULL;
2930227087Syongari	struct ifnet *ifp;
2931227087Syongari	int idx;
293245386Swpaul
2933147256Sbrooks	ifp = sc->ti_ifp;
293445386Swpaul
2935153982Syongari	txd = STAILQ_FIRST(&sc->ti_cdata.ti_txbusyq);
2936153982Syongari	if (txd == NULL)
2937153982Syongari		return;
2938227512Syongari
2939227512Syongari	if (sc->ti_rdata.ti_tx_ring != NULL)
2940227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_tx_ring_tag,
2941227512Syongari		    sc->ti_cdata.ti_tx_ring_map, BUS_DMASYNC_POSTWRITE);
294245386Swpaul	/*
294345386Swpaul	 * Go through our tx ring and free mbufs for those
294445386Swpaul	 * frames that have been sent.
294545386Swpaul	 */
2946153982Syongari	for (idx = sc->ti_tx_saved_considx; idx != sc->ti_tx_considx.ti_idx;
2947153982Syongari	    TI_INC(idx, TI_TX_RING_CNT)) {
294845386Swpaul		if (sc->ti_hwrev == TI_HWREV_TIGON) {
2949153770Syongari			ti_mem_read(sc, TI_TX_RING_BASE + idx * sizeof(txdesc),
2950153770Syongari			    sizeof(txdesc), &txdesc);
2951153770Syongari			cur_tx = &txdesc;
295245386Swpaul		} else
2953227512Syongari			cur_tx = &sc->ti_rdata.ti_tx_ring[idx];
295448011Swpaul		sc->ti_txcnt--;
2955153982Syongari		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2956153982Syongari		if ((cur_tx->ti_flags & TI_BDFLAG_END) == 0)
2957153982Syongari			continue;
2958227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_tx_tag, txd->tx_dmamap,
2959153982Syongari		    BUS_DMASYNC_POSTWRITE);
2960227512Syongari		bus_dmamap_unload(sc->ti_cdata.ti_tx_tag, txd->tx_dmamap);
2961153982Syongari
2962272169Sglebius		if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
2963153982Syongari		m_freem(txd->tx_m);
2964153982Syongari		txd->tx_m = NULL;
2965153982Syongari		STAILQ_REMOVE_HEAD(&sc->ti_cdata.ti_txbusyq, tx_q);
2966153982Syongari		STAILQ_INSERT_TAIL(&sc->ti_cdata.ti_txfreeq, txd, tx_q);
2967153982Syongari		txd = STAILQ_FIRST(&sc->ti_cdata.ti_txbusyq);
296845386Swpaul	}
2969153982Syongari	sc->ti_tx_saved_considx = idx;
2970227512Syongari	if (sc->ti_txcnt == 0)
2971227512Syongari		sc->ti_timer = 0;
297245386Swpaul}
297345386Swpaul
2974102336Salfredstatic void
2975227086Syongariti_intr(void *xsc)
297645386Swpaul{
2977227087Syongari	struct ti_softc *sc;
2978227087Syongari	struct ifnet *ifp;
297945386Swpaul
298045386Swpaul	sc = xsc;
298167087Swpaul	TI_LOCK(sc);
2982147256Sbrooks	ifp = sc->ti_ifp;
298345386Swpaul
298445386Swpaul	/* Make sure this is really our interrupt. */
298567087Swpaul	if (!(CSR_READ_4(sc, TI_MISC_HOST_CTL) & TI_MHC_INTSTATE)) {
298667087Swpaul		TI_UNLOCK(sc);
298745386Swpaul		return;
298867087Swpaul	}
298945386Swpaul
299045386Swpaul	/* Ack interrupt and stop others from occuring. */
299145386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
299245386Swpaul
2993148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2994227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_status_tag,
2995227512Syongari		    sc->ti_cdata.ti_status_map, BUS_DMASYNC_POSTREAD);
299645386Swpaul		/* Check RX return ring producer/consumer */
299745386Swpaul		ti_rxeof(sc);
299845386Swpaul
299945386Swpaul		/* Check TX ring producer/consumer */
300045386Swpaul		ti_txeof(sc);
3001227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_status_tag,
3002227512Syongari		    sc->ti_cdata.ti_status_map, BUS_DMASYNC_PREREAD);
300345386Swpaul	}
300445386Swpaul
300545386Swpaul	ti_handle_events(sc);
300645386Swpaul
3007227099Syongari	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3008227098Syongari		/* Re-enable interrupts. */
3009227098Syongari		CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
3010227099Syongari		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
3011227099Syongari			ti_start_locked(ifp);
3012227098Syongari	}
301345386Swpaul
301467087Swpaul	TI_UNLOCK(sc);
301545386Swpaul}
301645386Swpaul
3017272169Sglebiusstatic uint64_t
3018272169Sglebiusti_get_counter(struct ifnet *ifp, ift_counter cnt)
301945386Swpaul{
302045386Swpaul
3021272169Sglebius	switch (cnt) {
3022272169Sglebius	case IFCOUNTER_COLLISIONS:
3023272169Sglebius	    {
3024272169Sglebius		struct ti_softc *sc;
3025272169Sglebius		struct ti_stats *s;
3026272169Sglebius		uint64_t rv;
302745386Swpaul
3028272169Sglebius		sc = if_getsoftc(ifp);
3029272169Sglebius		s = &sc->ti_rdata.ti_info->ti_stats;
3030153770Syongari
3031272169Sglebius		TI_LOCK(sc);
3032272169Sglebius		bus_dmamap_sync(sc->ti_cdata.ti_gib_tag,
3033272169Sglebius		    sc->ti_cdata.ti_gib_map, BUS_DMASYNC_POSTREAD);
3034272169Sglebius		rv = s->dot3StatsSingleCollisionFrames +
3035272169Sglebius		    s->dot3StatsMultipleCollisionFrames +
3036272169Sglebius		    s->dot3StatsExcessiveCollisions +
3037272169Sglebius		    s->dot3StatsLateCollisions;
3038272169Sglebius		bus_dmamap_sync(sc->ti_cdata.ti_gib_tag,
3039272169Sglebius		    sc->ti_cdata.ti_gib_map, BUS_DMASYNC_PREREAD);
3040272169Sglebius		TI_UNLOCK(sc);
3041272169Sglebius		return (rv);
3042272169Sglebius	    }
3043272169Sglebius	default:
3044272169Sglebius		return (if_get_counter_default(ifp, cnt));
3045272169Sglebius	}
304645386Swpaul}
304745386Swpaul
3048153982Syongari/*
3049153982Syongari * Encapsulate an mbuf chain in the tx ring  by coupling the mbuf data
3050153982Syongari * pointers to descriptors.
3051153982Syongari */
3052153982Syongaristatic int
3053227086Syongariti_encap(struct ti_softc *sc, struct mbuf **m_head)
3054153396Sscottl{
3055227087Syongari	struct ti_txdesc *txd;
3056227087Syongari	struct ti_tx_desc *f;
3057227087Syongari	struct ti_tx_desc txdesc;
3058227087Syongari	struct mbuf *m;
3059227087Syongari	bus_dma_segment_t txsegs[TI_MAXTXSEGS];
3060227089Syongari	uint16_t csum_flags;
3061227087Syongari	int error, frag, i, nseg;
3062153396Sscottl
3063153982Syongari	if ((txd = STAILQ_FIRST(&sc->ti_cdata.ti_txfreeq)) == NULL)
3064153982Syongari		return (ENOBUFS);
3065153396Sscottl
3066227512Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_cdata.ti_tx_tag, txd->tx_dmamap,
3067161236Syongari	    *m_head, txsegs, &nseg, 0);
3068153982Syongari	if (error == EFBIG) {
3069243857Sglebius		m = m_defrag(*m_head, M_NOWAIT);
3070161236Syongari		if (m == NULL) {
3071161236Syongari			m_freem(*m_head);
3072161236Syongari			*m_head = NULL;
3073153982Syongari			return (ENOMEM);
3074153982Syongari		}
3075161236Syongari		*m_head = m;
3076227512Syongari		error = bus_dmamap_load_mbuf_sg(sc->ti_cdata.ti_tx_tag,
3077161236Syongari		    txd->tx_dmamap, *m_head, txsegs, &nseg, 0);
3078153982Syongari		if (error) {
3079161236Syongari			m_freem(*m_head);
3080161236Syongari			*m_head = NULL;
3081153982Syongari			return (error);
3082153982Syongari		}
3083153982Syongari	} else if (error != 0)
3084153982Syongari		return (error);
3085153982Syongari	if (nseg == 0) {
3086161236Syongari		m_freem(*m_head);
3087161236Syongari		*m_head = NULL;
3088153982Syongari		return (EIO);
3089153776Sscottl	}
3090153776Sscottl
3091153982Syongari	if (sc->ti_txcnt + nseg >= TI_TX_RING_CNT) {
3092227512Syongari		bus_dmamap_unload(sc->ti_cdata.ti_tx_tag, txd->tx_dmamap);
3093153982Syongari		return (ENOBUFS);
3094153982Syongari	}
3095227512Syongari	bus_dmamap_sync(sc->ti_cdata.ti_tx_tag, txd->tx_dmamap,
3096227512Syongari	    BUS_DMASYNC_PREWRITE);
3097153982Syongari
3098161236Syongari	m = *m_head;
3099161236Syongari	csum_flags = 0;
3100242425Syongari	if (m->m_pkthdr.csum_flags & CSUM_IP)
3101242425Syongari		csum_flags |= TI_BDFLAG_IP_CKSUM;
3102242425Syongari	if (m->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
3103242425Syongari		csum_flags |= TI_BDFLAG_TCP_UDP_CKSUM;
3104161236Syongari
3105153982Syongari	frag = sc->ti_tx_saved_prodidx;
3106153982Syongari	for (i = 0; i < nseg; i++) {
3107153396Sscottl		if (sc->ti_hwrev == TI_HWREV_TIGON) {
3108153770Syongari			bzero(&txdesc, sizeof(txdesc));
3109153770Syongari			f = &txdesc;
3110153396Sscottl		} else
3111227512Syongari			f = &sc->ti_rdata.ti_tx_ring[frag];
3112153982Syongari		ti_hostaddr64(&f->ti_addr, txsegs[i].ds_addr);
3113153982Syongari		f->ti_len = txsegs[i].ds_len;
3114153396Sscottl		f->ti_flags = csum_flags;
3115162375Sandre		if (m->m_flags & M_VLANTAG) {
3116153396Sscottl			f->ti_flags |= TI_BDFLAG_VLAN_TAG;
3117227094Syongari			f->ti_vlan_tag = m->m_pkthdr.ether_vtag;
3118153396Sscottl		} else {
3119153396Sscottl			f->ti_vlan_tag = 0;
3120153396Sscottl		}
3121153396Sscottl
3122153770Syongari		if (sc->ti_hwrev == TI_HWREV_TIGON)
3123153770Syongari			ti_mem_write(sc, TI_TX_RING_BASE + frag *
3124153770Syongari			    sizeof(txdesc), sizeof(txdesc), &txdesc);
3125153396Sscottl		TI_INC(frag, TI_TX_RING_CNT);
3126153396Sscottl	}
3127153396Sscottl
3128153982Syongari	sc->ti_tx_saved_prodidx = frag;
3129153982Syongari	/* set TI_BDFLAG_END on the last descriptor */
3130153982Syongari	frag = (frag + TI_TX_RING_CNT - 1) % TI_TX_RING_CNT;
3131153770Syongari	if (sc->ti_hwrev == TI_HWREV_TIGON) {
3132153770Syongari		txdesc.ti_flags |= TI_BDFLAG_END;
3133153982Syongari		ti_mem_write(sc, TI_TX_RING_BASE + frag * sizeof(txdesc),
3134153770Syongari		    sizeof(txdesc), &txdesc);
3135153770Syongari	} else
3136227512Syongari		sc->ti_rdata.ti_tx_ring[frag].ti_flags |= TI_BDFLAG_END;
3137153396Sscottl
3138153982Syongari	STAILQ_REMOVE_HEAD(&sc->ti_cdata.ti_txfreeq, tx_q);
3139153982Syongari	STAILQ_INSERT_TAIL(&sc->ti_cdata.ti_txbusyq, txd, tx_q);
3140153982Syongari	txd->tx_m = m;
3141153982Syongari	sc->ti_txcnt += nseg;
314245386Swpaul
3143131654Sbms	return (0);
314445386Swpaul}
314545386Swpaul
3146153770Syongaristatic void
3147227086Syongariti_start(struct ifnet *ifp)
3148153770Syongari{
3149227087Syongari	struct ti_softc *sc;
3150153770Syongari
3151153770Syongari	sc = ifp->if_softc;
3152153770Syongari	TI_LOCK(sc);
3153153770Syongari	ti_start_locked(ifp);
3154153770Syongari	TI_UNLOCK(sc);
3155153770Syongari}
3156153770Syongari
315745386Swpaul/*
315845386Swpaul * Main transmit routine. To avoid having to do mbuf copies, we put pointers
315945386Swpaul * to the mbuf data regions directly in the transmit descriptors.
316045386Swpaul */
3161102336Salfredstatic void
3162227086Syongariti_start_locked(struct ifnet *ifp)
316345386Swpaul{
3164227087Syongari	struct ti_softc *sc;
3165227087Syongari	struct mbuf *m_head = NULL;
3166227087Syongari	int enq = 0;
316745386Swpaul
316845386Swpaul	sc = ifp->if_softc;
316945386Swpaul
3170227099Syongari	for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
3171153982Syongari	    sc->ti_txcnt < (TI_TX_RING_CNT - 16);) {
3172227099Syongari		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
317345386Swpaul		if (m_head == NULL)
317445386Swpaul			break;
317545386Swpaul
317645386Swpaul		/*
317745386Swpaul		 * Pack the data into the transmit ring. If we
317845386Swpaul		 * don't have room, set the OACTIVE flag and wait
317945386Swpaul		 * for the NIC to drain the ring.
318045386Swpaul		 */
3181153982Syongari		if (ti_encap(sc, &m_head)) {
3182153982Syongari			if (m_head == NULL)
3183153982Syongari				break;
3184227099Syongari			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
3185148887Srwatson			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
318645386Swpaul			break;
318745386Swpaul		}
318845386Swpaul
3189153982Syongari		enq++;
319045386Swpaul		/*
319145386Swpaul		 * If there's a BPF listener, bounce a copy of this frame
319245386Swpaul		 * to him.
319345386Swpaul		 */
3194167190Scsjp		ETHER_BPF_MTAP(ifp, m_head);
319545386Swpaul	}
319645386Swpaul
3197153982Syongari	if (enq > 0) {
3198227512Syongari		if (sc->ti_rdata.ti_tx_ring != NULL)
3199227512Syongari			bus_dmamap_sync(sc->ti_cdata.ti_tx_ring_tag,
3200227512Syongari			    sc->ti_cdata.ti_tx_ring_map, BUS_DMASYNC_PREWRITE);
3201153982Syongari		/* Transmit */
3202153982Syongari		CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, sc->ti_tx_saved_prodidx);
320345386Swpaul
3204153982Syongari		/*
3205153982Syongari		 * Set a timeout in case the chip goes out to lunch.
3206153982Syongari		 */
3207199559Sjhb		sc->ti_timer = 5;
3208153982Syongari	}
320945386Swpaul}
321045386Swpaul
3211102336Salfredstatic void
3212227086Syongariti_init(void *xsc)
321345386Swpaul{
3214227087Syongari	struct ti_softc *sc;
3215153770Syongari
3216153770Syongari	sc = xsc;
3217153770Syongari	TI_LOCK(sc);
3218153770Syongari	ti_init_locked(sc);
3219153770Syongari	TI_UNLOCK(sc);
3220153770Syongari}
3221153770Syongari
3222153770Syongaristatic void
3223227086Syongariti_init_locked(void *xsc)
3224153770Syongari{
3225227087Syongari	struct ti_softc *sc = xsc;
322645386Swpaul
3227227312Syongari	if (sc->ti_ifp->if_drv_flags & IFF_DRV_RUNNING)
3228227312Syongari		return;
3229227312Syongari
323045386Swpaul	/* Cancel pending I/O and flush buffers. */
323145386Swpaul	ti_stop(sc);
323245386Swpaul
323345386Swpaul	/* Init the gen info block, ring control blocks and firmware. */
323445386Swpaul	if (ti_gibinit(sc)) {
3235162321Sglebius		device_printf(sc->ti_dev, "initialization failure\n");
323645386Swpaul		return;
323745386Swpaul	}
323845386Swpaul}
323945386Swpaul
3240227086Syongaristatic void ti_init2(struct ti_softc *sc)
324145386Swpaul{
3242227087Syongari	struct ti_cmd_desc cmd;
3243227087Syongari	struct ifnet *ifp;
3244227089Syongari	uint8_t *ea;
3245227087Syongari	struct ifmedia *ifm;
3246227087Syongari	int tmp;
324745386Swpaul
3248153770Syongari	TI_LOCK_ASSERT(sc);
3249153770Syongari
3250147256Sbrooks	ifp = sc->ti_ifp;
325145386Swpaul
325245386Swpaul	/* Specify MTU and interface index. */
3253227311Syongari	CSR_WRITE_4(sc, TI_GCR_IFINDEX, device_get_unit(sc->ti_dev));
325445386Swpaul	CSR_WRITE_4(sc, TI_GCR_IFMTU, ifp->if_mtu +
3255118454Ssimokawa	    ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN);
325645386Swpaul	TI_DO_CMD(TI_CMD_UPDATE_GENCOM, 0, 0);
325745386Swpaul
325845386Swpaul	/* Load our MAC address. */
3259153770Syongari	ea = IF_LLADDR(sc->ti_ifp);
3260153770Syongari	CSR_WRITE_4(sc, TI_GCR_PAR0, (ea[0] << 8) | ea[1]);
3261153770Syongari	CSR_WRITE_4(sc, TI_GCR_PAR1,
3262153770Syongari	    (ea[2] << 24) | (ea[3] << 16) | (ea[4] << 8) | ea[5]);
326345386Swpaul	TI_DO_CMD(TI_CMD_SET_MAC_ADDR, 0, 0);
326445386Swpaul
326545386Swpaul	/* Enable or disable promiscuous mode as needed. */
326645386Swpaul	if (ifp->if_flags & IFF_PROMISC) {
326745386Swpaul		TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_ENB, 0);
326845386Swpaul	} else {
326945386Swpaul		TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_DIS, 0);
327045386Swpaul	}
327145386Swpaul
327245386Swpaul	/* Program multicast filter. */
327345386Swpaul	ti_setmulti(sc);
327445386Swpaul
327545386Swpaul	/*
327645386Swpaul	 * If this is a Tigon 1, we should tell the
327745386Swpaul	 * firmware to use software packet filtering.
327845386Swpaul	 */
327945386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON) {
328045386Swpaul		TI_DO_CMD(TI_CMD_FDR_FILTERING, TI_CMD_CODE_FILT_ENB, 0);
328145386Swpaul	}
328245386Swpaul
328345386Swpaul	/* Init RX ring. */
3284227322Syongari	if (ti_init_rx_ring_std(sc) != 0) {
3285227322Syongari		/* XXX */
3286227322Syongari		device_printf(sc->ti_dev, "no memory for std Rx buffers.\n");
3287227322Syongari		return;
3288227322Syongari	}
328945386Swpaul
329045386Swpaul	/* Init jumbo RX ring. */
3291227512Syongari	if (ifp->if_mtu > ETHERMTU + ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN) {
3292227322Syongari		if (ti_init_rx_ring_jumbo(sc) != 0) {
3293227322Syongari			/* XXX */
3294227322Syongari			device_printf(sc->ti_dev,
3295227322Syongari			    "no memory for jumbo Rx buffers.\n");
3296227322Syongari			return;
3297227322Syongari		}
3298227322Syongari	}
329945386Swpaul
330045386Swpaul	/*
330145386Swpaul	 * If this is a Tigon 2, we can also configure the
330245386Swpaul	 * mini ring.
330345386Swpaul	 */
3304227322Syongari	if (sc->ti_hwrev == TI_HWREV_TIGON_II) {
3305227322Syongari		if (ti_init_rx_ring_mini(sc) != 0) {
3306227322Syongari			/* XXX */
3307227322Syongari			device_printf(sc->ti_dev,
3308227322Syongari			    "no memory for mini Rx buffers.\n");
3309227322Syongari			return;
3310227322Syongari		}
3311227322Syongari	}
331245386Swpaul
331345386Swpaul	CSR_WRITE_4(sc, TI_GCR_RXRETURNCONS_IDX, 0);
331445386Swpaul	sc->ti_rx_saved_considx = 0;
331545386Swpaul
331645386Swpaul	/* Init TX ring. */
331745386Swpaul	ti_init_tx_ring(sc);
331845386Swpaul
331945386Swpaul	/* Tell firmware we're alive. */
332045386Swpaul	TI_DO_CMD(TI_CMD_HOST_STATE, TI_CMD_CODE_STACK_UP, 0);
332145386Swpaul
332245386Swpaul	/* Enable host interrupts. */
332345386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
332445386Swpaul
3325148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3326148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
3327199559Sjhb	callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc);
332845386Swpaul
332945386Swpaul	/*
333045386Swpaul	 * Make sure to set media properly. We have to do this
333145386Swpaul	 * here since we have to issue commands in order to set
333245386Swpaul	 * the link negotiation and we can't issue commands until
333345386Swpaul	 * the firmware is running.
333445386Swpaul	 */
333545386Swpaul	ifm = &sc->ifmedia;
333645386Swpaul	tmp = ifm->ifm_media;
333745386Swpaul	ifm->ifm_media = ifm->ifm_cur->ifm_media;
3338227093Syongari	ti_ifmedia_upd_locked(sc);
333945386Swpaul	ifm->ifm_media = tmp;
334045386Swpaul}
334145386Swpaul
334245386Swpaul/*
334345386Swpaul * Set media options.
334445386Swpaul */
3345102336Salfredstatic int
3346227086Syongariti_ifmedia_upd(struct ifnet *ifp)
334745386Swpaul{
3348227087Syongari	struct ti_softc *sc;
3349227093Syongari	int error;
3350227093Syongari
3351227093Syongari	sc = ifp->if_softc;
3352227093Syongari	TI_LOCK(sc);
3353284724Sdim	error = ti_ifmedia_upd_locked(sc);
3354227093Syongari	TI_UNLOCK(sc);
3355227093Syongari
3356227093Syongari	return (error);
3357227093Syongari}
3358227093Syongari
3359227093Syongaristatic int
3360227093Syongariti_ifmedia_upd_locked(struct ti_softc *sc)
3361227093Syongari{
3362227087Syongari	struct ifmedia *ifm;
3363227087Syongari	struct ti_cmd_desc cmd;
3364227089Syongari	uint32_t flowctl;
336545386Swpaul
336645386Swpaul	ifm = &sc->ifmedia;
336745386Swpaul
336845386Swpaul	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
3369131654Sbms		return (EINVAL);
337045386Swpaul
337198849Sken	flowctl = 0;
337298849Sken
3373131654Sbms	switch (IFM_SUBTYPE(ifm->ifm_media)) {
337445386Swpaul	case IFM_AUTO:
337598849Sken		/*
337698849Sken		 * Transmit flow control doesn't work on the Tigon 1.
337798849Sken		 */
337898849Sken		flowctl = TI_GLNK_RX_FLOWCTL_Y;
337998849Sken
338098849Sken		/*
338198849Sken		 * Transmit flow control can also cause problems on the
338298849Sken		 * Tigon 2, apparantly with both the copper and fiber
338398849Sken		 * boards.  The symptom is that the interface will just
338498849Sken		 * hang.  This was reproduced with Alteon 180 switches.
338598849Sken		 */
338698849Sken#if 0
338798849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
3388131652Sbms			flowctl |= TI_GLNK_TX_FLOWCTL_Y;
338998849Sken#endif
339098849Sken
339145386Swpaul		CSR_WRITE_4(sc, TI_GCR_GLINK, TI_GLNK_PREF|TI_GLNK_1000MB|
339298849Sken		    TI_GLNK_FULL_DUPLEX| flowctl |
339345386Swpaul		    TI_GLNK_AUTONEGENB|TI_GLNK_ENB);
339498849Sken
339598849Sken		flowctl = TI_LNK_RX_FLOWCTL_Y;
339698849Sken#if 0
339798849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
339898849Sken			flowctl |= TI_LNK_TX_FLOWCTL_Y;
339998849Sken#endif
340098849Sken
340145386Swpaul		CSR_WRITE_4(sc, TI_GCR_LINK, TI_LNK_100MB|TI_LNK_10MB|
340298849Sken		    TI_LNK_FULL_DUPLEX|TI_LNK_HALF_DUPLEX| flowctl |
340345386Swpaul		    TI_LNK_AUTONEGENB|TI_LNK_ENB);
340445386Swpaul		TI_DO_CMD(TI_CMD_LINK_NEGOTIATION,
340545386Swpaul		    TI_CMD_CODE_NEGOTIATE_BOTH, 0);
340645386Swpaul		break;
340745386Swpaul	case IFM_1000_SX:
340895673Sphk	case IFM_1000_T:
340998849Sken		flowctl = TI_GLNK_RX_FLOWCTL_Y;
341098849Sken#if 0
341198849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
3412131652Sbms			flowctl |= TI_GLNK_TX_FLOWCTL_Y;
341398849Sken#endif
341498849Sken
341545386Swpaul		CSR_WRITE_4(sc, TI_GCR_GLINK, TI_GLNK_PREF|TI_GLNK_1000MB|
341698849Sken		    flowctl |TI_GLNK_ENB);
341745386Swpaul		CSR_WRITE_4(sc, TI_GCR_LINK, 0);
341863699Swpaul		if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
341963699Swpaul			TI_SETBIT(sc, TI_GCR_GLINK, TI_GLNK_FULL_DUPLEX);
342063699Swpaul		}
342145386Swpaul		TI_DO_CMD(TI_CMD_LINK_NEGOTIATION,
342245386Swpaul		    TI_CMD_CODE_NEGOTIATE_GIGABIT, 0);
342345386Swpaul		break;
342445386Swpaul	case IFM_100_FX:
342545386Swpaul	case IFM_10_FL:
342663699Swpaul	case IFM_100_TX:
342763699Swpaul	case IFM_10_T:
342898849Sken		flowctl = TI_LNK_RX_FLOWCTL_Y;
342998849Sken#if 0
343098849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
343198849Sken			flowctl |= TI_LNK_TX_FLOWCTL_Y;
343298849Sken#endif
343398849Sken
343445386Swpaul		CSR_WRITE_4(sc, TI_GCR_GLINK, 0);
343598849Sken		CSR_WRITE_4(sc, TI_GCR_LINK, TI_LNK_ENB|TI_LNK_PREF|flowctl);
343663699Swpaul		if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_FX ||
343763699Swpaul		    IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) {
343845386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_100MB);
343945386Swpaul		} else {
344045386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_10MB);
344145386Swpaul		}
344245386Swpaul		if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
344345386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_FULL_DUPLEX);
344445386Swpaul		} else {
344545386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_HALF_DUPLEX);
344645386Swpaul		}
344745386Swpaul		TI_DO_CMD(TI_CMD_LINK_NEGOTIATION,
344845386Swpaul		    TI_CMD_CODE_NEGOTIATE_10_100, 0);
344945386Swpaul		break;
345045386Swpaul	}
345145386Swpaul
3452131654Sbms	return (0);
345345386Swpaul}
345445386Swpaul
345545386Swpaul/*
345645386Swpaul * Report current media status.
345745386Swpaul */
3458102336Salfredstatic void
3459227086Syongariti_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
346045386Swpaul{
3461227087Syongari	struct ti_softc *sc;
3462227089Syongari	uint32_t media = 0;
346345386Swpaul
346445386Swpaul	sc = ifp->if_softc;
346545386Swpaul
3466227093Syongari	TI_LOCK(sc);
3467227093Syongari
346845386Swpaul	ifmr->ifm_status = IFM_AVALID;
346945386Swpaul	ifmr->ifm_active = IFM_ETHER;
347045386Swpaul
3471227093Syongari	if (sc->ti_linkstat == TI_EV_CODE_LINK_DOWN) {
3472227093Syongari		TI_UNLOCK(sc);
347345386Swpaul		return;
3474227093Syongari	}
347545386Swpaul
347645386Swpaul	ifmr->ifm_status |= IFM_ACTIVE;
347745386Swpaul
347863699Swpaul	if (sc->ti_linkstat == TI_EV_CODE_GIG_LINK_UP) {
347963699Swpaul		media = CSR_READ_4(sc, TI_GCR_GLINK_STAT);
348063699Swpaul		if (sc->ti_copper)
348195673Sphk			ifmr->ifm_active |= IFM_1000_T;
348263699Swpaul		else
348363699Swpaul			ifmr->ifm_active |= IFM_1000_SX;
348463699Swpaul		if (media & TI_GLNK_FULL_DUPLEX)
348563699Swpaul			ifmr->ifm_active |= IFM_FDX;
348663699Swpaul		else
348763699Swpaul			ifmr->ifm_active |= IFM_HDX;
348863699Swpaul	} else if (sc->ti_linkstat == TI_EV_CODE_LINK_UP) {
348945386Swpaul		media = CSR_READ_4(sc, TI_GCR_LINK_STAT);
349063699Swpaul		if (sc->ti_copper) {
349163699Swpaul			if (media & TI_LNK_100MB)
349263699Swpaul				ifmr->ifm_active |= IFM_100_TX;
349363699Swpaul			if (media & TI_LNK_10MB)
349463699Swpaul				ifmr->ifm_active |= IFM_10_T;
349563699Swpaul		} else {
349663699Swpaul			if (media & TI_LNK_100MB)
349763699Swpaul				ifmr->ifm_active |= IFM_100_FX;
349863699Swpaul			if (media & TI_LNK_10MB)
349963699Swpaul				ifmr->ifm_active |= IFM_10_FL;
350063699Swpaul		}
350145386Swpaul		if (media & TI_LNK_FULL_DUPLEX)
350245386Swpaul			ifmr->ifm_active |= IFM_FDX;
350345386Swpaul		if (media & TI_LNK_HALF_DUPLEX)
350445386Swpaul			ifmr->ifm_active |= IFM_HDX;
350545386Swpaul	}
3506227093Syongari	TI_UNLOCK(sc);
350745386Swpaul}
350845386Swpaul
3509102336Salfredstatic int
3510227086Syongariti_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
351145386Swpaul{
3512227087Syongari	struct ti_softc *sc = ifp->if_softc;
3513227087Syongari	struct ifreq *ifr = (struct ifreq *) data;
3514227087Syongari	struct ti_cmd_desc cmd;
3515227087Syongari	int mask, error = 0;
351645386Swpaul
3517131654Sbms	switch (command) {
351845386Swpaul	case SIOCSIFMTU:
3519153770Syongari		TI_LOCK(sc);
3520227324Syongari		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > TI_JUMBO_MTU)
352145386Swpaul			error = EINVAL;
352245386Swpaul		else {
352345386Swpaul			ifp->if_mtu = ifr->ifr_mtu;
3524227312Syongari			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3525227312Syongari				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
3526227312Syongari				ti_init_locked(sc);
3527227312Syongari			}
352845386Swpaul		}
3529153770Syongari		TI_UNLOCK(sc);
353045386Swpaul		break;
353145386Swpaul	case SIOCSIFFLAGS:
3532153770Syongari		TI_LOCK(sc);
353345386Swpaul		if (ifp->if_flags & IFF_UP) {
353445386Swpaul			/*
353545386Swpaul			 * If only the state of the PROMISC flag changed,
353645386Swpaul			 * then just use the 'set promisc mode' command
353745386Swpaul			 * instead of reinitializing the entire NIC. Doing
353845386Swpaul			 * a full re-init means reloading the firmware and
353945386Swpaul			 * waiting for it to start up, which may take a
354045386Swpaul			 * second or two.
354145386Swpaul			 */
3542148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
354345386Swpaul			    ifp->if_flags & IFF_PROMISC &&
354445386Swpaul			    !(sc->ti_if_flags & IFF_PROMISC)) {
354545386Swpaul				TI_DO_CMD(TI_CMD_SET_PROMISC_MODE,
354645386Swpaul				    TI_CMD_CODE_PROMISC_ENB, 0);
3547148887Srwatson			} else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
354845386Swpaul			    !(ifp->if_flags & IFF_PROMISC) &&
354945386Swpaul			    sc->ti_if_flags & IFF_PROMISC) {
355045386Swpaul				TI_DO_CMD(TI_CMD_SET_PROMISC_MODE,
355145386Swpaul				    TI_CMD_CODE_PROMISC_DIS, 0);
355245386Swpaul			} else
3553153770Syongari				ti_init_locked(sc);
355445386Swpaul		} else {
3555148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
355645386Swpaul				ti_stop(sc);
355745386Swpaul			}
355845386Swpaul		}
355945386Swpaul		sc->ti_if_flags = ifp->if_flags;
3560153770Syongari		TI_UNLOCK(sc);
356145386Swpaul		break;
356245386Swpaul	case SIOCADDMULTI:
356345386Swpaul	case SIOCDELMULTI:
3564153770Syongari		TI_LOCK(sc);
3565153770Syongari		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
356645386Swpaul			ti_setmulti(sc);
3567153770Syongari		TI_UNLOCK(sc);
356845386Swpaul		break;
356945386Swpaul	case SIOCSIFMEDIA:
357045386Swpaul	case SIOCGIFMEDIA:
357145386Swpaul		error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
357245386Swpaul		break;
357383630Sjlemon	case SIOCSIFCAP:
3574153770Syongari		TI_LOCK(sc);
357583630Sjlemon		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
3576227095Syongari		if ((mask & IFCAP_TXCSUM) != 0 &&
3577227095Syongari		    (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
3578227095Syongari			ifp->if_capenable ^= IFCAP_TXCSUM;
3579227095Syongari			if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
3580227095Syongari				ifp->if_hwassist |= TI_CSUM_FEATURES;
3581227095Syongari                        else
3582227095Syongari				ifp->if_hwassist &= ~TI_CSUM_FEATURES;
3583227095Syongari                }
3584227095Syongari		if ((mask & IFCAP_RXCSUM) != 0 &&
3585227095Syongari		    (ifp->if_capabilities & IFCAP_RXCSUM) != 0)
3586227095Syongari			ifp->if_capenable ^= IFCAP_RXCSUM;
3587227095Syongari		if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
3588227095Syongari		    (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0)
3589227095Syongari                        ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
3590227095Syongari		if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
3591227095Syongari		    (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0)
3592227095Syongari			ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
3593227095Syongari		if ((mask & (IFCAP_TXCSUM | IFCAP_RXCSUM |
3594227095Syongari		    IFCAP_VLAN_HWTAGGING)) != 0) {
3595227095Syongari			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3596227095Syongari				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
3597153770Syongari				ti_init_locked(sc);
3598227095Syongari			}
3599131655Sbms		}
3600153770Syongari		TI_UNLOCK(sc);
3601227095Syongari		VLAN_CAPABILITIES(ifp);
360283630Sjlemon		break;
360345386Swpaul	default:
3604106936Ssam		error = ether_ioctl(ifp, command, data);
360545386Swpaul		break;
360645386Swpaul	}
360745386Swpaul
3608131654Sbms	return (error);
360945386Swpaul}
361045386Swpaul
361198849Skenstatic int
3612130585Sphkti_open(struct cdev *dev, int flags, int fmt, struct thread *td)
361398849Sken{
361498849Sken	struct ti_softc *sc;
361598849Sken
3616120980Sphk	sc = dev->si_drv1;
361798849Sken	if (sc == NULL)
3618131654Sbms		return (ENODEV);
361998849Sken
362098849Sken	TI_LOCK(sc);
362198849Sken	sc->ti_flags |= TI_FLAG_DEBUGING;
362298849Sken	TI_UNLOCK(sc);
362398849Sken
3624131654Sbms	return (0);
362598849Sken}
362698849Sken
362798849Skenstatic int
3628130585Sphkti_close(struct cdev *dev, int flag, int fmt, struct thread *td)
362998849Sken{
363098849Sken	struct ti_softc *sc;
363198849Sken
3632120980Sphk	sc = dev->si_drv1;
363398849Sken	if (sc == NULL)
3634131654Sbms		return (ENODEV);
363598849Sken
363698849Sken	TI_LOCK(sc);
363798849Sken	sc->ti_flags &= ~TI_FLAG_DEBUGING;
363898849Sken	TI_UNLOCK(sc);
363998849Sken
3640131654Sbms	return (0);
364198849Sken}
364298849Sken
364398849Sken/*
364498849Sken * This ioctl routine goes along with the Tigon character device.
364598849Sken */
3646131652Sbmsstatic int
3647150719Sjhbti_ioctl2(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
3648150719Sjhb    struct thread *td)
364998849Sken{
3650227087Syongari	struct ti_softc *sc;
3651120980Sphk	int error;
365298849Sken
3653120980Sphk	sc = dev->si_drv1;
365498849Sken	if (sc == NULL)
3655131654Sbms		return (ENODEV);
365698849Sken
365798849Sken	error = 0;
365898849Sken
3659131654Sbms	switch (cmd) {
366098849Sken	case TIIOCGETSTATS:
366198849Sken	{
366298849Sken		struct ti_stats *outstats;
366398849Sken
366498849Sken		outstats = (struct ti_stats *)addr;
366598849Sken
3666153281Sscottl		TI_LOCK(sc);
3667227512Syongari		bus_dmamap_sync(sc->ti_cdata.ti_gib_tag,
3668227512Syongari		    sc->ti_cdata.ti_gib_map, BUS_DMASYNC_POSTREAD);
3669227512Syongari		bcopy(&sc->ti_rdata.ti_info->ti_stats, outstats,
3670227431Syongari		    sizeof(struct ti_stats));
3671272169Sglebius		bus_dmamap_sync(sc->ti_cdata.ti_gib_tag,
3672272169Sglebius		    sc->ti_cdata.ti_gib_map, BUS_DMASYNC_PREREAD);
3673153281Sscottl		TI_UNLOCK(sc);
367498849Sken		break;
367598849Sken	}
367698849Sken	case TIIOCGETPARAMS:
367798849Sken	{
3678227087Syongari		struct ti_params *params;
367998849Sken
368098849Sken		params = (struct ti_params *)addr;
368198849Sken
3682153281Sscottl		TI_LOCK(sc);
368398849Sken		params->ti_stat_ticks = sc->ti_stat_ticks;
368498849Sken		params->ti_rx_coal_ticks = sc->ti_rx_coal_ticks;
368598849Sken		params->ti_tx_coal_ticks = sc->ti_tx_coal_ticks;
368698849Sken		params->ti_rx_max_coal_bds = sc->ti_rx_max_coal_bds;
368798849Sken		params->ti_tx_max_coal_bds = sc->ti_tx_max_coal_bds;
368898849Sken		params->ti_tx_buf_ratio = sc->ti_tx_buf_ratio;
368998849Sken		params->param_mask = TI_PARAM_ALL;
3690153281Sscottl		TI_UNLOCK(sc);
369198849Sken		break;
369298849Sken	}
369398849Sken	case TIIOCSETPARAMS:
369498849Sken	{
369598849Sken		struct ti_params *params;
369698849Sken
369798849Sken		params = (struct ti_params *)addr;
369898849Sken
3699153281Sscottl		TI_LOCK(sc);
370098849Sken		if (params->param_mask & TI_PARAM_STAT_TICKS) {
370198849Sken			sc->ti_stat_ticks = params->ti_stat_ticks;
370298849Sken			CSR_WRITE_4(sc, TI_GCR_STAT_TICKS, sc->ti_stat_ticks);
370398849Sken		}
370498849Sken
370598849Sken		if (params->param_mask & TI_PARAM_RX_COAL_TICKS) {
370698849Sken			sc->ti_rx_coal_ticks = params->ti_rx_coal_ticks;
370798849Sken			CSR_WRITE_4(sc, TI_GCR_RX_COAL_TICKS,
370898849Sken				    sc->ti_rx_coal_ticks);
370998849Sken		}
371098849Sken
371198849Sken		if (params->param_mask & TI_PARAM_TX_COAL_TICKS) {
371298849Sken			sc->ti_tx_coal_ticks = params->ti_tx_coal_ticks;
371398849Sken			CSR_WRITE_4(sc, TI_GCR_TX_COAL_TICKS,
371498849Sken				    sc->ti_tx_coal_ticks);
371598849Sken		}
371698849Sken
371798849Sken		if (params->param_mask & TI_PARAM_RX_COAL_BDS) {
371898849Sken			sc->ti_rx_max_coal_bds = params->ti_rx_max_coal_bds;
371998849Sken			CSR_WRITE_4(sc, TI_GCR_RX_MAX_COAL_BD,
372098849Sken				    sc->ti_rx_max_coal_bds);
372198849Sken		}
372298849Sken
372398849Sken		if (params->param_mask & TI_PARAM_TX_COAL_BDS) {
372498849Sken			sc->ti_tx_max_coal_bds = params->ti_tx_max_coal_bds;
372598849Sken			CSR_WRITE_4(sc, TI_GCR_TX_MAX_COAL_BD,
372698849Sken				    sc->ti_tx_max_coal_bds);
372798849Sken		}
372898849Sken
372998849Sken		if (params->param_mask & TI_PARAM_TX_BUF_RATIO) {
373098849Sken			sc->ti_tx_buf_ratio = params->ti_tx_buf_ratio;
373198849Sken			CSR_WRITE_4(sc, TI_GCR_TX_BUFFER_RATIO,
373298849Sken				    sc->ti_tx_buf_ratio);
373398849Sken		}
3734153281Sscottl		TI_UNLOCK(sc);
373598849Sken		break;
373698849Sken	}
373798849Sken	case TIIOCSETTRACE: {
3738227431Syongari		ti_trace_type trace_type;
373998849Sken
374098849Sken		trace_type = *(ti_trace_type *)addr;
374198849Sken
374298849Sken		/*
374398849Sken		 * Set tracing to whatever the user asked for.  Setting
374498849Sken		 * this register to 0 should have the effect of disabling
374598849Sken		 * tracing.
374698849Sken		 */
3747227505Syongari		TI_LOCK(sc);
374898849Sken		CSR_WRITE_4(sc, TI_GCR_NIC_TRACING, trace_type);
3749227505Syongari		TI_UNLOCK(sc);
375098849Sken		break;
375198849Sken	}
375298849Sken	case TIIOCGETTRACE: {
3753227087Syongari		struct ti_trace_buf *trace_buf;
3754227089Syongari		uint32_t trace_start, cur_trace_ptr, trace_len;
375598849Sken
375698849Sken		trace_buf = (struct ti_trace_buf *)addr;
375798849Sken
3758153281Sscottl		TI_LOCK(sc);
375998849Sken		trace_start = CSR_READ_4(sc, TI_GCR_NICTRACE_START);
376098849Sken		cur_trace_ptr = CSR_READ_4(sc, TI_GCR_NICTRACE_PTR);
376198849Sken		trace_len = CSR_READ_4(sc, TI_GCR_NICTRACE_LEN);
376298849Sken#if 0
3763150719Sjhb		if_printf(sc->ti_ifp, "trace_start = %#x, cur_trace_ptr = %#x, "
3764150719Sjhb		       "trace_len = %d\n", trace_start,
376598849Sken		       cur_trace_ptr, trace_len);
3766150719Sjhb		if_printf(sc->ti_ifp, "trace_buf->buf_len = %d\n",
376798849Sken		       trace_buf->buf_len);
376898849Sken#endif
376998849Sken		error = ti_copy_mem(sc, trace_start, min(trace_len,
3770227431Syongari		    trace_buf->buf_len), (caddr_t)trace_buf->buf, 1, 1);
377198849Sken		if (error == 0) {
377298849Sken			trace_buf->fill_len = min(trace_len,
3773227431Syongari			    trace_buf->buf_len);
377498849Sken			if (cur_trace_ptr < trace_start)
377598849Sken				trace_buf->cur_trace_ptr =
3776227431Syongari				    trace_start - cur_trace_ptr;
377798849Sken			else
377898849Sken				trace_buf->cur_trace_ptr =
3779227431Syongari				    cur_trace_ptr - trace_start;
378098849Sken		} else
378198849Sken			trace_buf->fill_len = 0;
3782153281Sscottl		TI_UNLOCK(sc);
378398849Sken		break;
378498849Sken	}
378598849Sken
378698849Sken	/*
378798849Sken	 * For debugging, five ioctls are needed:
378898849Sken	 * ALT_ATTACH
378998849Sken	 * ALT_READ_TG_REG
379098849Sken	 * ALT_WRITE_TG_REG
379198849Sken	 * ALT_READ_TG_MEM
379298849Sken	 * ALT_WRITE_TG_MEM
379398849Sken	 */
379498849Sken	case ALT_ATTACH:
379598849Sken		/*
3796131652Sbms		 * From what I can tell, Alteon's Solaris Tigon driver
379798849Sken		 * only has one character device, so you have to attach
379898849Sken		 * to the Tigon board you're interested in.  This seems
379998849Sken		 * like a not-so-good way to do things, since unless you
380098849Sken		 * subsequently specify the unit number of the device
3801177626Sbrueffer		 * you're interested in every ioctl, you'll only be
380298849Sken		 * able to debug one board at a time.
380398849Sken		 */
380498849Sken		break;
380598849Sken	case ALT_READ_TG_MEM:
380698849Sken	case ALT_WRITE_TG_MEM:
380798849Sken	{
380898849Sken		struct tg_mem *mem_param;
3809227089Syongari		uint32_t sram_end, scratch_end;
381098849Sken
381198849Sken		mem_param = (struct tg_mem *)addr;
381298849Sken
381398849Sken		if (sc->ti_hwrev == TI_HWREV_TIGON) {
381498849Sken			sram_end = TI_END_SRAM_I;
381598849Sken			scratch_end = TI_END_SCRATCH_I;
381698849Sken		} else {
381798849Sken			sram_end = TI_END_SRAM_II;
381898849Sken			scratch_end = TI_END_SCRATCH_II;
381998849Sken		}
382098849Sken
382198849Sken		/*
382298849Sken		 * For now, we'll only handle accessing regular SRAM,
382398849Sken		 * nothing else.
382498849Sken		 */
3825153281Sscottl		TI_LOCK(sc);
3826227431Syongari		if (mem_param->tgAddr >= TI_BEG_SRAM &&
3827227431Syongari		    mem_param->tgAddr + mem_param->len <= sram_end) {
382898849Sken			/*
382998849Sken			 * In this instance, we always copy to/from user
383098849Sken			 * space, so the user space argument is set to 1.
383198849Sken			 */
383298849Sken			error = ti_copy_mem(sc, mem_param->tgAddr,
3833227431Syongari			    mem_param->len, mem_param->userAddr, 1,
3834227431Syongari			    cmd == ALT_READ_TG_MEM ? 1 : 0);
3835227431Syongari		} else if (mem_param->tgAddr >= TI_BEG_SCRATCH &&
3836227431Syongari		    mem_param->tgAddr <= scratch_end) {
383798849Sken			error = ti_copy_scratch(sc, mem_param->tgAddr,
3838227431Syongari			    mem_param->len, mem_param->userAddr, 1,
3839227431Syongari			    cmd == ALT_READ_TG_MEM ?  1 : 0, TI_PROCESSOR_A);
3840227431Syongari		} else if (mem_param->tgAddr >= TI_BEG_SCRATCH_B_DEBUG &&
3841227431Syongari		    mem_param->tgAddr <= TI_BEG_SCRATCH_B_DEBUG) {
384298849Sken			if (sc->ti_hwrev == TI_HWREV_TIGON) {
3843150719Sjhb				if_printf(sc->ti_ifp,
3844150719Sjhb				    "invalid memory range for Tigon I\n");
384598849Sken				error = EINVAL;
384698849Sken				break;
384798849Sken			}
3848131652Sbms			error = ti_copy_scratch(sc, mem_param->tgAddr -
3849227431Syongari			    TI_SCRATCH_DEBUG_OFF, mem_param->len,
3850227431Syongari			    mem_param->userAddr, 1,
3851227431Syongari			    cmd == ALT_READ_TG_MEM ? 1 : 0, TI_PROCESSOR_B);
385298849Sken		} else {
3853150719Sjhb			if_printf(sc->ti_ifp, "memory address %#x len %d is "
3854150719Sjhb			        "out of supported range\n",
385598849Sken			        mem_param->tgAddr, mem_param->len);
385698849Sken			error = EINVAL;
385798849Sken		}
3858153281Sscottl		TI_UNLOCK(sc);
385998849Sken		break;
386098849Sken	}
386198849Sken	case ALT_READ_TG_REG:
386298849Sken	case ALT_WRITE_TG_REG:
386398849Sken	{
3864227431Syongari		struct tg_reg *regs;
3865227431Syongari		uint32_t tmpval;
386698849Sken
386798849Sken		regs = (struct tg_reg *)addr;
386898849Sken
386998849Sken		/*
387098849Sken		 * Make sure the address in question isn't out of range.
387198849Sken		 */
387298849Sken		if (regs->addr > TI_REG_MAX) {
387398849Sken			error = EINVAL;
387498849Sken			break;
387598849Sken		}
3876153281Sscottl		TI_LOCK(sc);
387798849Sken		if (cmd == ALT_READ_TG_REG) {
387898849Sken			bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
3879227431Syongari			    regs->addr, &tmpval, 1);
388098849Sken			regs->data = ntohl(tmpval);
388198849Sken#if 0
388298849Sken			if ((regs->addr == TI_CPU_STATE)
388398849Sken			 || (regs->addr == TI_CPU_CTL_B)) {
3884150719Sjhb				if_printf(sc->ti_ifp, "register %#x = %#x\n",
3885150719Sjhb				       regs->addr, tmpval);
388698849Sken			}
388798849Sken#endif
388898849Sken		} else {
388998849Sken			tmpval = htonl(regs->data);
389098849Sken			bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
3891227431Syongari			    regs->addr, &tmpval, 1);
389298849Sken		}
3893153281Sscottl		TI_UNLOCK(sc);
389498849Sken		break;
389598849Sken	}
389698849Sken	default:
389798849Sken		error = ENOTTY;
389898849Sken		break;
389998849Sken	}
3900131654Sbms	return (error);
390198849Sken}
390298849Sken
3903102336Salfredstatic void
3904199559Sjhbti_watchdog(void *arg)
390545386Swpaul{
3906227087Syongari	struct ti_softc *sc;
3907227087Syongari	struct ifnet *ifp;
390845386Swpaul
3909199559Sjhb	sc = arg;
3910199559Sjhb	TI_LOCK_ASSERT(sc);
3911199559Sjhb	callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc);
3912199559Sjhb	if (sc->ti_timer == 0 || --sc->ti_timer > 0)
3913199559Sjhb		return;
391445386Swpaul
391598849Sken	/*
391698849Sken	 * When we're debugging, the chip is often stopped for long periods
391798849Sken	 * of time, and that would normally cause the watchdog timer to fire.
391898849Sken	 * Since that impedes debugging, we don't want to do that.
391998849Sken	 */
3920199559Sjhb	if (sc->ti_flags & TI_FLAG_DEBUGING)
392198849Sken		return;
392298849Sken
3923199559Sjhb	ifp = sc->ti_ifp;
3924150719Sjhb	if_printf(ifp, "watchdog timeout -- resetting\n");
3925227312Syongari	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
3926153770Syongari	ti_init_locked(sc);
392745386Swpaul
3928272169Sglebius	if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
392945386Swpaul}
393045386Swpaul
393145386Swpaul/*
393245386Swpaul * Stop the adapter and free any mbufs allocated to the
393345386Swpaul * RX and TX lists.
393445386Swpaul */
3935102336Salfredstatic void
3936227086Syongariti_stop(struct ti_softc *sc)
393745386Swpaul{
3938227087Syongari	struct ifnet *ifp;
3939227087Syongari	struct ti_cmd_desc cmd;
394045386Swpaul
3941153770Syongari	TI_LOCK_ASSERT(sc);
394267087Swpaul
3943147256Sbrooks	ifp = sc->ti_ifp;
394445386Swpaul
394545386Swpaul	/* Disable host interrupts. */
394645386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
394745386Swpaul	/*
394845386Swpaul	 * Tell firmware we're shutting down.
394945386Swpaul	 */
395045386Swpaul	TI_DO_CMD(TI_CMD_HOST_STATE, TI_CMD_CODE_STACK_DOWN, 0);
395145386Swpaul
395245386Swpaul	/* Halt and reinitialize. */
3953227323Syongari	if (ti_chipinit(sc) == 0) {
3954227323Syongari		ti_mem_zero(sc, 0x2000, 0x100000 - 0x2000);
3955227323Syongari		/* XXX ignore init errors. */
3956227323Syongari		ti_chipinit(sc);
3957227323Syongari	}
395845386Swpaul
395945386Swpaul	/* Free the RX lists. */
396045386Swpaul	ti_free_rx_ring_std(sc);
396145386Swpaul
396245386Swpaul	/* Free jumbo RX list. */
396345386Swpaul	ti_free_rx_ring_jumbo(sc);
396445386Swpaul
396545386Swpaul	/* Free mini RX list. */
396645386Swpaul	ti_free_rx_ring_mini(sc);
396745386Swpaul
396845386Swpaul	/* Free TX buffers. */
396945386Swpaul	ti_free_tx_ring(sc);
397045386Swpaul
397145386Swpaul	sc->ti_ev_prodidx.ti_idx = 0;
397245386Swpaul	sc->ti_return_prodidx.ti_idx = 0;
397345386Swpaul	sc->ti_tx_considx.ti_idx = 0;
397445386Swpaul	sc->ti_tx_saved_considx = TI_TXCONS_UNSET;
397545386Swpaul
3976148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3977199559Sjhb	callout_stop(&sc->ti_watchdog);
397845386Swpaul}
397945386Swpaul
398045386Swpaul/*
398145386Swpaul * Stop all chip I/O so that the kernel's probe routines don't
398245386Swpaul * get confused by errant DMAs when rebooting.
398345386Swpaul */
3984173839Syongaristatic int
3985227086Syongariti_shutdown(device_t dev)
398645386Swpaul{
3987227087Syongari	struct ti_softc *sc;
398845386Swpaul
398949011Swpaul	sc = device_get_softc(dev);
399067087Swpaul	TI_LOCK(sc);
399145386Swpaul	ti_chipinit(sc);
399267087Swpaul	TI_UNLOCK(sc);
3993173839Syongari
3994173839Syongari	return (0);
399545386Swpaul}
3996227509Syongari
3997227509Syongaristatic void
3998227509Syongariti_sysctl_node(struct ti_softc *sc)
3999227509Syongari{
4000227509Syongari	struct sysctl_ctx_list *ctx;
4001227509Syongari	struct sysctl_oid_list *child;
4002227512Syongari	char tname[32];
4003227509Syongari
4004227509Syongari	ctx = device_get_sysctl_ctx(sc->ti_dev);
4005227509Syongari	child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->ti_dev));
4006227509Syongari
4007227512Syongari	/* Use DAC */
4008227512Syongari	sc->ti_dac = 1;
4009227512Syongari	snprintf(tname, sizeof(tname), "dev.ti.%d.dac",
4010227512Syongari	    device_get_unit(sc->ti_dev));
4011227512Syongari	TUNABLE_INT_FETCH(tname, &sc->ti_dac);
4012227512Syongari
4013227509Syongari	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_coal_ticks", CTLFLAG_RW,
4014227509Syongari	    &sc->ti_rx_coal_ticks, 0, "Receive coalcesced ticks");
4015227509Syongari	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_max_coal_bds", CTLFLAG_RW,
4016227509Syongari	    &sc->ti_rx_max_coal_bds, 0, "Receive max coalcesced BDs");
4017227509Syongari
4018227509Syongari	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_coal_ticks", CTLFLAG_RW,
4019227509Syongari	    &sc->ti_tx_coal_ticks, 0, "Send coalcesced ticks");
4020227509Syongari	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_max_coal_bds", CTLFLAG_RW,
4021227509Syongari	    &sc->ti_tx_max_coal_bds, 0, "Send max coalcesced BDs");
4022227509Syongari	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_buf_ratio", CTLFLAG_RW,
4023227509Syongari	    &sc->ti_tx_buf_ratio, 0,
4024227509Syongari	    "Ratio of NIC memory devoted to TX buffer");
4025227509Syongari
4026227509Syongari	SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "stat_ticks", CTLFLAG_RW,
4027227509Syongari	    &sc->ti_stat_ticks, 0,
4028227509Syongari	    "Number of clock ticks for statistics update interval");
4029227509Syongari
4030227509Syongari	/* Pull in device tunables. */
4031227509Syongari	sc->ti_rx_coal_ticks = 170;
4032227509Syongari	resource_int_value(device_get_name(sc->ti_dev),
4033227509Syongari	    device_get_unit(sc->ti_dev), "rx_coal_ticks",
4034227509Syongari	    &sc->ti_rx_coal_ticks);
4035227509Syongari	sc->ti_rx_max_coal_bds = 64;
4036227509Syongari	resource_int_value(device_get_name(sc->ti_dev),
4037227509Syongari	    device_get_unit(sc->ti_dev), "rx_max_coal_bds",
4038227509Syongari	    &sc->ti_rx_max_coal_bds);
4039227509Syongari
4040227509Syongari	sc->ti_tx_coal_ticks = TI_TICKS_PER_SEC / 500;
4041227509Syongari	resource_int_value(device_get_name(sc->ti_dev),
4042227509Syongari	    device_get_unit(sc->ti_dev), "tx_coal_ticks",
4043227509Syongari	    &sc->ti_tx_coal_ticks);
4044227509Syongari	sc->ti_tx_max_coal_bds = 32;
4045227509Syongari	resource_int_value(device_get_name(sc->ti_dev),
4046227509Syongari	    device_get_unit(sc->ti_dev), "tx_max_coal_bds",
4047227509Syongari	    &sc->ti_tx_max_coal_bds);
4048227509Syongari	sc->ti_tx_buf_ratio = 21;
4049227509Syongari	resource_int_value(device_get_name(sc->ti_dev),
4050227509Syongari	    device_get_unit(sc->ti_dev), "tx_buf_ratio",
4051227509Syongari	    &sc->ti_tx_buf_ratio);
4052227509Syongari
4053227509Syongari	sc->ti_stat_ticks = 2 * TI_TICKS_PER_SEC;
4054227509Syongari	resource_int_value(device_get_name(sc->ti_dev),
4055227509Syongari	    device_get_unit(sc->ti_dev), "stat_ticks",
4056227509Syongari	    &sc->ti_stat_ticks);
4057227509Syongari}
4058