if_ti.c revision 227505
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 227505 2011-11-14 18:40:04Z yongari $");
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>
9745386Swpaul#include <net/if_arp.h>
9845386Swpaul#include <net/ethernet.h>
9945386Swpaul#include <net/if_dl.h>
10045386Swpaul#include <net/if_media.h>
10183115Sbrooks#include <net/if_types.h>
10283115Sbrooks#include <net/if_vlan_var.h>
10345386Swpaul
10445386Swpaul#include <net/bpf.h>
10545386Swpaul
10645386Swpaul#include <netinet/in_systm.h>
10745386Swpaul#include <netinet/in.h>
10845386Swpaul#include <netinet/ip.h>
10945386Swpaul
11045386Swpaul#include <machine/bus.h>
11149011Swpaul#include <machine/resource.h>
11249011Swpaul#include <sys/bus.h>
11349011Swpaul#include <sys/rman.h>
11445386Swpaul
115227347Syongari#ifdef TI_SF_BUF_JUMBO
116153770Syongari#include <vm/vm.h>
11798849Sken#include <vm/vm_page.h>
118153770Syongari#endif
11998849Sken
120119288Simp#include <dev/pci/pcireg.h>
121119288Simp#include <dev/pci/pcivar.h>
12245386Swpaul
12398849Sken#include <sys/tiio.h>
124153280Sscottl#include <dev/ti/if_tireg.h>
125153280Sscottl#include <dev/ti/ti_fw.h>
126153280Sscottl#include <dev/ti/ti_fw2.h>
12745386Swpaul
12858698Sjlemon#define TI_CSUM_FEATURES	(CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_IP_FRAGS)
12998849Sken/*
13098849Sken * We can only turn on header splitting if we're using extended receive
13198849Sken * BDs.
13298849Sken */
133227347Syongari#if defined(TI_JUMBO_HDRSPLIT) && !defined(TI_SF_BUF_JUMBO)
134227347Syongari#error "options TI_JUMBO_HDRSPLIT requires TI_SF_BUF_JUMBO"
135227347Syongari#endif /* TI_JUMBO_HDRSPLIT && !TI_SF_BUF_JUMBO */
13645386Swpaul
13798849Skentypedef enum {
13898849Sken	TI_SWAP_HTON,
13998849Sken	TI_SWAP_NTOH
14098849Sken} ti_swap_type;
14198849Sken
14245386Swpaul/*
14345386Swpaul * Various supported device vendors/types and their names.
14445386Swpaul */
14545386Swpaul
146219547Smariusstatic const struct ti_type const ti_devs[] = {
14745386Swpaul	{ ALT_VENDORID,	ALT_DEVICEID_ACENIC,
14863702Swpaul		"Alteon AceNIC 1000baseSX Gigabit Ethernet" },
14963699Swpaul	{ ALT_VENDORID,	ALT_DEVICEID_ACENIC_COPPER,
15063702Swpaul		"Alteon AceNIC 1000baseT Gigabit Ethernet" },
15145386Swpaul	{ TC_VENDORID,	TC_DEVICEID_3C985,
15245386Swpaul		"3Com 3c985-SX Gigabit Ethernet" },
15345386Swpaul	{ NG_VENDORID, NG_DEVICEID_GA620,
15464139Swpaul		"Netgear GA620 1000baseSX Gigabit Ethernet" },
15564139Swpaul	{ NG_VENDORID, NG_DEVICEID_GA620T,
15664139Swpaul		"Netgear GA620 1000baseT Gigabit Ethernet" },
15745386Swpaul	{ SGI_VENDORID, SGI_DEVICEID_TIGON,
15845386Swpaul		"Silicon Graphics Gigabit Ethernet" },
15956206Swpaul	{ DEC_VENDORID, DEC_DEVICEID_FARALLON_PN9000SX,
16056206Swpaul		"Farallon PN9000SX Gigabit Ethernet" },
16145386Swpaul	{ 0, 0, NULL }
16245386Swpaul};
16345386Swpaul
16498849Sken
16598849Skenstatic	d_open_t	ti_open;
16698849Skenstatic	d_close_t	ti_close;
16798849Skenstatic	d_ioctl_t	ti_ioctl2;
16898849Sken
16998849Skenstatic struct cdevsw ti_cdevsw = {
170126080Sphk	.d_version =	D_VERSION,
171153281Sscottl	.d_flags =	0,
172111815Sphk	.d_open =	ti_open,
173111815Sphk	.d_close =	ti_close,
174111815Sphk	.d_ioctl =	ti_ioctl2,
175111815Sphk	.d_name =	"ti",
17698849Sken};
17798849Sken
178142407Simpstatic int ti_probe(device_t);
179142407Simpstatic int ti_attach(device_t);
180142407Simpstatic int ti_detach(device_t);
181142407Simpstatic void ti_txeof(struct ti_softc *);
182142407Simpstatic void ti_rxeof(struct ti_softc *);
18345386Swpaul
184142407Simpstatic void ti_stats_update(struct ti_softc *);
185153982Syongaristatic int ti_encap(struct ti_softc *, struct mbuf **);
18645386Swpaul
187142407Simpstatic void ti_intr(void *);
188142407Simpstatic void ti_start(struct ifnet *);
189153770Syongaristatic void ti_start_locked(struct ifnet *);
190142407Simpstatic int ti_ioctl(struct ifnet *, u_long, caddr_t);
191142407Simpstatic void ti_init(void *);
192153770Syongaristatic void ti_init_locked(void *);
193142407Simpstatic void ti_init2(struct ti_softc *);
194142407Simpstatic void ti_stop(struct ti_softc *);
195199559Sjhbstatic void ti_watchdog(void *);
196173839Syongaristatic int ti_shutdown(device_t);
197142407Simpstatic int ti_ifmedia_upd(struct ifnet *);
198227093Syongaristatic int ti_ifmedia_upd_locked(struct ti_softc *);
199142407Simpstatic void ti_ifmedia_sts(struct ifnet *, struct ifmediareq *);
20045386Swpaul
201227089Syongaristatic uint32_t ti_eeprom_putbyte(struct ti_softc *, int);
202227089Syongaristatic uint8_t	ti_eeprom_getbyte(struct ti_softc *, int, uint8_t *);
203142407Simpstatic int ti_read_eeprom(struct ti_softc *, caddr_t, int, int);
20445386Swpaul
205142407Simpstatic void ti_add_mcast(struct ti_softc *, struct ether_addr *);
206142407Simpstatic void ti_del_mcast(struct ti_softc *, struct ether_addr *);
207142407Simpstatic void ti_setmulti(struct ti_softc *);
20845386Swpaul
209227089Syongaristatic void ti_mem_read(struct ti_softc *, uint32_t, uint32_t, void *);
210227089Syongaristatic void ti_mem_write(struct ti_softc *, uint32_t, uint32_t, void *);
211227089Syongaristatic void ti_mem_zero(struct ti_softc *, uint32_t, uint32_t);
212227089Syongaristatic int ti_copy_mem(struct ti_softc *, uint32_t, uint32_t, caddr_t, int,
213227087Syongari    int);
214227089Syongaristatic int ti_copy_scratch(struct ti_softc *, uint32_t, uint32_t, caddr_t,
215227087Syongari    int, int, int);
216142407Simpstatic int ti_bcopy_swap(const void *, void *, size_t, ti_swap_type);
217142407Simpstatic void ti_loadfw(struct ti_softc *);
218142407Simpstatic void ti_cmd(struct ti_softc *, struct ti_cmd_desc *);
219142407Simpstatic void ti_cmd_ext(struct ti_softc *, struct ti_cmd_desc *, caddr_t, int);
220142407Simpstatic void ti_handle_events(struct ti_softc *);
221153396Sscottlstatic int ti_alloc_dmamaps(struct ti_softc *);
222153396Sscottlstatic void ti_free_dmamaps(struct ti_softc *);
223153396Sscottlstatic int ti_alloc_jumbo_mem(struct ti_softc *);
224227347Syongaristatic int ti_newbuf_std(struct ti_softc *, int);
225227347Syongaristatic int ti_newbuf_mini(struct ti_softc *, int);
226142407Simpstatic int ti_newbuf_jumbo(struct ti_softc *, int, struct mbuf *);
227142407Simpstatic int ti_init_rx_ring_std(struct ti_softc *);
228142407Simpstatic void ti_free_rx_ring_std(struct ti_softc *);
229142407Simpstatic int ti_init_rx_ring_jumbo(struct ti_softc *);
230142407Simpstatic void ti_free_rx_ring_jumbo(struct ti_softc *);
231142407Simpstatic int ti_init_rx_ring_mini(struct ti_softc *);
232142407Simpstatic void ti_free_rx_ring_mini(struct ti_softc *);
233142407Simpstatic void ti_free_tx_ring(struct ti_softc *);
234142407Simpstatic int ti_init_tx_ring(struct ti_softc *);
235227347Syongaristatic void ti_discard_std(struct ti_softc *, int);
236227347Syongari#ifndef TI_SF_BUF_JUMBO
237227347Syongaristatic void ti_discard_jumbo(struct ti_softc *, int);
238227347Syongari#endif
239227347Syongaristatic void ti_discard_mini(struct ti_softc *, int);
24045386Swpaul
241142407Simpstatic int ti_64bitslot_war(struct ti_softc *);
242142407Simpstatic int ti_chipinit(struct ti_softc *);
243142407Simpstatic int ti_gibinit(struct ti_softc *);
24445386Swpaul
24598849Sken#ifdef TI_JUMBO_HDRSPLIT
246227087Syongaristatic __inline void ti_hdr_split(struct mbuf *top, int hdr_len, int pkt_len,
247227087Syongari    int idx);
24898849Sken#endif /* TI_JUMBO_HDRSPLIT */
24998849Sken
25049011Swpaulstatic device_method_t ti_methods[] = {
25149011Swpaul	/* Device interface */
25249011Swpaul	DEVMETHOD(device_probe,		ti_probe),
25349011Swpaul	DEVMETHOD(device_attach,	ti_attach),
25449011Swpaul	DEVMETHOD(device_detach,	ti_detach),
25549011Swpaul	DEVMETHOD(device_shutdown,	ti_shutdown),
25649011Swpaul	{ 0, 0 }
25749011Swpaul};
25849011Swpaul
25949011Swpaulstatic driver_t ti_driver = {
26051455Swpaul	"ti",
26149011Swpaul	ti_methods,
26249011Swpaul	sizeof(struct ti_softc)
26349011Swpaul};
26449011Swpaul
26549011Swpaulstatic devclass_t ti_devclass;
26649011Swpaul
267113506SmdoddDRIVER_MODULE(ti, pci, ti_driver, ti_devclass, 0, 0);
268113506SmdoddMODULE_DEPEND(ti, pci, 1, 1, 1);
269113506SmdoddMODULE_DEPEND(ti, ether, 1, 1, 1);
27049011Swpaul
27145386Swpaul/*
27245386Swpaul * Send an instruction or address to the EEPROM, check for ACK.
27345386Swpaul */
274227089Syongaristatic uint32_t
275227087Syongariti_eeprom_putbyte(struct ti_softc *sc, int byte)
27645386Swpaul{
277227087Syongari	int i, ack = 0;
27845386Swpaul
27945386Swpaul	/*
28045386Swpaul	 * Make sure we're in TX mode.
28145386Swpaul	 */
28245386Swpaul	TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN);
28345386Swpaul
28445386Swpaul	/*
28545386Swpaul	 * Feed in each bit and stobe the clock.
28645386Swpaul	 */
28745386Swpaul	for (i = 0x80; i; i >>= 1) {
28845386Swpaul		if (byte & i) {
28945386Swpaul			TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT);
29045386Swpaul		} else {
29145386Swpaul			TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_DOUT);
29245386Swpaul		}
29345386Swpaul		DELAY(1);
29445386Swpaul		TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
29545386Swpaul		DELAY(1);
29645386Swpaul		TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
29745386Swpaul	}
29845386Swpaul
29945386Swpaul	/*
30045386Swpaul	 * Turn off TX mode.
30145386Swpaul	 */
30245386Swpaul	TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN);
30345386Swpaul
30445386Swpaul	/*
30545386Swpaul	 * Check for ack.
30645386Swpaul	 */
30745386Swpaul	TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
30845386Swpaul	ack = CSR_READ_4(sc, TI_MISC_LOCAL_CTL) & TI_MLC_EE_DIN;
30945386Swpaul	TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
31045386Swpaul
311131654Sbms	return (ack);
31245386Swpaul}
31345386Swpaul
31445386Swpaul/*
31545386Swpaul * Read a byte of data stored in the EEPROM at address 'addr.'
31645386Swpaul * We have to send two address bytes since the EEPROM can hold
31745386Swpaul * more than 256 bytes of data.
31845386Swpaul */
319227089Syongaristatic uint8_t
320227089Syongariti_eeprom_getbyte(struct ti_softc *sc, int addr, uint8_t *dest)
32145386Swpaul{
322227087Syongari	int i;
323227089Syongari	uint8_t byte = 0;
32445386Swpaul
32545386Swpaul	EEPROM_START;
32645386Swpaul
32745386Swpaul	/*
32845386Swpaul	 * Send write control code to EEPROM.
32945386Swpaul	 */
33045386Swpaul	if (ti_eeprom_putbyte(sc, EEPROM_CTL_WRITE)) {
331162321Sglebius		device_printf(sc->ti_dev,
332150719Sjhb		    "failed to send write command, status: %x\n",
333150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
334131654Sbms		return (1);
33545386Swpaul	}
33645386Swpaul
33745386Swpaul	/*
33845386Swpaul	 * Send first byte of address of byte we want to read.
33945386Swpaul	 */
34045386Swpaul	if (ti_eeprom_putbyte(sc, (addr >> 8) & 0xFF)) {
341162321Sglebius		device_printf(sc->ti_dev, "failed to send address, status: %x\n",
342150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
343131654Sbms		return (1);
34445386Swpaul	}
34545386Swpaul	/*
34645386Swpaul	 * Send second byte address of byte we want to read.
34745386Swpaul	 */
34845386Swpaul	if (ti_eeprom_putbyte(sc, addr & 0xFF)) {
349162321Sglebius		device_printf(sc->ti_dev, "failed to send address, status: %x\n",
350150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
351131654Sbms		return (1);
35245386Swpaul	}
35345386Swpaul
35445386Swpaul	EEPROM_STOP;
35545386Swpaul	EEPROM_START;
35645386Swpaul	/*
35745386Swpaul	 * Send read control code to EEPROM.
35845386Swpaul	 */
35945386Swpaul	if (ti_eeprom_putbyte(sc, EEPROM_CTL_READ)) {
360162321Sglebius		device_printf(sc->ti_dev,
361150719Sjhb		    "failed to send read command, status: %x\n",
362150719Sjhb		    CSR_READ_4(sc, TI_MISC_LOCAL_CTL));
363131654Sbms		return (1);
36445386Swpaul	}
36545386Swpaul
36645386Swpaul	/*
36745386Swpaul	 * Start reading bits from EEPROM.
36845386Swpaul	 */
36945386Swpaul	TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_TXEN);
37045386Swpaul	for (i = 0x80; i; i >>= 1) {
37145386Swpaul		TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
37245386Swpaul		DELAY(1);
37345386Swpaul		if (CSR_READ_4(sc, TI_MISC_LOCAL_CTL) & TI_MLC_EE_DIN)
37445386Swpaul			byte |= i;
37545386Swpaul		TI_CLRBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_EE_CLK);
37645386Swpaul		DELAY(1);
37745386Swpaul	}
37845386Swpaul
37945386Swpaul	EEPROM_STOP;
38045386Swpaul
38145386Swpaul	/*
38245386Swpaul	 * No ACK generated for read, so just return byte.
38345386Swpaul	 */
38445386Swpaul
38545386Swpaul	*dest = byte;
38645386Swpaul
387131654Sbms	return (0);
38845386Swpaul}
38945386Swpaul
39045386Swpaul/*
39145386Swpaul * Read a sequence of bytes from the EEPROM.
39245386Swpaul */
393102336Salfredstatic int
394227086Syongariti_read_eeprom(struct ti_softc *sc, caddr_t dest, int off, int cnt)
39545386Swpaul{
396227087Syongari	int err = 0, i;
397227089Syongari	uint8_t byte = 0;
39845386Swpaul
39945386Swpaul	for (i = 0; i < cnt; i++) {
40045386Swpaul		err = ti_eeprom_getbyte(sc, off + i, &byte);
40145386Swpaul		if (err)
40245386Swpaul			break;
40345386Swpaul		*(dest + i) = byte;
40445386Swpaul	}
40545386Swpaul
406131654Sbms	return (err ? 1 : 0);
40745386Swpaul}
40845386Swpaul
40945386Swpaul/*
410153770Syongari * NIC memory read function.
411153770Syongari * Can be used to copy data from NIC local memory.
41245386Swpaul */
413102336Salfredstatic void
414227089Syongariti_mem_read(struct ti_softc *sc, uint32_t addr, uint32_t len, void *buf)
41545386Swpaul{
416227087Syongari	int segptr, segsize, cnt;
417227087Syongari	char *ptr;
41845386Swpaul
41945386Swpaul	segptr = addr;
42045386Swpaul	cnt = len;
42145386Swpaul	ptr = buf;
42245386Swpaul
423131654Sbms	while (cnt) {
42445386Swpaul		if (cnt < TI_WINLEN)
42545386Swpaul			segsize = cnt;
42645386Swpaul		else
42745386Swpaul			segsize = TI_WINLEN - (segptr % TI_WINLEN);
42845386Swpaul		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
429153770Syongari		bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
430227089Syongari		    TI_WINDOW + (segptr & (TI_WINLEN - 1)), (uint32_t *)ptr,
431153770Syongari		    segsize / 4);
432153770Syongari		ptr += segsize;
43345386Swpaul		segptr += segsize;
43445386Swpaul		cnt -= segsize;
43545386Swpaul	}
43645386Swpaul}
43745386Swpaul
438153770Syongari
439153770Syongari/*
440153770Syongari * NIC memory write function.
441153770Syongari * Can be used to copy data into NIC local memory.
442153770Syongari */
443153770Syongaristatic void
444227089Syongariti_mem_write(struct ti_softc *sc, uint32_t addr, uint32_t len, void *buf)
445153770Syongari{
446227087Syongari	int segptr, segsize, cnt;
447227087Syongari	char *ptr;
448153770Syongari
449153770Syongari	segptr = addr;
450153770Syongari	cnt = len;
451153770Syongari	ptr = buf;
452153770Syongari
453153770Syongari	while (cnt) {
454153770Syongari		if (cnt < TI_WINLEN)
455153770Syongari			segsize = cnt;
456153770Syongari		else
457153770Syongari			segsize = TI_WINLEN - (segptr % TI_WINLEN);
458153770Syongari		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
459153770Syongari		bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
460227089Syongari		    TI_WINDOW + (segptr & (TI_WINLEN - 1)), (uint32_t *)ptr,
461153770Syongari		    segsize / 4);
462153770Syongari		ptr += segsize;
463153770Syongari		segptr += segsize;
464153770Syongari		cnt -= segsize;
465153770Syongari	}
466153770Syongari}
467153770Syongari
468153770Syongari/*
469153770Syongari * NIC memory read function.
470153770Syongari * Can be used to clear a section of NIC local memory.
471153770Syongari */
472153770Syongaristatic void
473227089Syongariti_mem_zero(struct ti_softc *sc, uint32_t addr, uint32_t len)
474153770Syongari{
475227087Syongari	int segptr, segsize, cnt;
476153770Syongari
477153770Syongari	segptr = addr;
478153770Syongari	cnt = len;
479153770Syongari
480153770Syongari	while (cnt) {
481153770Syongari		if (cnt < TI_WINLEN)
482153770Syongari			segsize = cnt;
483153770Syongari		else
484153770Syongari			segsize = TI_WINLEN - (segptr % TI_WINLEN);
485153770Syongari		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
486153770Syongari		bus_space_set_region_4(sc->ti_btag, sc->ti_bhandle,
487153770Syongari		    TI_WINDOW + (segptr & (TI_WINLEN - 1)), 0, segsize / 4);
488153770Syongari		segptr += segsize;
489153770Syongari		cnt -= segsize;
490153770Syongari	}
491153770Syongari}
492153770Syongari
49398849Skenstatic int
494227089Syongariti_copy_mem(struct ti_softc *sc, uint32_t tigon_addr, uint32_t len,
495227086Syongari    caddr_t buf, int useraddr, int readdata)
49698849Sken{
497227087Syongari	int segptr, segsize, cnt;
498227087Syongari	caddr_t ptr;
499227089Syongari	uint32_t origwin;
500227087Syongari	int resid, segresid;
501227087Syongari	int first_pass;
50298849Sken
503153770Syongari	TI_LOCK_ASSERT(sc);
504153770Syongari
50598849Sken	/*
50698849Sken	 * At the moment, we don't handle non-aligned cases, we just bail.
50798849Sken	 * If this proves to be a problem, it will be fixed.
50898849Sken	 */
509227431Syongari	if (readdata == 0 && (tigon_addr & 0x3) != 0) {
510162321Sglebius		device_printf(sc->ti_dev, "%s: tigon address %#x isn't "
511162321Sglebius		    "word-aligned\n", __func__, tigon_addr);
512162321Sglebius		device_printf(sc->ti_dev, "%s: unaligned writes aren't "
513162321Sglebius		    "yet supported\n", __func__);
514131654Sbms		return (EINVAL);
51598849Sken	}
51698849Sken
51798849Sken	segptr = tigon_addr & ~0x3;
51898849Sken	segresid = tigon_addr - segptr;
51998849Sken
52098849Sken	/*
52198849Sken	 * This is the non-aligned amount left over that we'll need to
52298849Sken	 * copy.
52398849Sken	 */
52498849Sken	resid = len & 0x3;
52598849Sken
52698849Sken	/* Add in the left over amount at the front of the buffer */
52798849Sken	resid += segresid;
52898849Sken
52998849Sken	cnt = len & ~0x3;
53098849Sken	/*
53198849Sken	 * If resid + segresid is >= 4, add multiples of 4 to the count and
53298849Sken	 * decrease the residual by that much.
53398849Sken	 */
53498849Sken	cnt += resid & ~0x3;
53598849Sken	resid -= resid & ~0x3;
53698849Sken
53798849Sken	ptr = buf;
53898849Sken
53998849Sken	first_pass = 1;
54098849Sken
54198849Sken	/*
54298849Sken	 * Save the old window base value.
54398849Sken	 */
54498849Sken	origwin = CSR_READ_4(sc, TI_WINBASE);
54598849Sken
546131654Sbms	while (cnt) {
54798849Sken		bus_size_t ti_offset;
54898849Sken
54998849Sken		if (cnt < TI_WINLEN)
55098849Sken			segsize = cnt;
55198849Sken		else
55298849Sken			segsize = TI_WINLEN - (segptr % TI_WINLEN);
55398849Sken		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
55498849Sken
55598849Sken		ti_offset = TI_WINDOW + (segptr & (TI_WINLEN -1));
55698849Sken
55798849Sken		if (readdata) {
558227431Syongari			bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
559227505Syongari			    ti_offset, (uint32_t *)sc->ti_membuf, segsize >> 2);
56098849Sken			if (useraddr) {
56198849Sken				/*
56298849Sken				 * Yeah, this is a little on the kludgy
56398849Sken				 * side, but at least this code is only
56498849Sken				 * used for debugging.
56598849Sken				 */
566227505Syongari				ti_bcopy_swap(sc->ti_membuf, sc->ti_membuf2,
567227505Syongari				    segsize, TI_SWAP_NTOH);
56898849Sken
569153281Sscottl				TI_UNLOCK(sc);
57098849Sken				if (first_pass) {
571227505Syongari					copyout(&sc->ti_membuf2[segresid], ptr,
572227431Syongari					    segsize - segresid);
57398849Sken					first_pass = 0;
57498849Sken				} else
575227505Syongari					copyout(sc->ti_membuf2, ptr, segsize);
576153281Sscottl				TI_LOCK(sc);
57798849Sken			} else {
57898849Sken				if (first_pass) {
579227505Syongari
580227505Syongari					ti_bcopy_swap(sc->ti_membuf,
581227505Syongari					    sc->ti_membuf2, segsize,
582227505Syongari					    TI_SWAP_NTOH);
583153281Sscottl					TI_UNLOCK(sc);
584227505Syongari					bcopy(&sc->ti_membuf2[segresid], ptr,
585227431Syongari					    segsize - segresid);
586153281Sscottl					TI_LOCK(sc);
58798849Sken					first_pass = 0;
58898849Sken				} else
589227505Syongari					ti_bcopy_swap(sc->ti_membuf, ptr,
590227505Syongari					    segsize, TI_SWAP_NTOH);
59198849Sken			}
59298849Sken
59398849Sken		} else {
59498849Sken			if (useraddr) {
595153281Sscottl				TI_UNLOCK(sc);
596227505Syongari				copyin(ptr, sc->ti_membuf2, segsize);
597153281Sscottl				TI_LOCK(sc);
598227505Syongari				ti_bcopy_swap(sc->ti_membuf2, sc->ti_membuf,
599227505Syongari				    segsize, TI_SWAP_HTON);
60098849Sken			} else
601227505Syongari				ti_bcopy_swap(ptr, sc->ti_membuf, segsize,
602227431Syongari				    TI_SWAP_HTON);
60398849Sken
604227431Syongari			bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
605227505Syongari			    ti_offset, (uint32_t *)sc->ti_membuf, segsize >> 2);
60698849Sken		}
60798849Sken		segptr += segsize;
60898849Sken		ptr += segsize;
60998849Sken		cnt -= segsize;
61098849Sken	}
61198849Sken
61298849Sken	/*
61398849Sken	 * Handle leftover, non-word-aligned bytes.
61498849Sken	 */
61598849Sken	if (resid != 0) {
616227431Syongari		uint32_t tmpval, tmpval2;
617227431Syongari		bus_size_t ti_offset;
61898849Sken
61998849Sken		/*
62098849Sken		 * Set the segment pointer.
62198849Sken		 */
62298849Sken		CSR_WRITE_4(sc, TI_WINBASE, (segptr & ~(TI_WINLEN - 1)));
62398849Sken
62498849Sken		ti_offset = TI_WINDOW + (segptr & (TI_WINLEN - 1));
62598849Sken
62698849Sken		/*
62798849Sken		 * First, grab whatever is in our source/destination.
62898849Sken		 * We'll obviously need this for reads, but also for
62998849Sken		 * writes, since we'll be doing read/modify/write.
63098849Sken		 */
63198849Sken		bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
632227431Syongari		    ti_offset, &tmpval, 1);
63398849Sken
63498849Sken		/*
63598849Sken		 * Next, translate this from little-endian to big-endian
63698849Sken		 * (at least on i386 boxes).
63798849Sken		 */
63898849Sken		tmpval2 = ntohl(tmpval);
63998849Sken
64098849Sken		if (readdata) {
64198849Sken			/*
64298849Sken			 * If we're reading, just copy the leftover number
64398849Sken			 * of bytes from the host byte order buffer to
64498849Sken			 * the user's buffer.
64598849Sken			 */
646153281Sscottl			if (useraddr) {
647153281Sscottl				TI_UNLOCK(sc);
64898849Sken				copyout(&tmpval2, ptr, resid);
649153281Sscottl				TI_LOCK(sc);
650153281Sscottl			} else
65198849Sken				bcopy(&tmpval2, ptr, resid);
65298849Sken		} else {
65398849Sken			/*
65498849Sken			 * If we're writing, first copy the bytes to be
65598849Sken			 * written into the network byte order buffer,
65698849Sken			 * leaving the rest of the buffer with whatever was
65798849Sken			 * originally in there.  Then, swap the bytes
65898849Sken			 * around into host order and write them out.
65998849Sken			 *
66098849Sken			 * XXX KDM the read side of this has been verified
66198849Sken			 * to work, but the write side of it has not been
66298849Sken			 * verified.  So user beware.
66398849Sken			 */
664153281Sscottl			if (useraddr) {
665153281Sscottl				TI_UNLOCK(sc);
66698849Sken				copyin(ptr, &tmpval2, resid);
667153281Sscottl				TI_LOCK(sc);
668153281Sscottl			} else
66998849Sken				bcopy(ptr, &tmpval2, resid);
67098849Sken
67198849Sken			tmpval = htonl(tmpval2);
67298849Sken
67398849Sken			bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
674227431Syongari			    ti_offset, &tmpval, 1);
67598849Sken		}
67698849Sken	}
67798849Sken
67898849Sken	CSR_WRITE_4(sc, TI_WINBASE, origwin);
67998849Sken
680131654Sbms	return (0);
68198849Sken}
68298849Sken
68398849Skenstatic int
684227089Syongariti_copy_scratch(struct ti_softc *sc, uint32_t tigon_addr, uint32_t len,
685227086Syongari    caddr_t buf, int useraddr, int readdata, int cpu)
68698849Sken{
687227089Syongari	uint32_t segptr;
688227087Syongari	int cnt;
689227089Syongari	uint32_t tmpval, tmpval2;
690227087Syongari	caddr_t ptr;
69198849Sken
692153770Syongari	TI_LOCK_ASSERT(sc);
693153770Syongari
69498849Sken	/*
69598849Sken	 * At the moment, we don't handle non-aligned cases, we just bail.
69698849Sken	 * If this proves to be a problem, it will be fixed.
69798849Sken	 */
69898849Sken	if (tigon_addr & 0x3) {
699162321Sglebius		device_printf(sc->ti_dev, "%s: tigon address %#x "
700162321Sglebius		    "isn't word-aligned\n", __func__, tigon_addr);
701131654Sbms		return (EINVAL);
70298849Sken	}
70398849Sken
70498849Sken	if (len & 0x3) {
705162321Sglebius		device_printf(sc->ti_dev, "%s: transfer length %d "
706162321Sglebius		    "isn't word-aligned\n", __func__, len);
707131654Sbms		return (EINVAL);
70898849Sken	}
70998849Sken
71098849Sken	segptr = tigon_addr;
71198849Sken	cnt = len;
71298849Sken	ptr = buf;
71398849Sken
71498849Sken	while (cnt) {
71598849Sken		CSR_WRITE_4(sc, CPU_REG(TI_SRAM_ADDR, cpu), segptr);
71698849Sken
71798849Sken		if (readdata) {
71898849Sken			tmpval2 = CSR_READ_4(sc, CPU_REG(TI_SRAM_DATA, cpu));
71998849Sken
72098849Sken			tmpval = ntohl(tmpval2);
72198849Sken
72298849Sken			/*
72398849Sken			 * Note:  I've used this debugging interface
72498849Sken			 * extensively with Alteon's 12.3.15 firmware,
72598849Sken			 * compiled with GCC 2.7.2.1 and binutils 2.9.1.
72698849Sken			 *
72798849Sken			 * When you compile the firmware without
72898849Sken			 * optimization, which is necessary sometimes in
72998849Sken			 * order to properly step through it, you sometimes
730131652Sbms			 * read out a bogus value of 0xc0017c instead of
73198849Sken			 * whatever was supposed to be in that scratchpad
73298849Sken			 * location.  That value is on the stack somewhere,
73398849Sken			 * but I've never been able to figure out what was
73498849Sken			 * causing the problem.
73598849Sken			 *
73698849Sken			 * The address seems to pop up in random places,
73798849Sken			 * often not in the same place on two subsequent
73898849Sken			 * reads.
73998849Sken			 *
74098849Sken			 * In any case, the underlying data doesn't seem
74198849Sken			 * to be affected, just the value read out.
74298849Sken			 *
74398849Sken			 * KDM, 3/7/2000
74498849Sken			 */
74598849Sken
74698849Sken			if (tmpval2 == 0xc0017c)
747162321Sglebius				device_printf(sc->ti_dev, "found 0xc0017c at "
748162321Sglebius				    "%#x (tmpval2)\n", segptr);
74998849Sken
75098849Sken			if (tmpval == 0xc0017c)
751162321Sglebius				device_printf(sc->ti_dev, "found 0xc0017c at "
752162321Sglebius				    "%#x (tmpval)\n", segptr);
75398849Sken
75498849Sken			if (useraddr)
75598849Sken				copyout(&tmpval, ptr, 4);
75698849Sken			else
75798849Sken				bcopy(&tmpval, ptr, 4);
75898849Sken		} else {
75998849Sken			if (useraddr)
76098849Sken				copyin(ptr, &tmpval2, 4);
76198849Sken			else
76298849Sken				bcopy(ptr, &tmpval2, 4);
76398849Sken
76498849Sken			tmpval = htonl(tmpval2);
76598849Sken
76698849Sken			CSR_WRITE_4(sc, CPU_REG(TI_SRAM_DATA, cpu), tmpval);
76798849Sken		}
76898849Sken
76998849Sken		cnt -= 4;
77098849Sken		segptr += 4;
77198849Sken		ptr += 4;
77298849Sken	}
77398849Sken
774131654Sbms	return (0);
77598849Sken}
77698849Sken
77798849Skenstatic int
778227086Syongariti_bcopy_swap(const void *src, void *dst, size_t len, ti_swap_type swap_type)
77998849Sken{
780227089Syongari	const uint8_t *tmpsrc;
781227089Syongari	uint8_t *tmpdst;
78298849Sken	size_t tmplen;
78398849Sken
78498849Sken	if (len & 0x3) {
785227431Syongari		printf("ti_bcopy_swap: length %zd isn't 32-bit aligned\n", len);
786131654Sbms		return (-1);
78798849Sken	}
78898849Sken
78998849Sken	tmpsrc = src;
79098849Sken	tmpdst = dst;
79198849Sken	tmplen = len;
79298849Sken
79398849Sken	while (tmplen) {
79498849Sken		if (swap_type == TI_SWAP_NTOH)
795227431Syongari			*(uint32_t *)tmpdst = ntohl(*(const uint32_t *)tmpsrc);
79698849Sken		else
797227431Syongari			*(uint32_t *)tmpdst = htonl(*(const uint32_t *)tmpsrc);
79898849Sken		tmpsrc += 4;
79998849Sken		tmpdst += 4;
80098849Sken		tmplen -= 4;
80198849Sken	}
80298849Sken
803131654Sbms	return (0);
80498849Sken}
80598849Sken
80645386Swpaul/*
80745386Swpaul * Load firmware image into the NIC. Check that the firmware revision
80845386Swpaul * is acceptable and see if we want the firmware for the Tigon 1 or
80945386Swpaul * Tigon 2.
81045386Swpaul */
811102336Salfredstatic void
812227086Syongariti_loadfw(struct ti_softc *sc)
81345386Swpaul{
814153770Syongari
815153770Syongari	TI_LOCK_ASSERT(sc);
816153770Syongari
817131654Sbms	switch (sc->ti_hwrev) {
81845386Swpaul	case TI_HWREV_TIGON:
81945386Swpaul		if (tigonFwReleaseMajor != TI_FIRMWARE_MAJOR ||
82045386Swpaul		    tigonFwReleaseMinor != TI_FIRMWARE_MINOR ||
82145386Swpaul		    tigonFwReleaseFix != TI_FIRMWARE_FIX) {
822162321Sglebius			device_printf(sc->ti_dev, "firmware revision mismatch; "
823150719Sjhb			    "want %d.%d.%d, got %d.%d.%d\n",
82445386Swpaul			    TI_FIRMWARE_MAJOR, TI_FIRMWARE_MINOR,
82545386Swpaul			    TI_FIRMWARE_FIX, tigonFwReleaseMajor,
82645386Swpaul			    tigonFwReleaseMinor, tigonFwReleaseFix);
82745386Swpaul			return;
82845386Swpaul		}
829153770Syongari		ti_mem_write(sc, tigonFwTextAddr, tigonFwTextLen, tigonFwText);
830153770Syongari		ti_mem_write(sc, tigonFwDataAddr, tigonFwDataLen, tigonFwData);
831153770Syongari		ti_mem_write(sc, tigonFwRodataAddr, tigonFwRodataLen,
832153770Syongari		    tigonFwRodata);
833153770Syongari		ti_mem_zero(sc, tigonFwBssAddr, tigonFwBssLen);
834153770Syongari		ti_mem_zero(sc, tigonFwSbssAddr, tigonFwSbssLen);
83545386Swpaul		CSR_WRITE_4(sc, TI_CPU_PROGRAM_COUNTER, tigonFwStartAddr);
83645386Swpaul		break;
83745386Swpaul	case TI_HWREV_TIGON_II:
83845386Swpaul		if (tigon2FwReleaseMajor != TI_FIRMWARE_MAJOR ||
83945386Swpaul		    tigon2FwReleaseMinor != TI_FIRMWARE_MINOR ||
84045386Swpaul		    tigon2FwReleaseFix != TI_FIRMWARE_FIX) {
841162321Sglebius			device_printf(sc->ti_dev, "firmware revision mismatch; "
842150719Sjhb			    "want %d.%d.%d, got %d.%d.%d\n",
84345386Swpaul			    TI_FIRMWARE_MAJOR, TI_FIRMWARE_MINOR,
84445386Swpaul			    TI_FIRMWARE_FIX, tigon2FwReleaseMajor,
84545386Swpaul			    tigon2FwReleaseMinor, tigon2FwReleaseFix);
84645386Swpaul			return;
84745386Swpaul		}
848153770Syongari		ti_mem_write(sc, tigon2FwTextAddr, tigon2FwTextLen,
849153770Syongari		    tigon2FwText);
850153770Syongari		ti_mem_write(sc, tigon2FwDataAddr, tigon2FwDataLen,
851153770Syongari		    tigon2FwData);
852153770Syongari		ti_mem_write(sc, tigon2FwRodataAddr, tigon2FwRodataLen,
853153770Syongari		    tigon2FwRodata);
854153770Syongari		ti_mem_zero(sc, tigon2FwBssAddr, tigon2FwBssLen);
855153770Syongari		ti_mem_zero(sc, tigon2FwSbssAddr, tigon2FwSbssLen);
85645386Swpaul		CSR_WRITE_4(sc, TI_CPU_PROGRAM_COUNTER, tigon2FwStartAddr);
85745386Swpaul		break;
85845386Swpaul	default:
859162321Sglebius		device_printf(sc->ti_dev,
860150719Sjhb		    "can't load firmware: unknown hardware rev\n");
86145386Swpaul		break;
86245386Swpaul	}
86345386Swpaul}
86445386Swpaul
86545386Swpaul/*
86645386Swpaul * Send the NIC a command via the command ring.
86745386Swpaul */
868102336Salfredstatic void
869227086Syongariti_cmd(struct ti_softc *sc, struct ti_cmd_desc *cmd)
87045386Swpaul{
871227087Syongari	int index;
87245386Swpaul
87345386Swpaul	index = sc->ti_cmd_saved_prodidx;
874227089Syongari	CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4), *(uint32_t *)(cmd));
87545386Swpaul	TI_INC(index, TI_CMD_RING_CNT);
87645386Swpaul	CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, index);
87745386Swpaul	sc->ti_cmd_saved_prodidx = index;
87845386Swpaul}
87945386Swpaul
88045386Swpaul/*
88145386Swpaul * Send the NIC an extended command. The 'len' parameter specifies the
88245386Swpaul * number of command slots to include after the initial command.
88345386Swpaul */
884102336Salfredstatic void
885227086Syongariti_cmd_ext(struct ti_softc *sc, struct ti_cmd_desc *cmd, caddr_t arg, int len)
88645386Swpaul{
887227087Syongari	int index;
888227087Syongari	int i;
88945386Swpaul
89045386Swpaul	index = sc->ti_cmd_saved_prodidx;
891227089Syongari	CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4), *(uint32_t *)(cmd));
89245386Swpaul	TI_INC(index, TI_CMD_RING_CNT);
89345386Swpaul	for (i = 0; i < len; i++) {
89445386Swpaul		CSR_WRITE_4(sc, TI_GCR_CMDRING + (index * 4),
895227089Syongari		    *(uint32_t *)(&arg[i * 4]));
89645386Swpaul		TI_INC(index, TI_CMD_RING_CNT);
89745386Swpaul	}
89845386Swpaul	CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, index);
89945386Swpaul	sc->ti_cmd_saved_prodidx = index;
90045386Swpaul}
90145386Swpaul
90245386Swpaul/*
90345386Swpaul * Handle events that have triggered interrupts.
90445386Swpaul */
905102336Salfredstatic void
906227086Syongariti_handle_events(struct ti_softc *sc)
90745386Swpaul{
908227087Syongari	struct ti_event_desc *e;
90945386Swpaul
91045386Swpaul	if (sc->ti_rdata->ti_event_ring == NULL)
91145386Swpaul		return;
91245386Swpaul
91345386Swpaul	while (sc->ti_ev_saved_considx != sc->ti_ev_prodidx.ti_idx) {
91445386Swpaul		e = &sc->ti_rdata->ti_event_ring[sc->ti_ev_saved_considx];
915153770Syongari		switch (TI_EVENT_EVENT(e)) {
91645386Swpaul		case TI_EV_LINKSTAT_CHANGED:
917153770Syongari			sc->ti_linkstat = TI_EVENT_CODE(e);
918227092Syongari			if (sc->ti_linkstat == TI_EV_CODE_LINK_UP) {
919227092Syongari				if_link_state_change(sc->ti_ifp, LINK_STATE_UP);
920227092Syongari				sc->ti_ifp->if_baudrate = IF_Mbps(100);
921227092Syongari				if (bootverbose)
922227092Syongari					device_printf(sc->ti_dev,
923227092Syongari					    "10/100 link up\n");
924227092Syongari			} else if (sc->ti_linkstat == TI_EV_CODE_GIG_LINK_UP) {
925227092Syongari				if_link_state_change(sc->ti_ifp, LINK_STATE_UP);
926227092Syongari				sc->ti_ifp->if_baudrate = IF_Gbps(1UL);
927227092Syongari				if (bootverbose)
928227092Syongari					device_printf(sc->ti_dev,
929227092Syongari					    "gigabit link up\n");
930227092Syongari			} else if (sc->ti_linkstat == TI_EV_CODE_LINK_DOWN) {
931227092Syongari				if_link_state_change(sc->ti_ifp,
932227092Syongari				    LINK_STATE_DOWN);
933227092Syongari				sc->ti_ifp->if_baudrate = 0;
934227092Syongari				if (bootverbose)
935227092Syongari					device_printf(sc->ti_dev,
936227092Syongari					    "link down\n");
937227092Syongari			}
93845386Swpaul			break;
93945386Swpaul		case TI_EV_ERROR:
940153770Syongari			if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_INVAL_CMD)
941162321Sglebius				device_printf(sc->ti_dev, "invalid command\n");
942153770Syongari			else if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_UNIMP_CMD)
943162321Sglebius				device_printf(sc->ti_dev, "unknown command\n");
944153770Syongari			else if (TI_EVENT_CODE(e) == TI_EV_CODE_ERR_BADCFG)
945162321Sglebius				device_printf(sc->ti_dev, "bad config data\n");
94645386Swpaul			break;
94745386Swpaul		case TI_EV_FIRMWARE_UP:
94845386Swpaul			ti_init2(sc);
94945386Swpaul			break;
95045386Swpaul		case TI_EV_STATS_UPDATED:
95145386Swpaul			ti_stats_update(sc);
95245386Swpaul			break;
95345386Swpaul		case TI_EV_RESET_JUMBO_RING:
95445386Swpaul		case TI_EV_MCAST_UPDATED:
95545386Swpaul			/* Who cares. */
95645386Swpaul			break;
95745386Swpaul		default:
958162321Sglebius			device_printf(sc->ti_dev, "unknown event: %d\n",
959153770Syongari			    TI_EVENT_EVENT(e));
96045386Swpaul			break;
96145386Swpaul		}
96245386Swpaul		/* Advance the consumer index. */
96345386Swpaul		TI_INC(sc->ti_ev_saved_considx, TI_EVENT_RING_CNT);
96445386Swpaul		CSR_WRITE_4(sc, TI_GCR_EVENTCONS_IDX, sc->ti_ev_saved_considx);
96545386Swpaul	}
96645386Swpaul}
96745386Swpaul
968153396Sscottlstatic int
969153396Sscottlti_alloc_dmamaps(struct ti_softc *sc)
970153396Sscottl{
971153396Sscottl	int i;
972153396Sscottl
973153396Sscottl	for (i = 0; i < TI_TX_RING_CNT; i++) {
974153982Syongari		sc->ti_cdata.ti_txdesc[i].tx_m = NULL;
975227347Syongari		sc->ti_cdata.ti_txdesc[i].tx_dmamap = NULL;
976153396Sscottl		if (bus_dmamap_create(sc->ti_mbuftx_dmat, 0,
977227347Syongari		    &sc->ti_cdata.ti_txdesc[i].tx_dmamap)) {
978227347Syongari			device_printf(sc->ti_dev,
979227347Syongari			    "cannot create DMA map for TX\n");
980153396Sscottl			return (ENOBUFS);
981227347Syongari		}
982153396Sscottl	}
983153396Sscottl	for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
984153396Sscottl		if (bus_dmamap_create(sc->ti_mbufrx_dmat, 0,
985227347Syongari		    &sc->ti_cdata.ti_rx_std_maps[i])) {
986227347Syongari			device_printf(sc->ti_dev,
987227347Syongari			    "cannot create DMA map for RX\n");
988153396Sscottl			return (ENOBUFS);
989227347Syongari		}
990153396Sscottl	}
991227347Syongari	if (bus_dmamap_create(sc->ti_mbufrx_dmat, 0,
992227347Syongari	    &sc->ti_cdata.ti_rx_std_sparemap)) {
993227347Syongari		device_printf(sc->ti_dev,
994227347Syongari		    "cannot create spare DMA map for RX\n");
995227347Syongari		return (ENOBUFS);
996227347Syongari	}
997153396Sscottl
998153396Sscottl	for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
999153396Sscottl		if (bus_dmamap_create(sc->ti_jumbo_dmat, 0,
1000227347Syongari		    &sc->ti_cdata.ti_rx_jumbo_maps[i])) {
1001227347Syongari			device_printf(sc->ti_dev,
1002227347Syongari			    "cannot create DMA map for jumbo RX\n");
1003153396Sscottl			return (ENOBUFS);
1004227347Syongari		}
1005153396Sscottl	}
1006227347Syongari	if (bus_dmamap_create(sc->ti_jumbo_dmat, 0,
1007227347Syongari	    &sc->ti_cdata.ti_rx_jumbo_sparemap)) {
1008227347Syongari		device_printf(sc->ti_dev,
1009227347Syongari		    "cannot create spare DMA map for jumbo RX\n");
1010227347Syongari		return (ENOBUFS);
1011227347Syongari	}
1012227319Syongari
1013227319Syongari	/* Mini ring is not available on Tigon 1. */
1014227319Syongari	if (sc->ti_hwrev == TI_HWREV_TIGON)
1015227319Syongari		return (0);
1016227319Syongari
1017153396Sscottl	for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
1018153396Sscottl		if (bus_dmamap_create(sc->ti_mbufrx_dmat, 0,
1019227347Syongari		    &sc->ti_cdata.ti_rx_mini_maps[i])) {
1020227347Syongari			device_printf(sc->ti_dev,
1021227347Syongari			    "cannot create DMA map for mini RX\n");
1022153396Sscottl			return (ENOBUFS);
1023227347Syongari		}
1024153396Sscottl	}
1025227347Syongari	if (bus_dmamap_create(sc->ti_mbufrx_dmat, 0,
1026227347Syongari	    &sc->ti_cdata.ti_rx_mini_sparemap)) {
1027227347Syongari		device_printf(sc->ti_dev,
1028227347Syongari		    "cannot create DMA map for mini RX\n");
1029227347Syongari		return (ENOBUFS);
1030227347Syongari	}
1031153396Sscottl
1032153396Sscottl	return (0);
1033153396Sscottl}
1034153396Sscottl
1035153396Sscottlstatic void
1036153396Sscottlti_free_dmamaps(struct ti_softc *sc)
1037153396Sscottl{
1038153396Sscottl	int i;
1039153396Sscottl
1040227347Syongari	if (sc->ti_mbuftx_dmat) {
1041227347Syongari		for (i = 0; i < TI_TX_RING_CNT; i++) {
1042153982Syongari			if (sc->ti_cdata.ti_txdesc[i].tx_dmamap) {
1043153770Syongari				bus_dmamap_destroy(sc->ti_mbuftx_dmat,
1044153982Syongari				    sc->ti_cdata.ti_txdesc[i].tx_dmamap);
1045227347Syongari				sc->ti_cdata.ti_txdesc[i].tx_dmamap = NULL;
1046153770Syongari			}
1047227347Syongari		}
1048227347Syongari	}
1049153396Sscottl
1050227347Syongari	if (sc->ti_mbufrx_dmat) {
1051227347Syongari		for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
1052153770Syongari			if (sc->ti_cdata.ti_rx_std_maps[i]) {
1053153770Syongari				bus_dmamap_destroy(sc->ti_mbufrx_dmat,
1054153770Syongari				    sc->ti_cdata.ti_rx_std_maps[i]);
1055227347Syongari				sc->ti_cdata.ti_rx_std_maps[i] = NULL;
1056153770Syongari			}
1057227347Syongari		}
1058227347Syongari		if (sc->ti_cdata.ti_rx_std_sparemap) {
1059227347Syongari			bus_dmamap_destroy(sc->ti_mbufrx_dmat,
1060227347Syongari			    sc->ti_cdata.ti_rx_std_sparemap);
1061227347Syongari			sc->ti_cdata.ti_rx_std_sparemap = NULL;
1062227347Syongari		}
1063227347Syongari	}
1064153396Sscottl
1065227347Syongari	if (sc->ti_jumbo_dmat) {
1066227347Syongari		for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
1067153770Syongari			if (sc->ti_cdata.ti_rx_jumbo_maps[i]) {
1068153770Syongari				bus_dmamap_destroy(sc->ti_jumbo_dmat,
1069153770Syongari				    sc->ti_cdata.ti_rx_jumbo_maps[i]);
1070227347Syongari				sc->ti_cdata.ti_rx_jumbo_maps[i] = NULL;
1071153770Syongari			}
1072227347Syongari		}
1073227347Syongari		if (sc->ti_cdata.ti_rx_jumbo_sparemap) {
1074227347Syongari			bus_dmamap_destroy(sc->ti_jumbo_dmat,
1075227347Syongari			    sc->ti_cdata.ti_rx_jumbo_sparemap);
1076227347Syongari			sc->ti_cdata.ti_rx_jumbo_sparemap = NULL;
1077227347Syongari		}
1078227347Syongari	}
1079227347Syongari
1080227347Syongari	if (sc->ti_mbufrx_dmat) {
1081227347Syongari		for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
1082153770Syongari			if (sc->ti_cdata.ti_rx_mini_maps[i]) {
1083153770Syongari				bus_dmamap_destroy(sc->ti_mbufrx_dmat,
1084153770Syongari				    sc->ti_cdata.ti_rx_mini_maps[i]);
1085227347Syongari				sc->ti_cdata.ti_rx_mini_maps[i] = NULL;
1086153770Syongari			}
1087227347Syongari		}
1088227347Syongari		if (sc->ti_cdata.ti_rx_mini_sparemap) {
1089227347Syongari			bus_dmamap_destroy(sc->ti_mbufrx_dmat,
1090227347Syongari			    sc->ti_cdata.ti_rx_mini_sparemap);
1091227347Syongari			sc->ti_cdata.ti_rx_mini_sparemap = NULL;
1092227347Syongari		}
1093227347Syongari	}
1094153396Sscottl}
1095153396Sscottl
1096227347Syongari#ifndef TI_SF_BUF_JUMBO
109798849Sken
1098102336Salfredstatic int
1099227086Syongariti_alloc_jumbo_mem(struct ti_softc *sc)
110045386Swpaul{
110145386Swpaul
1102227347Syongari	if (bus_dma_tag_create(sc->ti_parent_dmat, 1, 0, BUS_SPACE_MAXADDR,
1103227347Syongari	    BUS_SPACE_MAXADDR, NULL, NULL, MJUM9BYTES, 1, MJUM9BYTES, 0, NULL,
1104227347Syongari	    NULL, &sc->ti_jumbo_dmat) != 0) {
1105153396Sscottl		device_printf(sc->ti_dev, "Failed to allocate jumbo dmat\n");
1106227347Syongari                return (ENOBUFS);
1107153288Sscottl	}
1108131654Sbms	return (0);
110945386Swpaul}
111045386Swpaul
1111153396Sscottl#else
1112153396Sscottl
1113153396Sscottlstatic int
1114227086Syongariti_alloc_jumbo_mem(struct ti_softc *sc)
1115153396Sscottl{
1116153396Sscottl
1117153396Sscottl	/*
1118153396Sscottl	 * The VM system will take care of providing aligned pages.  Alignment
1119153396Sscottl	 * is set to 1 here so that busdma resources won't be wasted.
1120153396Sscottl	 */
1121153396Sscottl	if (bus_dma_tag_create(sc->ti_parent_dmat,	/* parent */
1122153396Sscottl				1, 0,			/* algnmnt, boundary */
1123153396Sscottl				BUS_SPACE_MAXADDR,	/* lowaddr */
1124153396Sscottl				BUS_SPACE_MAXADDR,	/* highaddr */
1125153396Sscottl				NULL, NULL,		/* filter, filterarg */
1126153396Sscottl				PAGE_SIZE * 4 /*XXX*/,	/* maxsize */
1127153396Sscottl				4,			/* nsegments */
1128153396Sscottl				PAGE_SIZE,		/* maxsegsize */
1129153396Sscottl				0,			/* flags */
1130153396Sscottl				NULL, NULL,		/* lockfunc, lockarg */
1131153396Sscottl				&sc->ti_jumbo_dmat) != 0) {
1132153396Sscottl		device_printf(sc->ti_dev, "Failed to allocate jumbo dmat\n");
1133153396Sscottl		return (ENOBUFS);
1134153396Sscottl	}
1135153396Sscottl
1136153396Sscottl	return (0);
1137153396Sscottl}
1138153396Sscottl
1139227347Syongari#endif /* TI_SF_BUF_JUMBO */
114045386Swpaul
114145386Swpaul/*
114245386Swpaul * Intialize a standard receive ring descriptor.
114345386Swpaul */
1144102336Salfredstatic int
1145227347Syongariti_newbuf_std(struct ti_softc *sc, int i)
114645386Swpaul{
1147227087Syongari	bus_dmamap_t map;
1148227347Syongari	bus_dma_segment_t segs[1];
1149227347Syongari	struct mbuf *m;
1150227087Syongari	struct ti_rx_desc *r;
1151227347Syongari	int error, nsegs;
115245386Swpaul
1153227347Syongari	m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1154227347Syongari	if (m == NULL)
1155227347Syongari		return (ENOBUFS);
1156227347Syongari	m->m_len = m->m_pkthdr.len = MCLBYTES;
1157227347Syongari	m_adj(m, ETHER_ALIGN);
115845386Swpaul
1159227347Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_mbufrx_dmat,
1160227347Syongari	    sc->ti_cdata.ti_rx_std_sparemap, m, segs, &nsegs, 0);
1161227347Syongari	if (error != 0) {
1162227347Syongari		m_freem(m);
1163227347Syongari		return (error);
1164227347Syongari        }
1165227347Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
1166227347Syongari
1167227347Syongari	if (sc->ti_cdata.ti_rx_std_chain[i] != NULL) {
1168227347Syongari		bus_dmamap_sync(sc->ti_mbufrx_dmat,
1169227347Syongari		    sc->ti_cdata.ti_rx_std_maps[i], BUS_DMASYNC_POSTREAD);
1170227347Syongari		bus_dmamap_unload(sc->ti_mbufrx_dmat,
1171227347Syongari		    sc->ti_cdata.ti_rx_std_maps[i]);
117245386Swpaul	}
117345386Swpaul
1174227347Syongari	map = sc->ti_cdata.ti_rx_std_maps[i];
1175227347Syongari	sc->ti_cdata.ti_rx_std_maps[i] = sc->ti_cdata.ti_rx_std_sparemap;
1176227347Syongari	sc->ti_cdata.ti_rx_std_sparemap = map;
1177227347Syongari	sc->ti_cdata.ti_rx_std_chain[i] = m;
1178227347Syongari
117945386Swpaul	r = &sc->ti_rdata->ti_rx_std_ring[i];
1180227347Syongari	ti_hostaddr64(&r->ti_addr, segs[0].ds_addr);
1181227347Syongari	r->ti_len = segs[0].ds_len;
118245386Swpaul	r->ti_type = TI_BDTYPE_RECV_BD;
118345386Swpaul	r->ti_flags = 0;
1184227347Syongari	r->ti_vlan_tag = 0;
1185227347Syongari	r->ti_tcp_udp_cksum = 0;
1186227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
118758698Sjlemon		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
118845386Swpaul	r->ti_idx = i;
118945386Swpaul
1190227347Syongari	bus_dmamap_sync(sc->ti_mbufrx_dmat, sc->ti_cdata.ti_rx_std_maps[i],
1191227347Syongari	    BUS_DMASYNC_PREREAD);
1192131654Sbms	return (0);
119345386Swpaul}
119445386Swpaul
119545386Swpaul/*
119645386Swpaul * Intialize a mini receive ring descriptor. This only applies to
119745386Swpaul * the Tigon 2.
119845386Swpaul */
1199102336Salfredstatic int
1200227347Syongariti_newbuf_mini(struct ti_softc *sc, int i)
120145386Swpaul{
1202227087Syongari	bus_dmamap_t map;
1203227347Syongari	bus_dma_segment_t segs[1];
1204227347Syongari	struct mbuf *m;
1205227087Syongari	struct ti_rx_desc *r;
1206227347Syongari	int error, nsegs;
120745386Swpaul
1208227347Syongari	MGETHDR(m, M_DONTWAIT, MT_DATA);
1209227347Syongari	if (m == NULL)
1210227347Syongari		return (ENOBUFS);
1211227347Syongari	m->m_len = m->m_pkthdr.len = MHLEN;
1212227347Syongari	m_adj(m, ETHER_ALIGN);
1213227347Syongari
1214227347Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_mbufrx_dmat,
1215227347Syongari	    sc->ti_cdata.ti_rx_mini_sparemap, m, segs, &nsegs, 0);
1216227347Syongari	if (error != 0) {
1217227347Syongari		m_freem(m);
1218227347Syongari		return (error);
1219227347Syongari        }
1220227347Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
1221227347Syongari
1222227347Syongari	if (sc->ti_cdata.ti_rx_mini_chain[i] != NULL) {
1223227347Syongari		bus_dmamap_sync(sc->ti_mbufrx_dmat,
1224227347Syongari		    sc->ti_cdata.ti_rx_mini_maps[i], BUS_DMASYNC_POSTREAD);
1225227347Syongari		bus_dmamap_unload(sc->ti_mbufrx_dmat,
1226227347Syongari		    sc->ti_cdata.ti_rx_mini_maps[i]);
122745386Swpaul	}
122849036Swpaul
1229227347Syongari	map = sc->ti_cdata.ti_rx_mini_maps[i];
1230227347Syongari	sc->ti_cdata.ti_rx_mini_maps[i] = sc->ti_cdata.ti_rx_mini_sparemap;
1231227347Syongari	sc->ti_cdata.ti_rx_mini_sparemap = map;
1232227347Syongari	sc->ti_cdata.ti_rx_mini_chain[i] = m;
1233227347Syongari
123445386Swpaul	r = &sc->ti_rdata->ti_rx_mini_ring[i];
1235227347Syongari	ti_hostaddr64(&r->ti_addr, segs[0].ds_addr);
1236227347Syongari	r->ti_len = segs[0].ds_len;
123745386Swpaul	r->ti_type = TI_BDTYPE_RECV_BD;
123845386Swpaul	r->ti_flags = TI_BDFLAG_MINI_RING;
1239227347Syongari	r->ti_vlan_tag = 0;
1240227347Syongari	r->ti_tcp_udp_cksum = 0;
1241227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
124258698Sjlemon		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
124345386Swpaul	r->ti_idx = i;
124445386Swpaul
1245227347Syongari	bus_dmamap_sync(sc->ti_mbufrx_dmat, sc->ti_cdata.ti_rx_mini_maps[i],
1246227347Syongari	    BUS_DMASYNC_PREREAD);
1247131654Sbms	return (0);
124845386Swpaul}
124945386Swpaul
1250227347Syongari#ifndef TI_SF_BUF_JUMBO
125198849Sken
125245386Swpaul/*
125345386Swpaul * Initialize a jumbo receive ring descriptor. This allocates
125445386Swpaul * a jumbo buffer from the pool managed internally by the driver.
125545386Swpaul */
1256102336Salfredstatic int
1257227347Syongariti_newbuf_jumbo(struct ti_softc *sc, int i, struct mbuf *dummy)
125845386Swpaul{
1259227087Syongari	bus_dmamap_t map;
1260227347Syongari	bus_dma_segment_t segs[1];
1261227347Syongari	struct mbuf *m;
1262227087Syongari	struct ti_rx_desc *r;
1263227347Syongari	int error, nsegs;
126445386Swpaul
1265227347Syongari	(void)dummy;
126645386Swpaul
1267227347Syongari	m = m_getjcl(M_DONTWAIT, MT_DATA, M_PKTHDR, MJUM9BYTES);
1268227347Syongari	if (m == NULL)
1269227347Syongari		return (ENOBUFS);
1270227347Syongari	m->m_len = m->m_pkthdr.len = MJUM9BYTES;
1271227347Syongari	m_adj(m, ETHER_ALIGN);
127245386Swpaul
1273227347Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_jumbo_dmat,
1274227347Syongari	    sc->ti_cdata.ti_rx_jumbo_sparemap, m, segs, &nsegs, 0);
1275227347Syongari	if (error != 0) {
1276227347Syongari		m_freem(m);
1277227347Syongari		return (error);
1278227347Syongari        }
1279227347Syongari	KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs));
128045386Swpaul
1281227347Syongari	if (sc->ti_cdata.ti_rx_jumbo_chain[i] != NULL) {
1282227347Syongari		bus_dmamap_sync(sc->ti_jumbo_dmat,
1283227347Syongari		    sc->ti_cdata.ti_rx_jumbo_maps[i], BUS_DMASYNC_POSTREAD);
1284227347Syongari		bus_dmamap_unload(sc->ti_jumbo_dmat,
1285227347Syongari		    sc->ti_cdata.ti_rx_jumbo_maps[i]);
128645386Swpaul	}
128745386Swpaul
1288227347Syongari	map = sc->ti_cdata.ti_rx_jumbo_maps[i];
1289227347Syongari	sc->ti_cdata.ti_rx_jumbo_maps[i] = sc->ti_cdata.ti_rx_jumbo_sparemap;
1290227347Syongari	sc->ti_cdata.ti_rx_jumbo_sparemap = map;
1291227347Syongari	sc->ti_cdata.ti_rx_jumbo_chain[i] = m;
1292227347Syongari
129345386Swpaul	r = &sc->ti_rdata->ti_rx_jumbo_ring[i];
1294227347Syongari	ti_hostaddr64(&r->ti_addr, segs[0].ds_addr);
1295227347Syongari	r->ti_len = segs[0].ds_len;
129645386Swpaul	r->ti_type = TI_BDTYPE_RECV_JUMBO_BD;
129745386Swpaul	r->ti_flags = TI_BDFLAG_JUMBO_RING;
1298227347Syongari	r->ti_vlan_tag = 0;
1299227347Syongari	r->ti_tcp_udp_cksum = 0;
1300227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
130158698Sjlemon		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
130245386Swpaul	r->ti_idx = i;
130345386Swpaul
1304227347Syongari	bus_dmamap_sync(sc->ti_jumbo_dmat, sc->ti_cdata.ti_rx_jumbo_maps[i],
1305227347Syongari	    BUS_DMASYNC_PREREAD);
1306131654Sbms	return (0);
130745386Swpaul}
130845386Swpaul
130998849Sken#else
131098849Sken
131198849Sken#if (PAGE_SIZE == 4096)
131298849Sken#define NPAYLOAD 2
131398849Sken#else
131498849Sken#define NPAYLOAD 1
1315131652Sbms#endif
131698849Sken
131798849Sken#define TCP_HDR_LEN (52 + sizeof(struct ether_header))
131898849Sken#define UDP_HDR_LEN (28 + sizeof(struct ether_header))
131998849Sken#define NFS_HDR_LEN (UDP_HDR_LEN)
1320227087Syongaristatic int HDR_LEN = TCP_HDR_LEN;
132198849Sken
1322131655Sbms/*
1323131655Sbms * Initialize a jumbo receive ring descriptor. This allocates
1324131655Sbms * a jumbo buffer from the pool managed internally by the driver.
1325131655Sbms */
132698849Skenstatic int
1327227086Syongariti_newbuf_jumbo(struct ti_softc *sc, int idx, struct mbuf *m_old)
132898849Sken{
1329227087Syongari	bus_dmamap_t map;
1330227087Syongari	struct mbuf *cur, *m_new = NULL;
1331227087Syongari	struct mbuf *m[3] = {NULL, NULL, NULL};
1332227087Syongari	struct ti_rx_desc_ext *r;
1333227087Syongari	vm_page_t frame;
1334227087Syongari	static int color;
1335227087Syongari	/* 1 extra buf to make nobufs easy*/
1336227087Syongari	struct sf_buf *sf[3] = {NULL, NULL, NULL};
1337227087Syongari	int i;
1338227087Syongari	bus_dma_segment_t segs[4];
1339227087Syongari	int nsegs;
134098849Sken
134198849Sken	if (m_old != NULL) {
134298849Sken		m_new = m_old;
134398849Sken		cur = m_old->m_next;
134498849Sken		for (i = 0; i <= NPAYLOAD; i++){
134598849Sken			m[i] = cur;
134698849Sken			cur = cur->m_next;
134798849Sken		}
134898849Sken	} else {
134998849Sken		/* Allocate the mbufs. */
1350111119Simp		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
135198849Sken		if (m_new == NULL) {
1352162321Sglebius			device_printf(sc->ti_dev, "mbuf allocation failed "
1353150719Sjhb			    "-- packet dropped!\n");
135498849Sken			goto nobufs;
135598849Sken		}
1356111119Simp		MGET(m[NPAYLOAD], M_DONTWAIT, MT_DATA);
135798849Sken		if (m[NPAYLOAD] == NULL) {
1358162321Sglebius			device_printf(sc->ti_dev, "cluster mbuf allocation "
1359162321Sglebius			    "failed -- packet dropped!\n");
136098849Sken			goto nobufs;
136198849Sken		}
1362111119Simp		MCLGET(m[NPAYLOAD], M_DONTWAIT);
136398849Sken		if ((m[NPAYLOAD]->m_flags & M_EXT) == 0) {
1364162321Sglebius			device_printf(sc->ti_dev, "mbuf allocation failed "
1365150719Sjhb			    "-- packet dropped!\n");
136698849Sken			goto nobufs;
136798849Sken		}
136898849Sken		m[NPAYLOAD]->m_len = MCLBYTES;
136998849Sken
137098849Sken		for (i = 0; i < NPAYLOAD; i++){
1371111119Simp			MGET(m[i], M_DONTWAIT, MT_DATA);
137298849Sken			if (m[i] == NULL) {
1373162321Sglebius				device_printf(sc->ti_dev, "mbuf allocation "
1374162321Sglebius				    "failed -- packet dropped!\n");
137598849Sken				goto nobufs;
137698849Sken			}
1377138424Salc			frame = vm_page_alloc(NULL, color++,
1378138424Salc			    VM_ALLOC_INTERRUPT | VM_ALLOC_NOOBJ |
1379138424Salc			    VM_ALLOC_WIRED);
1380138424Salc			if (frame == NULL) {
1381162321Sglebius				device_printf(sc->ti_dev, "buffer allocation "
1382150719Sjhb				    "failed -- packet dropped!\n");
138398849Sken				printf("      index %d page %d\n", idx, i);
1384131655Sbms				goto nobufs;
138598849Sken			}
1386138424Salc			sf[i] = sf_buf_alloc(frame, SFB_NOWAIT);
1387138424Salc			if (sf[i] == NULL) {
1388138424Salc				vm_page_unwire(frame, 0);
1389138424Salc				vm_page_free(frame);
1390162321Sglebius				device_printf(sc->ti_dev, "buffer allocation "
1391150719Sjhb				    "failed -- packet dropped!\n");
1392138424Salc				printf("      index %d page %d\n", idx, i);
1393138424Salc				goto nobufs;
1394138424Salc			}
139598849Sken		}
139698849Sken		for (i = 0; i < NPAYLOAD; i++){
1397131655Sbms		/* Attach the buffer to the mbuf. */
1398138424Salc			m[i]->m_data = (void *)sf_buf_kva(sf[i]);
139998849Sken			m[i]->m_len = PAGE_SIZE;
1400138424Salc			MEXTADD(m[i], sf_buf_kva(sf[i]), PAGE_SIZE,
1401175872Sphk			    sf_buf_mext, (void*)sf_buf_kva(sf[i]), sf[i],
1402175872Sphk			    0, EXT_DISPOSABLE);
140398849Sken			m[i]->m_next = m[i+1];
140498849Sken		}
140598849Sken		/* link the buffers to the header */
140698849Sken		m_new->m_next = m[0];
140798849Sken		m_new->m_data += ETHER_ALIGN;
140898849Sken		if (sc->ti_hdrsplit)
140998849Sken			m_new->m_len = MHLEN - ETHER_ALIGN;
141098849Sken		else
1411131655Sbms			m_new->m_len = HDR_LEN;
141298849Sken		m_new->m_pkthdr.len = NPAYLOAD * PAGE_SIZE + m_new->m_len;
141398849Sken	}
141498849Sken
141598849Sken	/* Set up the descriptor. */
141698849Sken	r = &sc->ti_rdata->ti_rx_jumbo_ring[idx];
141798849Sken	sc->ti_cdata.ti_rx_jumbo_chain[idx] = m_new;
1418153396Sscottl	map = sc->ti_cdata.ti_rx_jumbo_maps[i];
1419153396Sscottl	if (bus_dmamap_load_mbuf_sg(sc->ti_jumbo_dmat, map, m_new, segs,
1420153396Sscottl				    &nsegs, 0))
1421153396Sscottl		return (ENOBUFS);
1422153396Sscottl	if ((nsegs < 1) || (nsegs > 4))
1423153396Sscottl		return (ENOBUFS);
1424153396Sscottl	ti_hostaddr64(&r->ti_addr0, segs[0].ds_addr);
142598849Sken	r->ti_len0 = m_new->m_len;
142698849Sken
1427153396Sscottl	ti_hostaddr64(&r->ti_addr1, segs[1].ds_addr);
142898849Sken	r->ti_len1 = PAGE_SIZE;
142998849Sken
1430153396Sscottl	ti_hostaddr64(&r->ti_addr2, segs[2].ds_addr);
143198849Sken	r->ti_len2 = m[1]->m_ext.ext_size; /* could be PAGE_SIZE or MCLBYTES */
143298849Sken
143398849Sken	if (PAGE_SIZE == 4096) {
1434153396Sscottl		ti_hostaddr64(&r->ti_addr3, segs[3].ds_addr);
143598849Sken		r->ti_len3 = MCLBYTES;
143698849Sken	} else {
143798849Sken		r->ti_len3 = 0;
143898849Sken	}
1439131655Sbms	r->ti_type = TI_BDTYPE_RECV_JUMBO_BD;
144098849Sken
1441131655Sbms	r->ti_flags = TI_BDFLAG_JUMBO_RING|TI_RCB_FLAG_USE_EXT_RX_BD;
144298849Sken
1443227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
144498849Sken		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM|TI_BDFLAG_IP_CKSUM;
144598849Sken
1446131655Sbms	r->ti_idx = idx;
144798849Sken
1448153396Sscottl	bus_dmamap_sync(sc->ti_jumbo_dmat, map, BUS_DMASYNC_PREREAD);
1449131655Sbms	return (0);
145098849Sken
1451131655Sbmsnobufs:
145298849Sken
145398849Sken	/*
145498849Sken	 * Warning! :
145598849Sken	 * This can only be called before the mbufs are strung together.
1456131652Sbms	 * If the mbufs are strung together, m_freem() will free the chain,
145798849Sken	 * so that the later mbufs will be freed multiple times.
145898849Sken	 */
1459131655Sbms	if (m_new)
1460131655Sbms		m_freem(m_new);
146198849Sken
1462131655Sbms	for (i = 0; i < 3; i++) {
1463131655Sbms		if (m[i])
1464131655Sbms			m_freem(m[i]);
1465138424Salc		if (sf[i])
1466138424Salc			sf_buf_mext((void *)sf_buf_kva(sf[i]), sf[i]);
1467131655Sbms	}
1468131655Sbms	return (ENOBUFS);
146998849Sken}
147098849Sken#endif
147198849Sken
147245386Swpaul/*
147345386Swpaul * The standard receive ring has 512 entries in it. At 2K per mbuf cluster,
147445386Swpaul * that's 1MB or memory, which is a lot. For now, we fill only the first
147545386Swpaul * 256 ring entries and hope that our CPU is fast enough to keep up with
147645386Swpaul * the NIC.
147745386Swpaul */
1478102336Salfredstatic int
1479227086Syongariti_init_rx_ring_std(struct ti_softc *sc)
148045386Swpaul{
1481227087Syongari	int i;
1482227087Syongari	struct ti_cmd_desc cmd;
148345386Swpaul
1484227347Syongari	for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
1485227347Syongari		if (ti_newbuf_std(sc, i) != 0)
1486131654Sbms			return (ENOBUFS);
148745386Swpaul	};
148845386Swpaul
1489227347Syongari	sc->ti_std = TI_STD_RX_RING_CNT - 1;
1490227347Syongari	TI_UPDATE_STDPROD(sc, TI_STD_RX_RING_CNT - 1);
149145386Swpaul
1492131654Sbms	return (0);
149345386Swpaul}
149445386Swpaul
1495102336Salfredstatic void
1496227086Syongariti_free_rx_ring_std(struct ti_softc *sc)
149745386Swpaul{
1498227087Syongari	bus_dmamap_t map;
1499227087Syongari	int i;
150045386Swpaul
150145386Swpaul	for (i = 0; i < TI_STD_RX_RING_CNT; i++) {
150245386Swpaul		if (sc->ti_cdata.ti_rx_std_chain[i] != NULL) {
1503153770Syongari			map = sc->ti_cdata.ti_rx_std_maps[i];
1504153770Syongari			bus_dmamap_sync(sc->ti_mbufrx_dmat, map,
1505153770Syongari			    BUS_DMASYNC_POSTREAD);
1506153770Syongari			bus_dmamap_unload(sc->ti_mbufrx_dmat, map);
150745386Swpaul			m_freem(sc->ti_cdata.ti_rx_std_chain[i]);
150845386Swpaul			sc->ti_cdata.ti_rx_std_chain[i] = NULL;
150945386Swpaul		}
151045386Swpaul		bzero((char *)&sc->ti_rdata->ti_rx_std_ring[i],
151145386Swpaul		    sizeof(struct ti_rx_desc));
151245386Swpaul	}
151345386Swpaul}
151445386Swpaul
1515102336Salfredstatic int
1516227086Syongariti_init_rx_ring_jumbo(struct ti_softc *sc)
151745386Swpaul{
1518227087Syongari	struct ti_cmd_desc cmd;
1519227087Syongari	int i;
152045386Swpaul
152163699Swpaul	for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
1522227347Syongari		if (ti_newbuf_jumbo(sc, i, NULL) != 0)
1523131654Sbms			return (ENOBUFS);
152445386Swpaul	};
152545386Swpaul
1526227347Syongari	sc->ti_jumbo = TI_JUMBO_RX_RING_CNT - 1;
1527227347Syongari	TI_UPDATE_JUMBOPROD(sc, TI_JUMBO_RX_RING_CNT - 1);
152845386Swpaul
1529131654Sbms	return (0);
153045386Swpaul}
153145386Swpaul
1532102336Salfredstatic void
1533227086Syongariti_free_rx_ring_jumbo(struct ti_softc *sc)
153445386Swpaul{
1535227087Syongari	bus_dmamap_t map;
1536227087Syongari	int i;
153745386Swpaul
153845386Swpaul	for (i = 0; i < TI_JUMBO_RX_RING_CNT; i++) {
153945386Swpaul		if (sc->ti_cdata.ti_rx_jumbo_chain[i] != NULL) {
1540153770Syongari			map = sc->ti_cdata.ti_rx_jumbo_maps[i];
1541153770Syongari			bus_dmamap_sync(sc->ti_jumbo_dmat, map,
1542153770Syongari			    BUS_DMASYNC_POSTREAD);
1543153770Syongari			bus_dmamap_unload(sc->ti_jumbo_dmat, map);
154445386Swpaul			m_freem(sc->ti_cdata.ti_rx_jumbo_chain[i]);
154545386Swpaul			sc->ti_cdata.ti_rx_jumbo_chain[i] = NULL;
154645386Swpaul		}
154745386Swpaul		bzero((char *)&sc->ti_rdata->ti_rx_jumbo_ring[i],
154845386Swpaul		    sizeof(struct ti_rx_desc));
154945386Swpaul	}
155045386Swpaul}
155145386Swpaul
1552102336Salfredstatic int
1553227086Syongariti_init_rx_ring_mini(struct ti_softc *sc)
155445386Swpaul{
1555227087Syongari	int i;
155645386Swpaul
1557227347Syongari	for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
1558227347Syongari		if (ti_newbuf_mini(sc, i) != 0)
1559131654Sbms			return (ENOBUFS);
156045386Swpaul	};
156145386Swpaul
1562227347Syongari	sc->ti_mini = TI_MINI_RX_RING_CNT - 1;
1563227347Syongari	TI_UPDATE_MINIPROD(sc, TI_MINI_RX_RING_CNT - 1);
156445386Swpaul
1565131654Sbms	return (0);
156645386Swpaul}
156745386Swpaul
1568102336Salfredstatic void
1569227086Syongariti_free_rx_ring_mini(struct ti_softc *sc)
157045386Swpaul{
1571227087Syongari	bus_dmamap_t map;
1572227087Syongari	int i;
157345386Swpaul
157445386Swpaul	for (i = 0; i < TI_MINI_RX_RING_CNT; i++) {
157545386Swpaul		if (sc->ti_cdata.ti_rx_mini_chain[i] != NULL) {
1576153770Syongari			map = sc->ti_cdata.ti_rx_mini_maps[i];
1577153770Syongari			bus_dmamap_sync(sc->ti_mbufrx_dmat, map,
1578153770Syongari			    BUS_DMASYNC_POSTREAD);
1579153770Syongari			bus_dmamap_unload(sc->ti_mbufrx_dmat, map);
158045386Swpaul			m_freem(sc->ti_cdata.ti_rx_mini_chain[i]);
158145386Swpaul			sc->ti_cdata.ti_rx_mini_chain[i] = NULL;
158245386Swpaul		}
158345386Swpaul		bzero((char *)&sc->ti_rdata->ti_rx_mini_ring[i],
158445386Swpaul		    sizeof(struct ti_rx_desc));
158545386Swpaul	}
158645386Swpaul}
158745386Swpaul
1588102336Salfredstatic void
1589227086Syongariti_free_tx_ring(struct ti_softc *sc)
159045386Swpaul{
1591227087Syongari	struct ti_txdesc *txd;
1592227087Syongari	int i;
159345386Swpaul
159445386Swpaul	if (sc->ti_rdata->ti_tx_ring == NULL)
159545386Swpaul		return;
159645386Swpaul
159745386Swpaul	for (i = 0; i < TI_TX_RING_CNT; i++) {
1598153982Syongari		txd = &sc->ti_cdata.ti_txdesc[i];
1599153982Syongari		if (txd->tx_m != NULL) {
1600153982Syongari			bus_dmamap_sync(sc->ti_mbuftx_dmat, txd->tx_dmamap,
1601153770Syongari			    BUS_DMASYNC_POSTWRITE);
1602153982Syongari			bus_dmamap_unload(sc->ti_mbuftx_dmat, txd->tx_dmamap);
1603153982Syongari			m_freem(txd->tx_m);
1604153982Syongari			txd->tx_m = NULL;
160545386Swpaul		}
160645386Swpaul		bzero((char *)&sc->ti_rdata->ti_tx_ring[i],
160745386Swpaul		    sizeof(struct ti_tx_desc));
160845386Swpaul	}
160945386Swpaul}
161045386Swpaul
1611102336Salfredstatic int
1612227086Syongariti_init_tx_ring(struct ti_softc *sc)
161345386Swpaul{
1614227087Syongari	struct ti_txdesc *txd;
1615227087Syongari	int i;
1616153982Syongari
1617153982Syongari	STAILQ_INIT(&sc->ti_cdata.ti_txfreeq);
1618153982Syongari	STAILQ_INIT(&sc->ti_cdata.ti_txbusyq);
1619153982Syongari	for (i = 0; i < TI_TX_RING_CNT; i++) {
1620153982Syongari		txd = &sc->ti_cdata.ti_txdesc[i];
1621153982Syongari		STAILQ_INSERT_TAIL(&sc->ti_cdata.ti_txfreeq, txd, tx_q);
1622153982Syongari	}
162348011Swpaul	sc->ti_txcnt = 0;
162445386Swpaul	sc->ti_tx_saved_considx = 0;
1625153778Sscottl	sc->ti_tx_saved_prodidx = 0;
162645386Swpaul	CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, 0);
1627131654Sbms	return (0);
162845386Swpaul}
162945386Swpaul
163045386Swpaul/*
163145386Swpaul * The Tigon 2 firmware has a new way to add/delete multicast addresses,
163245386Swpaul * but we have to support the old way too so that Tigon 1 cards will
163345386Swpaul * work.
163445386Swpaul */
1635105219Sphkstatic void
1636227086Syongariti_add_mcast(struct ti_softc *sc, struct ether_addr *addr)
163745386Swpaul{
1638227087Syongari	struct ti_cmd_desc cmd;
1639227089Syongari	uint16_t *m;
1640227089Syongari	uint32_t ext[2] = {0, 0};
164145386Swpaul
1642227089Syongari	m = (uint16_t *)&addr->octet[0];
164345386Swpaul
1644131654Sbms	switch (sc->ti_hwrev) {
164545386Swpaul	case TI_HWREV_TIGON:
164645386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR0, htons(m[0]));
164745386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR1, (htons(m[1]) << 16) | htons(m[2]));
164845386Swpaul		TI_DO_CMD(TI_CMD_ADD_MCAST_ADDR, 0, 0);
164945386Swpaul		break;
165045386Swpaul	case TI_HWREV_TIGON_II:
165145386Swpaul		ext[0] = htons(m[0]);
165245386Swpaul		ext[1] = (htons(m[1]) << 16) | htons(m[2]);
165345386Swpaul		TI_DO_CMD_EXT(TI_CMD_EXT_ADD_MCAST, 0, 0, (caddr_t)&ext, 2);
165445386Swpaul		break;
165545386Swpaul	default:
1656162321Sglebius		device_printf(sc->ti_dev, "unknown hwrev\n");
165745386Swpaul		break;
165845386Swpaul	}
165945386Swpaul}
166045386Swpaul
1661105219Sphkstatic void
1662227086Syongariti_del_mcast(struct ti_softc *sc, struct ether_addr *addr)
166345386Swpaul{
1664227087Syongari	struct ti_cmd_desc cmd;
1665227089Syongari	uint16_t *m;
1666227089Syongari	uint32_t ext[2] = {0, 0};
166745386Swpaul
1668227089Syongari	m = (uint16_t *)&addr->octet[0];
166945386Swpaul
1670131654Sbms	switch (sc->ti_hwrev) {
167145386Swpaul	case TI_HWREV_TIGON:
167245386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR0, htons(m[0]));
167345386Swpaul		CSR_WRITE_4(sc, TI_GCR_MAR1, (htons(m[1]) << 16) | htons(m[2]));
167445386Swpaul		TI_DO_CMD(TI_CMD_DEL_MCAST_ADDR, 0, 0);
167545386Swpaul		break;
167645386Swpaul	case TI_HWREV_TIGON_II:
167745386Swpaul		ext[0] = htons(m[0]);
167845386Swpaul		ext[1] = (htons(m[1]) << 16) | htons(m[2]);
167945386Swpaul		TI_DO_CMD_EXT(TI_CMD_EXT_DEL_MCAST, 0, 0, (caddr_t)&ext, 2);
168045386Swpaul		break;
168145386Swpaul	default:
1682162321Sglebius		device_printf(sc->ti_dev, "unknown hwrev\n");
168345386Swpaul		break;
168445386Swpaul	}
168545386Swpaul}
168645386Swpaul
168745386Swpaul/*
168845386Swpaul * Configure the Tigon's multicast address filter.
168945386Swpaul *
169045386Swpaul * The actual multicast table management is a bit of a pain, thanks to
169145386Swpaul * slight brain damage on the part of both Alteon and us. With our
169245386Swpaul * multicast code, we are only alerted when the multicast address table
169345386Swpaul * changes and at that point we only have the current list of addresses:
169445386Swpaul * we only know the current state, not the previous state, so we don't
169545386Swpaul * actually know what addresses were removed or added. The firmware has
169645386Swpaul * state, but we can't get our grubby mits on it, and there is no 'delete
169745386Swpaul * all multicast addresses' command. Hence, we have to maintain our own
169845386Swpaul * state so we know what addresses have been programmed into the NIC at
169945386Swpaul * any given time.
170045386Swpaul */
1701102336Salfredstatic void
1702227086Syongariti_setmulti(struct ti_softc *sc)
170345386Swpaul{
1704227087Syongari	struct ifnet *ifp;
1705227087Syongari	struct ifmultiaddr *ifma;
1706227087Syongari	struct ti_cmd_desc cmd;
1707227087Syongari	struct ti_mc_entry *mc;
1708227089Syongari	uint32_t intrs;
170945386Swpaul
1710153770Syongari	TI_LOCK_ASSERT(sc);
1711153770Syongari
1712147256Sbrooks	ifp = sc->ti_ifp;
171345386Swpaul
171445386Swpaul	if (ifp->if_flags & IFF_ALLMULTI) {
171545386Swpaul		TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_ENB, 0);
171645386Swpaul		return;
171745386Swpaul	} else {
171845386Swpaul		TI_DO_CMD(TI_CMD_SET_ALLMULTI, TI_CMD_CODE_ALLMULTI_DIS, 0);
171945386Swpaul	}
172045386Swpaul
172145386Swpaul	/* Disable interrupts. */
172245386Swpaul	intrs = CSR_READ_4(sc, TI_MB_HOSTINTR);
172345386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
172445386Swpaul
172545386Swpaul	/* First, zot all the existing filters. */
172671999Sphk	while (SLIST_FIRST(&sc->ti_mc_listhead) != NULL) {
172771999Sphk		mc = SLIST_FIRST(&sc->ti_mc_listhead);
172845386Swpaul		ti_del_mcast(sc, &mc->mc_addr);
172945386Swpaul		SLIST_REMOVE_HEAD(&sc->ti_mc_listhead, mc_entries);
173045386Swpaul		free(mc, M_DEVBUF);
173145386Swpaul	}
173245386Swpaul
173345386Swpaul	/* Now program new ones. */
1734195049Srwatson	if_maddr_rlock(ifp);
173572084Sphk	TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
173645386Swpaul		if (ifma->ifma_addr->sa_family != AF_LINK)
173745386Swpaul			continue;
173845386Swpaul		mc = malloc(sizeof(struct ti_mc_entry), M_DEVBUF, M_NOWAIT);
1739144165Ssam		if (mc == NULL) {
1740162321Sglebius			device_printf(sc->ti_dev,
1741162321Sglebius			    "no memory for mcast filter entry\n");
1742144165Ssam			continue;
1743144165Ssam		}
174445386Swpaul		bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),
174545386Swpaul		    (char *)&mc->mc_addr, ETHER_ADDR_LEN);
174645386Swpaul		SLIST_INSERT_HEAD(&sc->ti_mc_listhead, mc, mc_entries);
174745386Swpaul		ti_add_mcast(sc, &mc->mc_addr);
174845386Swpaul	}
1749195049Srwatson	if_maddr_runlock(ifp);
175045386Swpaul
175145386Swpaul	/* Re-enable interrupts. */
175245386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, intrs);
175345386Swpaul}
175445386Swpaul
175545386Swpaul/*
175645386Swpaul * Check to see if the BIOS has configured us for a 64 bit slot when
175745386Swpaul * we aren't actually in one. If we detect this condition, we can work
175845386Swpaul * around it on the Tigon 2 by setting a bit in the PCI state register,
175945386Swpaul * but for the Tigon 1 we must give up and abort the interface attach.
176045386Swpaul */
1761227431Syongaristatic int
1762227431Syongariti_64bitslot_war(struct ti_softc *sc)
176345386Swpaul{
1764227087Syongari
176545386Swpaul	if (!(CSR_READ_4(sc, TI_PCI_STATE) & TI_PCISTATE_32BIT_BUS)) {
176645386Swpaul		CSR_WRITE_4(sc, 0x600, 0);
176745386Swpaul		CSR_WRITE_4(sc, 0x604, 0);
176845386Swpaul		CSR_WRITE_4(sc, 0x600, 0x5555AAAA);
176945386Swpaul		if (CSR_READ_4(sc, 0x604) == 0x5555AAAA) {
177045386Swpaul			if (sc->ti_hwrev == TI_HWREV_TIGON)
1771131654Sbms				return (EINVAL);
177245386Swpaul			else {
177345386Swpaul				TI_SETBIT(sc, TI_PCI_STATE,
177445386Swpaul				    TI_PCISTATE_32BIT_BUS);
1775131654Sbms				return (0);
177645386Swpaul			}
177745386Swpaul		}
177845386Swpaul	}
177945386Swpaul
1780131654Sbms	return (0);
178145386Swpaul}
178245386Swpaul
178345386Swpaul/*
178445386Swpaul * Do endian, PCI and DMA initialization. Also check the on-board ROM
178545386Swpaul * self-test results.
178645386Swpaul */
1787102336Salfredstatic int
1788227086Syongariti_chipinit(struct ti_softc *sc)
178945386Swpaul{
1790227089Syongari	uint32_t cacheline;
1791227089Syongari	uint32_t pci_writemax = 0;
1792227089Syongari	uint32_t hdrsplit;
179345386Swpaul
179445386Swpaul	/* Initialize link to down state. */
179545386Swpaul	sc->ti_linkstat = TI_EV_CODE_LINK_DOWN;
179645386Swpaul
179745386Swpaul	/* Set endianness before we access any non-PCI registers. */
1798153770Syongari#if 0 && BYTE_ORDER == BIG_ENDIAN
179945386Swpaul	CSR_WRITE_4(sc, TI_MISC_HOST_CTL,
180045386Swpaul	    TI_MHC_BIGENDIAN_INIT | (TI_MHC_BIGENDIAN_INIT << 24));
180145386Swpaul#else
180245386Swpaul	CSR_WRITE_4(sc, TI_MISC_HOST_CTL,
180345386Swpaul	    TI_MHC_LITTLEENDIAN_INIT | (TI_MHC_LITTLEENDIAN_INIT << 24));
180445386Swpaul#endif
180545386Swpaul
180645386Swpaul	/* Check the ROM failed bit to see if self-tests passed. */
180745386Swpaul	if (CSR_READ_4(sc, TI_CPU_STATE) & TI_CPUSTATE_ROMFAIL) {
1808162321Sglebius		device_printf(sc->ti_dev, "board self-diagnostics failed!\n");
1809131654Sbms		return (ENODEV);
181045386Swpaul	}
181145386Swpaul
181245386Swpaul	/* Halt the CPU. */
181345386Swpaul	TI_SETBIT(sc, TI_CPU_STATE, TI_CPUSTATE_HALT);
181445386Swpaul
181545386Swpaul	/* Figure out the hardware revision. */
1816131654Sbms	switch (CSR_READ_4(sc, TI_MISC_HOST_CTL) & TI_MHC_CHIP_REV_MASK) {
181745386Swpaul	case TI_REV_TIGON_I:
181845386Swpaul		sc->ti_hwrev = TI_HWREV_TIGON;
181945386Swpaul		break;
182045386Swpaul	case TI_REV_TIGON_II:
182145386Swpaul		sc->ti_hwrev = TI_HWREV_TIGON_II;
182245386Swpaul		break;
182345386Swpaul	default:
1824162321Sglebius		device_printf(sc->ti_dev, "unsupported chip revision\n");
1825131654Sbms		return (ENODEV);
182645386Swpaul	}
182745386Swpaul
182845386Swpaul	/* Do special setup for Tigon 2. */
182945386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON_II) {
183045386Swpaul		TI_SETBIT(sc, TI_CPU_CTL_B, TI_CPUSTATE_HALT);
183176033Swpaul		TI_SETBIT(sc, TI_MISC_LOCAL_CTL, TI_MLC_SRAM_BANK_512K);
183245386Swpaul		TI_SETBIT(sc, TI_MISC_CONF, TI_MCR_SRAM_SYNCHRONOUS);
183345386Swpaul	}
183445386Swpaul
183598849Sken	/*
183698849Sken	 * We don't have firmware source for the Tigon 1, so Tigon 1 boards
183798849Sken	 * can't do header splitting.
183898849Sken	 */
183998849Sken#ifdef TI_JUMBO_HDRSPLIT
184098849Sken	if (sc->ti_hwrev != TI_HWREV_TIGON)
184198849Sken		sc->ti_hdrsplit = 1;
184298849Sken	else
1843162321Sglebius		device_printf(sc->ti_dev,
1844150719Sjhb		    "can't do header splitting on a Tigon I board\n");
184598849Sken#endif /* TI_JUMBO_HDRSPLIT */
184698849Sken
184745386Swpaul	/* Set up the PCI state register. */
184845386Swpaul	CSR_WRITE_4(sc, TI_PCI_STATE, TI_PCI_READ_CMD|TI_PCI_WRITE_CMD);
184945386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON_II) {
185045386Swpaul		TI_SETBIT(sc, TI_PCI_STATE, TI_PCISTATE_USE_MEM_RD_MULT);
185145386Swpaul	}
185245386Swpaul
185345386Swpaul	/* Clear the read/write max DMA parameters. */
185445386Swpaul	TI_CLRBIT(sc, TI_PCI_STATE, (TI_PCISTATE_WRITE_MAXDMA|
185545386Swpaul	    TI_PCISTATE_READ_MAXDMA));
185645386Swpaul
185745386Swpaul	/* Get cache line size. */
185845386Swpaul	cacheline = CSR_READ_4(sc, TI_PCI_BIST) & 0xFF;
185945386Swpaul
186045386Swpaul	/*
186145386Swpaul	 * If the system has set enabled the PCI memory write
186245386Swpaul	 * and invalidate command in the command register, set
186345386Swpaul	 * the write max parameter accordingly. This is necessary
186445386Swpaul	 * to use MWI with the Tigon 2.
186545386Swpaul	 */
186645386Swpaul	if (CSR_READ_4(sc, TI_PCI_CMDSTAT) & PCIM_CMD_MWIEN) {
1867131654Sbms		switch (cacheline) {
186845386Swpaul		case 1:
186945386Swpaul		case 4:
187045386Swpaul		case 8:
187145386Swpaul		case 16:
187245386Swpaul		case 32:
187345386Swpaul		case 64:
187445386Swpaul			break;
187545386Swpaul		default:
187645386Swpaul		/* Disable PCI memory write and invalidate. */
187745386Swpaul			if (bootverbose)
1878162321Sglebius				device_printf(sc->ti_dev, "cache line size %d"
1879162321Sglebius				    " not supported; disabling PCI MWI\n",
1880150719Sjhb				    cacheline);
188145386Swpaul			CSR_WRITE_4(sc, TI_PCI_CMDSTAT, CSR_READ_4(sc,
188245386Swpaul			    TI_PCI_CMDSTAT) & ~PCIM_CMD_MWIEN);
188345386Swpaul			break;
188445386Swpaul		}
188545386Swpaul	}
188645386Swpaul
188745386Swpaul	TI_SETBIT(sc, TI_PCI_STATE, pci_writemax);
188845386Swpaul
188945386Swpaul	/* This sets the min dma param all the way up (0xff). */
189045386Swpaul	TI_SETBIT(sc, TI_PCI_STATE, TI_PCISTATE_MINDMA);
189145386Swpaul
189298849Sken	if (sc->ti_hdrsplit)
189398849Sken		hdrsplit = TI_OPMODE_JUMBO_HDRSPLIT;
189498849Sken	else
189598849Sken		hdrsplit = 0;
189698849Sken
189745386Swpaul	/* Configure DMA variables. */
189845386Swpaul#if BYTE_ORDER == BIG_ENDIAN
189945386Swpaul	CSR_WRITE_4(sc, TI_GCR_OPMODE, TI_OPMODE_BYTESWAP_BD |
190045386Swpaul	    TI_OPMODE_BYTESWAP_DATA | TI_OPMODE_WORDSWAP_BD |
190145386Swpaul	    TI_OPMODE_WARN_ENB | TI_OPMODE_FATAL_ENB |
190298849Sken	    TI_OPMODE_DONT_FRAG_JUMBO | hdrsplit);
190398849Sken#else /* BYTE_ORDER */
190445386Swpaul	CSR_WRITE_4(sc, TI_GCR_OPMODE, TI_OPMODE_BYTESWAP_DATA|
190545386Swpaul	    TI_OPMODE_WORDSWAP_BD|TI_OPMODE_DONT_FRAG_JUMBO|
190698849Sken	    TI_OPMODE_WARN_ENB|TI_OPMODE_FATAL_ENB | hdrsplit);
190798849Sken#endif /* BYTE_ORDER */
190845386Swpaul
190945386Swpaul	/*
191045386Swpaul	 * Only allow 1 DMA channel to be active at a time.
191145386Swpaul	 * I don't think this is a good idea, but without it
191245386Swpaul	 * the firmware racks up lots of nicDmaReadRingFull
191358698Sjlemon	 * errors.  This is not compatible with hardware checksums.
191445386Swpaul	 */
1915227095Syongari	if ((sc->ti_ifp->if_capenable & (IFCAP_TXCSUM | IFCAP_RXCSUM)) == 0)
191658698Sjlemon		TI_SETBIT(sc, TI_GCR_OPMODE, TI_OPMODE_1_DMA_ACTIVE);
191745386Swpaul
191845386Swpaul	/* Recommended settings from Tigon manual. */
191945386Swpaul	CSR_WRITE_4(sc, TI_GCR_DMA_WRITECFG, TI_DMA_STATE_THRESH_8W);
192045386Swpaul	CSR_WRITE_4(sc, TI_GCR_DMA_READCFG, TI_DMA_STATE_THRESH_8W);
192145386Swpaul
192245386Swpaul	if (ti_64bitslot_war(sc)) {
1923162321Sglebius		device_printf(sc->ti_dev, "bios thinks we're in a 64 bit slot, "
1924150719Sjhb		    "but we aren't");
1925131654Sbms		return (EINVAL);
192645386Swpaul	}
192745386Swpaul
1928131654Sbms	return (0);
192945386Swpaul}
193045386Swpaul
193145386Swpaul/*
193245386Swpaul * Initialize the general information block and firmware, and
193345386Swpaul * start the CPU(s) running.
193445386Swpaul */
1935102336Salfredstatic int
1936227086Syongariti_gibinit(struct ti_softc *sc)
193745386Swpaul{
1938227087Syongari	struct ifnet *ifp;
1939227087Syongari	struct ti_rcb *rcb;
1940227087Syongari	uint32_t rdphys;
1941227087Syongari	int i;
194245386Swpaul
1943153770Syongari	TI_LOCK_ASSERT(sc);
1944153770Syongari
1945147256Sbrooks	ifp = sc->ti_ifp;
1946143903Sscottl	rdphys = sc->ti_rdata_phys;
194745386Swpaul
194845386Swpaul	/* Disable interrupts for now. */
194945386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
195045386Swpaul
1951143903Sscottl	/*
1952143903Sscottl	 * Tell the chip where to find the general information block.
1953143903Sscottl	 * While this struct could go into >4GB memory, we allocate it in a
1954143903Sscottl	 * single slab with the other descriptors, and those don't seem to
1955143903Sscottl	 * support being located in a 64-bit region.
1956143903Sscottl	 */
195745386Swpaul	CSR_WRITE_4(sc, TI_GCR_GENINFO_HI, 0);
1958143903Sscottl	CSR_WRITE_4(sc, TI_GCR_GENINFO_LO, rdphys + TI_RD_OFF(ti_info));
195945386Swpaul
196045386Swpaul	/* Load the firmware into SRAM. */
196145386Swpaul	ti_loadfw(sc);
196245386Swpaul
196345386Swpaul	/* Set up the contents of the general info and ring control blocks. */
196445386Swpaul
196545386Swpaul	/* Set up the event ring and producer pointer. */
196645386Swpaul	rcb = &sc->ti_rdata->ti_info.ti_ev_rcb;
196745386Swpaul
1968143903Sscottl	TI_HOSTADDR(rcb->ti_hostaddr) = rdphys + TI_RD_OFF(ti_event_ring);
196945386Swpaul	rcb->ti_flags = 0;
197045386Swpaul	TI_HOSTADDR(sc->ti_rdata->ti_info.ti_ev_prodidx_ptr) =
1971143903Sscottl	    rdphys + TI_RD_OFF(ti_ev_prodidx_r);
197245386Swpaul	sc->ti_ev_prodidx.ti_idx = 0;
197345386Swpaul	CSR_WRITE_4(sc, TI_GCR_EVENTCONS_IDX, 0);
197445386Swpaul	sc->ti_ev_saved_considx = 0;
197545386Swpaul
197645386Swpaul	/* Set up the command ring and producer mailbox. */
197745386Swpaul	rcb = &sc->ti_rdata->ti_info.ti_cmd_rcb;
197845386Swpaul
197945386Swpaul	TI_HOSTADDR(rcb->ti_hostaddr) = TI_GCR_NIC_ADDR(TI_GCR_CMDRING);
198045386Swpaul	rcb->ti_flags = 0;
198145386Swpaul	rcb->ti_max_len = 0;
198245386Swpaul	for (i = 0; i < TI_CMD_RING_CNT; i++) {
198345386Swpaul		CSR_WRITE_4(sc, TI_GCR_CMDRING + (i * 4), 0);
198445386Swpaul	}
198545386Swpaul	CSR_WRITE_4(sc, TI_GCR_CMDCONS_IDX, 0);
198645386Swpaul	CSR_WRITE_4(sc, TI_MB_CMDPROD_IDX, 0);
198745386Swpaul	sc->ti_cmd_saved_prodidx = 0;
198845386Swpaul
198945386Swpaul	/*
199045386Swpaul	 * Assign the address of the stats refresh buffer.
199145386Swpaul	 * We re-use the current stats buffer for this to
199245386Swpaul	 * conserve memory.
199345386Swpaul	 */
199445386Swpaul	TI_HOSTADDR(sc->ti_rdata->ti_info.ti_refresh_stats_ptr) =
1995143903Sscottl	    rdphys + TI_RD_OFF(ti_info.ti_stats);
199645386Swpaul
199745386Swpaul	/* Set up the standard receive ring. */
199845386Swpaul	rcb = &sc->ti_rdata->ti_info.ti_std_rx_rcb;
1999143903Sscottl	TI_HOSTADDR(rcb->ti_hostaddr) = rdphys + TI_RD_OFF(ti_rx_std_ring);
200045386Swpaul	rcb->ti_max_len = TI_FRAMELEN;
200145386Swpaul	rcb->ti_flags = 0;
2002227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
200358698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
200458698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
2005227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2006227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
200745386Swpaul
200845386Swpaul	/* Set up the jumbo receive ring. */
200945386Swpaul	rcb = &sc->ti_rdata->ti_info.ti_jumbo_rx_rcb;
2010143903Sscottl	TI_HOSTADDR(rcb->ti_hostaddr) = rdphys + TI_RD_OFF(ti_rx_jumbo_ring);
201198849Sken
2012227347Syongari#ifndef TI_SF_BUF_JUMBO
2013227347Syongari	rcb->ti_max_len = MJUM9BYTES - ETHER_ALIGN;
201445386Swpaul	rcb->ti_flags = 0;
201598849Sken#else
201698849Sken	rcb->ti_max_len = PAGE_SIZE;
201798849Sken	rcb->ti_flags = TI_RCB_FLAG_USE_EXT_RX_BD;
201898849Sken#endif
2019227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
202058698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
202158698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
2022227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2023227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
202445386Swpaul
202545386Swpaul	/*
202645386Swpaul	 * Set up the mini ring. Only activated on the
202745386Swpaul	 * Tigon 2 but the slot in the config block is
202845386Swpaul	 * still there on the Tigon 1.
202945386Swpaul	 */
203045386Swpaul	rcb = &sc->ti_rdata->ti_info.ti_mini_rx_rcb;
2031143903Sscottl	TI_HOSTADDR(rcb->ti_hostaddr) = rdphys + TI_RD_OFF(ti_rx_mini_ring);
203251352Swpaul	rcb->ti_max_len = MHLEN - ETHER_ALIGN;
203345386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
203445386Swpaul		rcb->ti_flags = TI_RCB_FLAG_RING_DISABLED;
203545386Swpaul	else
203645386Swpaul		rcb->ti_flags = 0;
2037227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
203858698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
203958698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
2040227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2041227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
204245386Swpaul
204345386Swpaul	/*
204445386Swpaul	 * Set up the receive return ring.
204545386Swpaul	 */
204645386Swpaul	rcb = &sc->ti_rdata->ti_info.ti_return_rcb;
2047143903Sscottl	TI_HOSTADDR(rcb->ti_hostaddr) = rdphys + TI_RD_OFF(ti_rx_return_ring);
204845386Swpaul	rcb->ti_flags = 0;
204945386Swpaul	rcb->ti_max_len = TI_RETURN_RING_CNT;
205045386Swpaul	TI_HOSTADDR(sc->ti_rdata->ti_info.ti_return_prodidx_ptr) =
2051143903Sscottl	    rdphys + TI_RD_OFF(ti_return_prodidx_r);
205245386Swpaul
205345386Swpaul	/*
205445386Swpaul	 * Set up the tx ring. Note: for the Tigon 2, we have the option
205545386Swpaul	 * of putting the transmit ring in the host's address space and
205645386Swpaul	 * letting the chip DMA it instead of leaving the ring in the NIC's
205745386Swpaul	 * memory and accessing it through the shared memory region. We
205845386Swpaul	 * do this for the Tigon 2, but it doesn't work on the Tigon 1,
205945386Swpaul	 * so we have to revert to the shared memory scheme if we detect
206045386Swpaul	 * a Tigon 1 chip.
206145386Swpaul	 */
206245386Swpaul	CSR_WRITE_4(sc, TI_WINBASE, TI_TX_RING_BASE);
206345386Swpaul	bzero((char *)sc->ti_rdata->ti_tx_ring,
206445386Swpaul	    TI_TX_RING_CNT * sizeof(struct ti_tx_desc));
206545386Swpaul	rcb = &sc->ti_rdata->ti_info.ti_tx_rcb;
206645386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
206745386Swpaul		rcb->ti_flags = 0;
206845386Swpaul	else
206945386Swpaul		rcb->ti_flags = TI_RCB_FLAG_HOST_RING;
2070227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_VLAN_HWTAGGING)
2071227095Syongari		rcb->ti_flags |= TI_RCB_FLAG_VLAN_ASSIST;
2072227095Syongari	if (sc->ti_ifp->if_capenable & IFCAP_TXCSUM)
207358698Sjlemon		rcb->ti_flags |= TI_RCB_FLAG_TCP_UDP_CKSUM |
207458698Sjlemon		     TI_RCB_FLAG_IP_CKSUM | TI_RCB_FLAG_NO_PHDR_CKSUM;
207545386Swpaul	rcb->ti_max_len = TI_TX_RING_CNT;
207645386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
207745386Swpaul		TI_HOSTADDR(rcb->ti_hostaddr) = TI_TX_RING_BASE;
207845386Swpaul	else
2079143903Sscottl		TI_HOSTADDR(rcb->ti_hostaddr) = rdphys + TI_RD_OFF(ti_tx_ring);
208045386Swpaul	TI_HOSTADDR(sc->ti_rdata->ti_info.ti_tx_considx_ptr) =
2081143903Sscottl	    rdphys + TI_RD_OFF(ti_tx_considx_r);
208245386Swpaul
2083153770Syongari	bus_dmamap_sync(sc->ti_rdata_dmat, sc->ti_rdata_dmamap,
2084153770Syongari	    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
2085153770Syongari
208645386Swpaul	/* Set up tuneables */
208798849Sken#if 0
208845386Swpaul	if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN))
208945386Swpaul		CSR_WRITE_4(sc, TI_GCR_RX_COAL_TICKS,
209045386Swpaul		    (sc->ti_rx_coal_ticks / 10));
209145386Swpaul	else
209298849Sken#endif
209345386Swpaul		CSR_WRITE_4(sc, TI_GCR_RX_COAL_TICKS, sc->ti_rx_coal_ticks);
209445386Swpaul	CSR_WRITE_4(sc, TI_GCR_TX_COAL_TICKS, sc->ti_tx_coal_ticks);
209545386Swpaul	CSR_WRITE_4(sc, TI_GCR_STAT_TICKS, sc->ti_stat_ticks);
209645386Swpaul	CSR_WRITE_4(sc, TI_GCR_RX_MAX_COAL_BD, sc->ti_rx_max_coal_bds);
209745386Swpaul	CSR_WRITE_4(sc, TI_GCR_TX_MAX_COAL_BD, sc->ti_tx_max_coal_bds);
209845386Swpaul	CSR_WRITE_4(sc, TI_GCR_TX_BUFFER_RATIO, sc->ti_tx_buf_ratio);
209945386Swpaul
210045386Swpaul	/* Turn interrupts on. */
210145386Swpaul	CSR_WRITE_4(sc, TI_GCR_MASK_INTRS, 0);
210245386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
210345386Swpaul
210445386Swpaul	/* Start CPU. */
210545386Swpaul	TI_CLRBIT(sc, TI_CPU_STATE, (TI_CPUSTATE_HALT|TI_CPUSTATE_STEP));
210645386Swpaul
2107131654Sbms	return (0);
210845386Swpaul}
210945386Swpaul
2110143903Sscottlstatic void
2111143903Sscottlti_rdata_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2112143903Sscottl{
2113143903Sscottl	struct ti_softc *sc;
2114143903Sscottl
2115143903Sscottl	sc = arg;
2116143903Sscottl	if (error || nseg != 1)
2117143903Sscottl		return;
2118143903Sscottl
2119143903Sscottl	/*
2120143903Sscottl	 * All of the Tigon data structures need to live at <4GB.  This
2121143903Sscottl	 * cast is fine since busdma was told about this constraint.
2122143903Sscottl	 */
2123153770Syongari	sc->ti_rdata_phys = segs[0].ds_addr;
2124143903Sscottl	return;
2125143903Sscottl}
2126227087Syongari
212745386Swpaul/*
212845386Swpaul * Probe for a Tigon chip. Check the PCI vendor and device IDs
212945386Swpaul * against our list and return its name if we find a match.
213045386Swpaul */
2131102336Salfredstatic int
2132227086Syongariti_probe(device_t dev)
213345386Swpaul{
2134227087Syongari	const struct ti_type *t;
213545386Swpaul
213645386Swpaul	t = ti_devs;
213745386Swpaul
2138131654Sbms	while (t->ti_name != NULL) {
213949011Swpaul		if ((pci_get_vendor(dev) == t->ti_vid) &&
214049011Swpaul		    (pci_get_device(dev) == t->ti_did)) {
214149011Swpaul			device_set_desc(dev, t->ti_name);
2142142398Simp			return (BUS_PROBE_DEFAULT);
214349011Swpaul		}
214445386Swpaul		t++;
214545386Swpaul	}
214645386Swpaul
2147131654Sbms	return (ENXIO);
214845386Swpaul}
214945386Swpaul
215098849Skenstatic int
2151227086Syongariti_attach(device_t dev)
215245386Swpaul{
2153227087Syongari	struct ifnet *ifp;
2154227087Syongari	struct ti_softc *sc;
2155227087Syongari	int error = 0, rid;
2156227087Syongari	u_char eaddr[6];
215745386Swpaul
215849011Swpaul	sc = device_get_softc(dev);
2159153396Sscottl	sc->ti_dev = dev;
216045386Swpaul
216193818Sjhb	mtx_init(&sc->ti_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
2162153770Syongari	    MTX_DEF);
2163199559Sjhb	callout_init_mtx(&sc->ti_watchdog, &sc->ti_mtx, 0);
2164113609Snjl	ifmedia_init(&sc->ifmedia, IFM_IMASK, ti_ifmedia_upd, ti_ifmedia_sts);
2165147805Sscottl	ifp = sc->ti_ifp = if_alloc(IFT_ETHER);
2166147805Sscottl	if (ifp == NULL) {
2167150719Sjhb		device_printf(dev, "can not if_alloc()\n");
2168147805Sscottl		error = ENOSPC;
2169147805Sscottl		goto fail;
2170147805Sscottl	}
2171227095Syongari	sc->ti_ifp->if_hwassist = TI_CSUM_FEATURES;
2172227095Syongari	sc->ti_ifp->if_capabilities = IFCAP_TXCSUM | IFCAP_RXCSUM;
2173147256Sbrooks	sc->ti_ifp->if_capenable = sc->ti_ifp->if_capabilities;
217469583Swpaul
217545386Swpaul	/*
217645386Swpaul	 * Map control/status registers.
217745386Swpaul	 */
217872813Swpaul	pci_enable_busmaster(dev);
217945386Swpaul
2180227311Syongari	rid = PCIR_BAR(0);
2181127135Snjl	sc->ti_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
2182178588Smarius	    RF_ACTIVE);
218349011Swpaul
218449011Swpaul	if (sc->ti_res == NULL) {
2185150719Sjhb		device_printf(dev, "couldn't map memory\n");
218649011Swpaul		error = ENXIO;
218745386Swpaul		goto fail;
218845386Swpaul	}
218945386Swpaul
219049035Swpaul	sc->ti_btag = rman_get_bustag(sc->ti_res);
219149035Swpaul	sc->ti_bhandle = rman_get_bushandle(sc->ti_res);
219249035Swpaul
219349011Swpaul	/* Allocate interrupt */
219449011Swpaul	rid = 0;
2195131652Sbms
2196127135Snjl	sc->ti_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
219749011Swpaul	    RF_SHAREABLE | RF_ACTIVE);
219845386Swpaul
219949011Swpaul	if (sc->ti_irq == NULL) {
2200150719Sjhb		device_printf(dev, "couldn't map interrupt\n");
220149011Swpaul		error = ENXIO;
220245386Swpaul		goto fail;
220345386Swpaul	}
220445386Swpaul
220545386Swpaul	if (ti_chipinit(sc)) {
2206150719Sjhb		device_printf(dev, "chip initialization failed\n");
220749011Swpaul		error = ENXIO;
220845386Swpaul		goto fail;
220945386Swpaul	}
221045386Swpaul
221145386Swpaul	/* Zero out the NIC's on-board SRAM. */
2212153770Syongari	ti_mem_zero(sc, 0x2000, 0x100000 - 0x2000);
221345386Swpaul
221445386Swpaul	/* Init again -- zeroing memory may have clobbered some registers. */
221545386Swpaul	if (ti_chipinit(sc)) {
2216150719Sjhb		device_printf(dev, "chip initialization failed\n");
221749011Swpaul		error = ENXIO;
221845386Swpaul		goto fail;
221945386Swpaul	}
222045386Swpaul
222145386Swpaul	/*
222245386Swpaul	 * Get station address from the EEPROM. Note: the manual states
222345386Swpaul	 * that the MAC address is at offset 0x8c, however the data is
222445386Swpaul	 * stored as two longwords (since that's how it's loaded into
222572645Sasmodai	 * the NIC). This means the MAC address is actually preceded
222645386Swpaul	 * by two zero bytes. We need to skip over those.
222745386Swpaul	 */
2228147256Sbrooks	if (ti_read_eeprom(sc, eaddr,
222945386Swpaul				TI_EE_MAC_OFFSET + 2, ETHER_ADDR_LEN)) {
2230150719Sjhb		device_printf(dev, "failed to read station address\n");
223149011Swpaul		error = ENXIO;
223245386Swpaul		goto fail;
223345386Swpaul	}
223445386Swpaul
2235227505Syongari	/* Allocate working area for memory dump. */
2236227505Syongari	sc->ti_membuf = malloc(sizeof(uint8_t) * TI_WINLEN, M_DEVBUF, M_NOWAIT);
2237227505Syongari	sc->ti_membuf2 = malloc(sizeof(uint8_t) * TI_WINLEN, M_DEVBUF,
2238227505Syongari	    M_NOWAIT);
2239227505Syongari	if (sc->ti_membuf == NULL || sc->ti_membuf2 == NULL) {
2240227505Syongari		device_printf(dev, "cannot allocate memory buffer\n");
2241227505Syongari		error = ENOMEM;
2242227505Syongari		goto fail;
2243227505Syongari	}
2244227505Syongari
224545386Swpaul	/* Allocate the general information block and ring buffers. */
2246166165Smarius	if (bus_dma_tag_create(bus_get_dma_tag(dev),	/* parent */
2247143903Sscottl				1, 0,			/* algnmnt, boundary */
2248143903Sscottl				BUS_SPACE_MAXADDR,	/* lowaddr */
2249143903Sscottl				BUS_SPACE_MAXADDR,	/* highaddr */
2250143903Sscottl				NULL, NULL,		/* filter, filterarg */
2251143903Sscottl				BUS_SPACE_MAXSIZE_32BIT,/* maxsize */
2252143903Sscottl				0,			/* nsegments */
2253143903Sscottl				BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
2254143903Sscottl				0,			/* flags */
2255143903Sscottl				NULL, NULL,		/* lockfunc, lockarg */
2256143903Sscottl				&sc->ti_parent_dmat) != 0) {
2257150719Sjhb		device_printf(dev, "Failed to allocate parent dmat\n");
2258143903Sscottl		error = ENOMEM;
2259143903Sscottl		goto fail;
2260143903Sscottl	}
226145386Swpaul
2262143903Sscottl	if (bus_dma_tag_create(sc->ti_parent_dmat,	/* parent */
2263143903Sscottl				PAGE_SIZE, 0,		/* algnmnt, boundary */
2264143903Sscottl				BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
2265143903Sscottl				BUS_SPACE_MAXADDR,	/* highaddr */
2266143903Sscottl				NULL, NULL,		/* filter, filterarg */
2267143903Sscottl				sizeof(struct ti_ring_data),	/* maxsize */
2268143903Sscottl				1,			/* nsegments */
2269143903Sscottl				sizeof(struct ti_ring_data),	/* maxsegsize */
2270143903Sscottl				0,			/* flags */
2271143903Sscottl				NULL, NULL,		/* lockfunc, lockarg */
2272143903Sscottl				&sc->ti_rdata_dmat) != 0) {
2273150719Sjhb		device_printf(dev, "Failed to allocate rdata dmat\n");
2274143903Sscottl		error = ENOMEM;
227545386Swpaul		goto fail;
227645386Swpaul	}
227745386Swpaul
2278143903Sscottl	if (bus_dmamem_alloc(sc->ti_rdata_dmat, (void**)&sc->ti_rdata,
2279219547Smarius			     BUS_DMA_NOWAIT | BUS_DMA_COHERENT,
2280219547Smarius			     &sc->ti_rdata_dmamap) != 0) {
2281150719Sjhb		device_printf(dev, "Failed to allocate rdata memory\n");
2282143903Sscottl		error = ENOMEM;
2283143903Sscottl		goto fail;
2284143903Sscottl	}
2285143903Sscottl
2286143903Sscottl	if (bus_dmamap_load(sc->ti_rdata_dmat, sc->ti_rdata_dmamap,
2287143903Sscottl			    sc->ti_rdata, sizeof(struct ti_ring_data),
2288143903Sscottl			    ti_rdata_cb, sc, BUS_DMA_NOWAIT) != 0) {
2289150719Sjhb		device_printf(dev, "Failed to load rdata segments\n");
2290143903Sscottl		error = ENOMEM;
2291143903Sscottl		goto fail;
2292143903Sscottl	}
2293143903Sscottl
229445386Swpaul	bzero(sc->ti_rdata, sizeof(struct ti_ring_data));
229545386Swpaul
229645386Swpaul	/* Try to allocate memory for jumbo buffers. */
229745386Swpaul	if (ti_alloc_jumbo_mem(sc)) {
2298150719Sjhb		device_printf(dev, "jumbo buffer allocation failed\n");
229949011Swpaul		error = ENXIO;
230045386Swpaul		goto fail;
230145386Swpaul	}
230245386Swpaul
2303153396Sscottl	if (bus_dma_tag_create(sc->ti_parent_dmat,	/* parent */
2304153396Sscottl				1, 0,			/* algnmnt, boundary */
2305153396Sscottl				BUS_SPACE_MAXADDR,	/* lowaddr */
2306153396Sscottl				BUS_SPACE_MAXADDR,	/* highaddr */
2307153396Sscottl				NULL, NULL,		/* filter, filterarg */
2308153396Sscottl				MCLBYTES * TI_MAXTXSEGS,/* maxsize */
2309153396Sscottl				TI_MAXTXSEGS,		/* nsegments */
2310153396Sscottl				MCLBYTES,		/* maxsegsize */
2311153396Sscottl				0,			/* flags */
2312153396Sscottl				NULL, NULL,		/* lockfunc, lockarg */
2313153396Sscottl				&sc->ti_mbuftx_dmat) != 0) {
2314153396Sscottl		device_printf(dev, "Failed to allocate rdata dmat\n");
2315153396Sscottl		error = ENOMEM;
2316153396Sscottl		goto fail;
2317153396Sscottl	}
2318153396Sscottl
2319153396Sscottl	if (bus_dma_tag_create(sc->ti_parent_dmat,	/* parent */
2320153396Sscottl				1, 0,			/* algnmnt, boundary */
2321153396Sscottl				BUS_SPACE_MAXADDR,	/* lowaddr */
2322153396Sscottl				BUS_SPACE_MAXADDR,	/* highaddr */
2323153396Sscottl				NULL, NULL,		/* filter, filterarg */
2324153396Sscottl				MCLBYTES,		/* maxsize */
2325153396Sscottl				1,			/* nsegments */
2326153396Sscottl				MCLBYTES,		/* maxsegsize */
2327153396Sscottl				0,			/* flags */
2328153396Sscottl				NULL, NULL,		/* lockfunc, lockarg */
2329153396Sscottl				&sc->ti_mbufrx_dmat) != 0) {
2330153396Sscottl		device_printf(dev, "Failed to allocate rdata dmat\n");
2331153396Sscottl		error = ENOMEM;
2332153396Sscottl		goto fail;
2333153396Sscottl	}
2334153396Sscottl
2335153396Sscottl	if (ti_alloc_dmamaps(sc)) {
2336153396Sscottl		error = ENXIO;
2337153396Sscottl		goto fail;
2338153396Sscottl	}
2339153396Sscottl
234063699Swpaul	/*
234163699Swpaul	 * We really need a better way to tell a 1000baseTX card
234263699Swpaul	 * from a 1000baseSX one, since in theory there could be
234363699Swpaul	 * OEMed 1000baseTX cards from lame vendors who aren't
234463699Swpaul	 * clever enough to change the PCI ID. For the moment
234563699Swpaul	 * though, the AceNIC is the only copper card available.
234663699Swpaul	 */
234763699Swpaul	if (pci_get_vendor(dev) == ALT_VENDORID &&
234863699Swpaul	    pci_get_device(dev) == ALT_DEVICEID_ACENIC_COPPER)
234963699Swpaul		sc->ti_copper = 1;
235064139Swpaul	/* Ok, it's not the only copper card available. */
235164139Swpaul	if (pci_get_vendor(dev) == NG_VENDORID &&
235264139Swpaul	    pci_get_device(dev) == NG_DEVICEID_GA620T)
235364139Swpaul		sc->ti_copper = 1;
235463699Swpaul
235545386Swpaul	/* Set default tuneable values. */
235645386Swpaul	sc->ti_stat_ticks = 2 * TI_TICKS_PER_SEC;
235798849Sken#if 0
235845386Swpaul	sc->ti_rx_coal_ticks = TI_TICKS_PER_SEC / 5000;
235998849Sken#endif
236098849Sken	sc->ti_rx_coal_ticks = 170;
236145386Swpaul	sc->ti_tx_coal_ticks = TI_TICKS_PER_SEC / 500;
236245386Swpaul	sc->ti_rx_max_coal_bds = 64;
236398849Sken#if 0
236445386Swpaul	sc->ti_tx_max_coal_bds = 128;
236598849Sken#endif
236698849Sken	sc->ti_tx_max_coal_bds = 32;
236745386Swpaul	sc->ti_tx_buf_ratio = 21;
236845386Swpaul
236945386Swpaul	/* Set up ifnet structure */
237045386Swpaul	ifp->if_softc = sc;
2371121816Sbrooks	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
2372153281Sscottl	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
237345386Swpaul	ifp->if_ioctl = ti_ioctl;
237445386Swpaul	ifp->if_start = ti_start;
237545386Swpaul	ifp->if_init = ti_init;
2376227092Syongari	ifp->if_baudrate = IF_Gbps(1UL);
2377227099Syongari	ifp->if_snd.ifq_drv_maxlen = TI_TX_RING_CNT - 1;
2378227099Syongari	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
2379227099Syongari	IFQ_SET_READY(&ifp->if_snd);
238045386Swpaul
238145386Swpaul	/* Set up ifmedia support. */
238263699Swpaul	if (sc->ti_copper) {
238363699Swpaul		/*
238463699Swpaul		 * Copper cards allow manual 10/100 mode selection,
238563699Swpaul		 * but not manual 1000baseTX mode selection. Why?
238663699Swpaul		 * Becuase currently there's no way to specify the
238763699Swpaul		 * master/slave setting through the firmware interface,
238863699Swpaul		 * so Alteon decided to just bag it and handle it
238963699Swpaul		 * via autonegotiation.
239063699Swpaul		 */
239163699Swpaul		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
239263699Swpaul		ifmedia_add(&sc->ifmedia,
239363699Swpaul		    IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
239463699Swpaul		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
239563699Swpaul		ifmedia_add(&sc->ifmedia,
239663699Swpaul		    IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
239795673Sphk		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_1000_T, 0, NULL);
239863699Swpaul		ifmedia_add(&sc->ifmedia,
239995673Sphk		    IFM_ETHER|IFM_1000_T|IFM_FDX, 0, NULL);
240063699Swpaul	} else {
240163699Swpaul		/* Fiber cards don't support 10/100 modes. */
240263699Swpaul		ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_1000_SX, 0, NULL);
240363699Swpaul		ifmedia_add(&sc->ifmedia,
240463699Swpaul		    IFM_ETHER|IFM_1000_SX|IFM_FDX, 0, NULL);
240563699Swpaul	}
240645386Swpaul	ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
240745386Swpaul	ifmedia_set(&sc->ifmedia, IFM_ETHER|IFM_AUTO);
240845386Swpaul
240945386Swpaul	/*
241098849Sken	 * We're assuming here that card initialization is a sequential
241198849Sken	 * thing.  If it isn't, multiple cards probing at the same time
241298849Sken	 * could stomp on the list of softcs here.
241398849Sken	 */
241498849Sken
241598849Sken	/* Register the device */
2416227311Syongari	sc->dev = make_dev(&ti_cdevsw, device_get_unit(dev), UID_ROOT,
2417227311Syongari	    GID_OPERATOR, 0600, "ti%d", device_get_unit(dev));
2418120980Sphk	sc->dev->si_drv1 = sc;
241998849Sken
242098849Sken	/*
242163090Sarchie	 * Call MI attach routine.
242245386Swpaul	 */
2423147256Sbrooks	ether_ifattach(ifp, eaddr);
242445386Swpaul
2425227095Syongari	/* VLAN capability setup. */
2426227095Syongari	ifp->if_capabilities |= IFCAP_VLAN_MTU | IFCAP_VLAN_HWCSUM |
2427227095Syongari	    IFCAP_VLAN_HWTAGGING;
2428227095Syongari	ifp->if_capenable = ifp->if_capabilities;
2429227095Syongari	/* Tell the upper layer we support VLAN over-sized frames. */
2430227095Syongari	ifp->if_hdrlen = sizeof(struct ether_vlan_header);
2431227095Syongari
2432227092Syongari	/* Driver supports link state tracking. */
2433227092Syongari	ifp->if_capabilities |= IFCAP_LINKSTATE;
2434227092Syongari	ifp->if_capenable |= IFCAP_LINKSTATE;
2435227092Syongari
2436113609Snjl	/* Hook interrupt last to avoid having to lock softc */
2437153281Sscottl	error = bus_setup_intr(dev, sc->ti_irq, INTR_TYPE_NET|INTR_MPSAFE,
2438166901Spiso	   NULL, ti_intr, sc, &sc->ti_intrhand);
2439112872Snjl
2440112872Snjl	if (error) {
2441150719Sjhb		device_printf(dev, "couldn't set up irq\n");
2442112872Snjl		goto fail;
2443112872Snjl	}
2444112872Snjl
244545386Swpaulfail:
2446153770Syongari	if (error)
2447112872Snjl		ti_detach(dev);
2448112872Snjl
2449131654Sbms	return (error);
245045386Swpaul}
245145386Swpaul
245298849Sken/*
2453113609Snjl * Shutdown hardware and free up resources. This can be called any
2454113609Snjl * time after the mutex has been initialized. It is called in both
2455113609Snjl * the error case in attach and the normal detach case so it needs
2456113609Snjl * to be careful about only freeing resources that have actually been
2457113609Snjl * allocated.
2458113609Snjl */
2459102336Salfredstatic int
2460227086Syongariti_detach(device_t dev)
246149011Swpaul{
2462227087Syongari	struct ti_softc *sc;
2463227087Syongari	struct ifnet *ifp;
246449011Swpaul
246549011Swpaul	sc = device_get_softc(dev);
2466144407Sscottl	if (sc->dev)
2467144407Sscottl		destroy_dev(sc->dev);
2468112930Sphk	KASSERT(mtx_initialized(&sc->ti_mtx), ("ti mutex not initialized"));
2469147256Sbrooks	ifp = sc->ti_ifp;
2470199559Sjhb	if (device_is_attached(dev)) {
2471199559Sjhb		ether_ifdetach(ifp);
2472199559Sjhb		TI_LOCK(sc);
2473153770Syongari		ti_stop(sc);
2474199559Sjhb		TI_UNLOCK(sc);
2475199559Sjhb	}
247649011Swpaul
2477113609Snjl	/* These should only be active if attach succeeded */
2478199559Sjhb	callout_drain(&sc->ti_watchdog);
2479199559Sjhb	bus_generic_detach(dev);
2480153770Syongari	ti_free_dmamaps(sc);
2481113609Snjl	ifmedia_removeall(&sc->ifmedia);
248249011Swpaul
2483153288Sscottl	if (sc->ti_jumbo_dmat)
2484153288Sscottl		bus_dma_tag_destroy(sc->ti_jumbo_dmat);
2485153396Sscottl	if (sc->ti_mbuftx_dmat)
2486153396Sscottl		bus_dma_tag_destroy(sc->ti_mbuftx_dmat);
2487153396Sscottl	if (sc->ti_mbufrx_dmat)
2488153396Sscottl		bus_dma_tag_destroy(sc->ti_mbufrx_dmat);
2489227091Syongari	if (sc->ti_rdata && sc->ti_rdata_dmamap)
2490227091Syongari		bus_dmamap_unload(sc->ti_rdata_dmat, sc->ti_rdata_dmamap);
2491143903Sscottl	if (sc->ti_rdata)
2492143903Sscottl		bus_dmamem_free(sc->ti_rdata_dmat, sc->ti_rdata,
2493143903Sscottl				sc->ti_rdata_dmamap);
2494143903Sscottl	if (sc->ti_rdata_dmat)
2495143903Sscottl		bus_dma_tag_destroy(sc->ti_rdata_dmat);
2496143903Sscottl	if (sc->ti_parent_dmat)
2497143903Sscottl		bus_dma_tag_destroy(sc->ti_parent_dmat);
2498112872Snjl	if (sc->ti_intrhand)
2499112872Snjl		bus_teardown_intr(dev, sc->ti_irq, sc->ti_intrhand);
2500112872Snjl	if (sc->ti_irq)
2501112872Snjl		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ti_irq);
2502112872Snjl	if (sc->ti_res) {
2503227311Syongari		bus_release_resource(dev, SYS_RES_MEMORY, PCIR_BAR(0),
2504112872Snjl		    sc->ti_res);
2505112872Snjl	}
2506151297Sru	if (ifp)
2507151297Sru		if_free(ifp);
2508227505Syongari	if (sc->ti_membuf)
2509227505Syongari		free(sc->ti_membuf, M_DEVBUF);
2510227505Syongari	if (sc->ti_membuf2)
2511227505Syongari		free(sc->ti_membuf2, M_DEVBUF);
251249011Swpaul
251367087Swpaul	mtx_destroy(&sc->ti_mtx);
251449011Swpaul
2515131654Sbms	return (0);
251649011Swpaul}
251749011Swpaul
251898849Sken#ifdef TI_JUMBO_HDRSPLIT
251945386Swpaul/*
252098849Sken * If hdr_len is 0, that means that header splitting wasn't done on
252198849Sken * this packet for some reason.  The two most likely reasons are that
252298849Sken * the protocol isn't a supported protocol for splitting, or this
252398849Sken * packet had a fragment offset that wasn't 0.
252498849Sken *
252598849Sken * The header length, if it is non-zero, will always be the length of
252698849Sken * the headers on the packet, but that length could be longer than the
252798849Sken * first mbuf.  So we take the minimum of the two as the actual
2528131652Sbms * length.
252998849Sken */
253098849Skenstatic __inline void
253198849Skenti_hdr_split(struct mbuf *top, int hdr_len, int pkt_len, int idx)
253298849Sken{
253398849Sken	int i = 0;
253498849Sken	int lengths[4] = {0, 0, 0, 0};
253598849Sken	struct mbuf *m, *mp;
253698849Sken
253798849Sken	if (hdr_len != 0)
253898849Sken		top->m_len = min(hdr_len, top->m_len);
253998849Sken	pkt_len -= top->m_len;
254098849Sken	lengths[i++] = top->m_len;
254198849Sken
254298849Sken	mp = top;
254398849Sken	for (m = top->m_next; m && pkt_len; m = m->m_next) {
254498849Sken		m->m_len = m->m_ext.ext_size = min(m->m_len, pkt_len);
254598849Sken		pkt_len -= m->m_len;
254698849Sken		lengths[i++] = m->m_len;
254798849Sken		mp = m;
254898849Sken	}
254998849Sken
255098849Sken#if 0
255198849Sken	if (hdr_len != 0)
255298849Sken		printf("got split packet: ");
255398849Sken	else
255498849Sken		printf("got non-split packet: ");
2555131652Sbms
255698849Sken	printf("%d,%d,%d,%d = %d\n", lengths[0],
255798849Sken	    lengths[1], lengths[2], lengths[3],
255898849Sken	    lengths[0] + lengths[1] + lengths[2] +
255998849Sken	    lengths[3]);
256098849Sken#endif
256198849Sken
256298849Sken	if (pkt_len)
256398849Sken		panic("header splitting didn't");
2564131652Sbms
256598849Sken	if (m) {
256698849Sken		m_freem(m);
256798849Sken		mp->m_next = NULL;
256898849Sken
256998849Sken	}
257098849Sken	if (mp->m_next != NULL)
257198849Sken		panic("ti_hdr_split: last mbuf in chain should be null");
257298849Sken}
257398849Sken#endif /* TI_JUMBO_HDRSPLIT */
257498849Sken
2575227347Syongaristatic void
2576227347Syongariti_discard_std(struct ti_softc *sc, int i)
2577227347Syongari{
2578227347Syongari
2579227347Syongari	struct ti_rx_desc *r;
2580227347Syongari
2581227347Syongari	r = &sc->ti_rdata->ti_rx_std_ring[i];
2582227347Syongari	r->ti_len = MCLBYTES - ETHER_ALIGN;
2583227347Syongari	r->ti_type = TI_BDTYPE_RECV_BD;
2584227347Syongari	r->ti_flags = 0;
2585227347Syongari	r->ti_vlan_tag = 0;
2586227347Syongari	r->ti_tcp_udp_cksum = 0;
2587227347Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
2588227347Syongari		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
2589227347Syongari	r->ti_idx = i;
2590227347Syongari}
2591227347Syongari
2592227347Syongaristatic void
2593227347Syongariti_discard_mini(struct ti_softc *sc, int i)
2594227347Syongari{
2595227347Syongari
2596227347Syongari	struct ti_rx_desc *r;
2597227347Syongari
2598227347Syongari	r = &sc->ti_rdata->ti_rx_mini_ring[i];
2599227347Syongari	r->ti_len = MHLEN - ETHER_ALIGN;
2600227347Syongari	r->ti_type = TI_BDTYPE_RECV_BD;
2601227347Syongari	r->ti_flags = TI_BDFLAG_MINI_RING;
2602227347Syongari	r->ti_vlan_tag = 0;
2603227347Syongari	r->ti_tcp_udp_cksum = 0;
2604227347Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
2605227347Syongari		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
2606227347Syongari	r->ti_idx = i;
2607227347Syongari}
2608227347Syongari
2609227347Syongari#ifndef TI_SF_BUF_JUMBO
2610227347Syongaristatic void
2611227347Syongariti_discard_jumbo(struct ti_softc *sc, int i)
2612227347Syongari{
2613227347Syongari
2614227347Syongari	struct ti_rx_desc *r;
2615227347Syongari
2616227347Syongari	r = &sc->ti_rdata->ti_rx_mini_ring[i];
2617227347Syongari	r->ti_len = MJUM9BYTES - ETHER_ALIGN;
2618227347Syongari	r->ti_type = TI_BDTYPE_RECV_JUMBO_BD;
2619227347Syongari	r->ti_flags = TI_BDFLAG_JUMBO_RING;
2620227347Syongari	r->ti_vlan_tag = 0;
2621227347Syongari	r->ti_tcp_udp_cksum = 0;
2622227347Syongari	if (sc->ti_ifp->if_capenable & IFCAP_RXCSUM)
2623227347Syongari		r->ti_flags |= TI_BDFLAG_TCP_UDP_CKSUM | TI_BDFLAG_IP_CKSUM;
2624227347Syongari	r->ti_idx = i;
2625227347Syongari}
2626227347Syongari#endif
2627227347Syongari
262898849Sken/*
262945386Swpaul * Frame reception handling. This is called if there's a frame
263045386Swpaul * on the receive return list.
263145386Swpaul *
263245386Swpaul * Note: we have to be able to handle three possibilities here:
263345386Swpaul * 1) the frame is from the mini receive ring (can only happen)
263445386Swpaul *    on Tigon 2 boards)
263545386Swpaul * 2) the frame is from the jumbo recieve ring
263645386Swpaul * 3) the frame is from the standard receive ring
263745386Swpaul */
263845386Swpaul
2639102336Salfredstatic void
2640227086Syongariti_rxeof(struct ti_softc *sc)
264145386Swpaul{
2642227087Syongari	struct ifnet *ifp;
2643227347Syongari#ifdef TI_SF_BUF_JUMBO
2644227087Syongari	bus_dmamap_t map;
2645227347Syongari#endif
2646227087Syongari	struct ti_cmd_desc cmd;
2647227347Syongari	int jumbocnt, minicnt, stdcnt, ti_len;
264845386Swpaul
2649122689Ssam	TI_LOCK_ASSERT(sc);
2650122689Ssam
2651147256Sbrooks	ifp = sc->ti_ifp;
265245386Swpaul
2653227318Syongari	jumbocnt = minicnt = stdcnt = 0;
2654131654Sbms	while (sc->ti_rx_saved_considx != sc->ti_return_prodidx.ti_idx) {
2655227087Syongari		struct ti_rx_desc *cur_rx;
2656227318Syongari		uint32_t rxidx;
2657227087Syongari		struct mbuf *m = NULL;
2658227089Syongari		uint16_t vlan_tag = 0;
2659227087Syongari		int have_tag = 0;
266045386Swpaul
266145386Swpaul		cur_rx =
266245386Swpaul		    &sc->ti_rdata->ti_rx_return_ring[sc->ti_rx_saved_considx];
266345386Swpaul		rxidx = cur_rx->ti_idx;
2664227347Syongari		ti_len = cur_rx->ti_len;
266545386Swpaul		TI_INC(sc->ti_rx_saved_considx, TI_RETURN_RING_CNT);
266645386Swpaul
266745386Swpaul		if (cur_rx->ti_flags & TI_BDFLAG_VLAN_TAG) {
266845386Swpaul			have_tag = 1;
2669227094Syongari			vlan_tag = cur_rx->ti_vlan_tag;
267045386Swpaul		}
267145386Swpaul
267245386Swpaul		if (cur_rx->ti_flags & TI_BDFLAG_JUMBO_RING) {
2673227318Syongari			jumbocnt++;
267445386Swpaul			TI_INC(sc->ti_jumbo, TI_JUMBO_RX_RING_CNT);
267545386Swpaul			m = sc->ti_cdata.ti_rx_jumbo_chain[rxidx];
2676227347Syongari#ifndef TI_SF_BUF_JUMBO
2677227347Syongari			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
2678227347Syongari				ifp->if_ierrors++;
2679227347Syongari				ti_discard_jumbo(sc, rxidx);
2680227347Syongari				continue;
2681227347Syongari			}
2682227347Syongari			if (ti_newbuf_jumbo(sc, rxidx, NULL) != 0) {
2683227347Syongari				ifp->if_iqdrops++;
2684227347Syongari				ti_discard_jumbo(sc, rxidx);
2685227347Syongari				continue;
2686227347Syongari			}
2687227347Syongari			m->m_len = ti_len;
2688227347Syongari#else /* !TI_SF_BUF_JUMBO */
268945386Swpaul			sc->ti_cdata.ti_rx_jumbo_chain[rxidx] = NULL;
2690153396Sscottl			map = sc->ti_cdata.ti_rx_jumbo_maps[rxidx];
2691153396Sscottl			bus_dmamap_sync(sc->ti_jumbo_dmat, map,
2692153396Sscottl			    BUS_DMASYNC_POSTREAD);
2693153396Sscottl			bus_dmamap_unload(sc->ti_jumbo_dmat, map);
269445386Swpaul			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
269545386Swpaul				ifp->if_ierrors++;
269645386Swpaul				ti_newbuf_jumbo(sc, sc->ti_jumbo, m);
269745386Swpaul				continue;
269845386Swpaul			}
269948597Swpaul			if (ti_newbuf_jumbo(sc, sc->ti_jumbo, NULL) == ENOBUFS) {
2700227347Syongari				ifp->if_iqdrops++;
270148597Swpaul				ti_newbuf_jumbo(sc, sc->ti_jumbo, m);
270248597Swpaul				continue;
270348597Swpaul			}
270498849Sken#ifdef TI_JUMBO_HDRSPLIT
270598849Sken			if (sc->ti_hdrsplit)
270698849Sken				ti_hdr_split(m, TI_HOSTADDR(cur_rx->ti_addr),
2707227347Syongari					     ti_len, rxidx);
270898849Sken			else
270998849Sken#endif /* TI_JUMBO_HDRSPLIT */
2710227347Syongari			m_adj(m, ti_len - m->m_pkthdr.len);
2711227347Syongari#endif /* TI_SF_BUF_JUMBO */
271245386Swpaul		} else if (cur_rx->ti_flags & TI_BDFLAG_MINI_RING) {
2713227318Syongari			minicnt++;
271445386Swpaul			TI_INC(sc->ti_mini, TI_MINI_RX_RING_CNT);
271545386Swpaul			m = sc->ti_cdata.ti_rx_mini_chain[rxidx];
271645386Swpaul			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
271745386Swpaul				ifp->if_ierrors++;
2718227347Syongari				ti_discard_mini(sc, rxidx);
271945386Swpaul				continue;
272045386Swpaul			}
2721227347Syongari			if (ti_newbuf_mini(sc, rxidx) != 0) {
2722227347Syongari				ifp->if_iqdrops++;
2723227347Syongari				ti_discard_mini(sc, rxidx);
272448597Swpaul				continue;
272548597Swpaul			}
2726227347Syongari			m->m_len = ti_len;
272745386Swpaul		} else {
2728227318Syongari			stdcnt++;
272945386Swpaul			TI_INC(sc->ti_std, TI_STD_RX_RING_CNT);
273045386Swpaul			m = sc->ti_cdata.ti_rx_std_chain[rxidx];
273145386Swpaul			if (cur_rx->ti_flags & TI_BDFLAG_ERROR) {
273245386Swpaul				ifp->if_ierrors++;
2733227347Syongari				ti_discard_std(sc, rxidx);
273445386Swpaul				continue;
273545386Swpaul			}
2736227347Syongari			if (ti_newbuf_std(sc, rxidx) != 0) {
2737227347Syongari				ifp->if_iqdrops++;
2738227347Syongari				ti_discard_std(sc, rxidx);
273948597Swpaul				continue;
274048597Swpaul			}
2741227347Syongari			m->m_len = ti_len;
274245386Swpaul		}
274345386Swpaul
2744227347Syongari		m->m_pkthdr.len = ti_len;
274545386Swpaul		ifp->if_ipackets++;
274645386Swpaul		m->m_pkthdr.rcvif = ifp;
274745386Swpaul
2748227095Syongari		if (ifp->if_capenable & IFCAP_RXCSUM) {
2749227095Syongari			if (cur_rx->ti_flags & TI_BDFLAG_IP_CKSUM) {
2750227095Syongari				m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
2751227095Syongari				if ((cur_rx->ti_ip_cksum ^ 0xffff) == 0)
2752227095Syongari					m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
2753227095Syongari			}
2754227095Syongari			if (cur_rx->ti_flags & TI_BDFLAG_TCP_UDP_CKSUM) {
2755227095Syongari				m->m_pkthdr.csum_data =
2756227095Syongari				    cur_rx->ti_tcp_udp_cksum;
2757227095Syongari				m->m_pkthdr.csum_flags |= CSUM_DATA_VALID;
2758227095Syongari			}
275958698Sjlemon		}
276045386Swpaul
276145386Swpaul		/*
2762106936Ssam		 * If we received a packet with a vlan tag,
2763106936Ssam		 * tag it before passing the packet upward.
276445386Swpaul		 */
2765153512Sglebius		if (have_tag) {
2766162375Sandre			m->m_pkthdr.ether_vtag = vlan_tag;
2767162375Sandre			m->m_flags |= M_VLANTAG;
2768153512Sglebius		}
2769122689Ssam		TI_UNLOCK(sc);
2770106936Ssam		(*ifp->if_input)(ifp, m);
2771122689Ssam		TI_LOCK(sc);
277245386Swpaul	}
277345386Swpaul
277445386Swpaul	/* Only necessary on the Tigon 1. */
277545386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON)
277645386Swpaul		CSR_WRITE_4(sc, TI_GCR_RXRETURNCONS_IDX,
277745386Swpaul		    sc->ti_rx_saved_considx);
277845386Swpaul
2779227318Syongari	if (stdcnt > 0)
2780227318Syongari		TI_UPDATE_STDPROD(sc, sc->ti_std);
2781227318Syongari	if (minicnt > 0)
2782227318Syongari		TI_UPDATE_MINIPROD(sc, sc->ti_mini);
2783227318Syongari	if (jumbocnt > 0)
2784227318Syongari		TI_UPDATE_JUMBOPROD(sc, sc->ti_jumbo);
278545386Swpaul}
278645386Swpaul
2787102336Salfredstatic void
2788227086Syongariti_txeof(struct ti_softc *sc)
278945386Swpaul{
2790227087Syongari	struct ti_txdesc *txd;
2791227087Syongari	struct ti_tx_desc txdesc;
2792227087Syongari	struct ti_tx_desc *cur_tx = NULL;
2793227087Syongari	struct ifnet *ifp;
2794227087Syongari	int idx;
279545386Swpaul
2796147256Sbrooks	ifp = sc->ti_ifp;
279745386Swpaul
2798153982Syongari	txd = STAILQ_FIRST(&sc->ti_cdata.ti_txbusyq);
2799153982Syongari	if (txd == NULL)
2800153982Syongari		return;
280145386Swpaul	/*
280245386Swpaul	 * Go through our tx ring and free mbufs for those
280345386Swpaul	 * frames that have been sent.
280445386Swpaul	 */
2805153982Syongari	for (idx = sc->ti_tx_saved_considx; idx != sc->ti_tx_considx.ti_idx;
2806153982Syongari	    TI_INC(idx, TI_TX_RING_CNT)) {
280745386Swpaul		if (sc->ti_hwrev == TI_HWREV_TIGON) {
2808153770Syongari			ti_mem_read(sc, TI_TX_RING_BASE + idx * sizeof(txdesc),
2809153770Syongari			    sizeof(txdesc), &txdesc);
2810153770Syongari			cur_tx = &txdesc;
281145386Swpaul		} else
281245386Swpaul			cur_tx = &sc->ti_rdata->ti_tx_ring[idx];
281348011Swpaul		sc->ti_txcnt--;
2814153982Syongari		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
2815153982Syongari		if ((cur_tx->ti_flags & TI_BDFLAG_END) == 0)
2816153982Syongari			continue;
2817153982Syongari		bus_dmamap_sync(sc->ti_mbuftx_dmat, txd->tx_dmamap,
2818153982Syongari		    BUS_DMASYNC_POSTWRITE);
2819153982Syongari		bus_dmamap_unload(sc->ti_mbuftx_dmat, txd->tx_dmamap);
2820153982Syongari
2821153982Syongari		ifp->if_opackets++;
2822153982Syongari		m_freem(txd->tx_m);
2823153982Syongari		txd->tx_m = NULL;
2824153982Syongari		STAILQ_REMOVE_HEAD(&sc->ti_cdata.ti_txbusyq, tx_q);
2825153982Syongari		STAILQ_INSERT_TAIL(&sc->ti_cdata.ti_txfreeq, txd, tx_q);
2826153982Syongari		txd = STAILQ_FIRST(&sc->ti_cdata.ti_txbusyq);
282745386Swpaul	}
2828153982Syongari	sc->ti_tx_saved_considx = idx;
282945386Swpaul
2830199559Sjhb	sc->ti_timer = sc->ti_txcnt > 0 ? 5 : 0;
283145386Swpaul}
283245386Swpaul
2833102336Salfredstatic void
2834227086Syongariti_intr(void *xsc)
283545386Swpaul{
2836227087Syongari	struct ti_softc *sc;
2837227087Syongari	struct ifnet *ifp;
283845386Swpaul
283945386Swpaul	sc = xsc;
284067087Swpaul	TI_LOCK(sc);
2841147256Sbrooks	ifp = sc->ti_ifp;
284245386Swpaul
284345386Swpaul	/* Make sure this is really our interrupt. */
284467087Swpaul	if (!(CSR_READ_4(sc, TI_MISC_HOST_CTL) & TI_MHC_INTSTATE)) {
284567087Swpaul		TI_UNLOCK(sc);
284645386Swpaul		return;
284767087Swpaul	}
284845386Swpaul
284945386Swpaul	/* Ack interrupt and stop others from occuring. */
285045386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
285145386Swpaul
2852148887Srwatson	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
285345386Swpaul		/* Check RX return ring producer/consumer */
285445386Swpaul		ti_rxeof(sc);
285545386Swpaul
285645386Swpaul		/* Check TX ring producer/consumer */
285745386Swpaul		ti_txeof(sc);
285845386Swpaul	}
285945386Swpaul
286045386Swpaul	ti_handle_events(sc);
286145386Swpaul
2862227099Syongari	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
2863227098Syongari		/* Re-enable interrupts. */
2864227098Syongari		CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
2865227099Syongari		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
2866227099Syongari			ti_start_locked(ifp);
2867227098Syongari	}
286845386Swpaul
286967087Swpaul	TI_UNLOCK(sc);
287045386Swpaul}
287145386Swpaul
2872102336Salfredstatic void
2873227086Syongariti_stats_update(struct ti_softc *sc)
287445386Swpaul{
2875227087Syongari	struct ifnet *ifp;
287645386Swpaul
2877147256Sbrooks	ifp = sc->ti_ifp;
287845386Swpaul
2879153770Syongari	bus_dmamap_sync(sc->ti_rdata_dmat, sc->ti_rdata_dmamap,
2880153770Syongari	    BUS_DMASYNC_POSTREAD);
2881153770Syongari
288245386Swpaul	ifp->if_collisions +=
288345386Swpaul	   (sc->ti_rdata->ti_info.ti_stats.dot3StatsSingleCollisionFrames +
288445386Swpaul	   sc->ti_rdata->ti_info.ti_stats.dot3StatsMultipleCollisionFrames +
288545386Swpaul	   sc->ti_rdata->ti_info.ti_stats.dot3StatsExcessiveCollisions +
288645386Swpaul	   sc->ti_rdata->ti_info.ti_stats.dot3StatsLateCollisions) -
288745386Swpaul	   ifp->if_collisions;
2888153770Syongari
2889153770Syongari	bus_dmamap_sync(sc->ti_rdata_dmat, sc->ti_rdata_dmamap,
2890153770Syongari	    BUS_DMASYNC_PREREAD);
289145386Swpaul}
289245386Swpaul
2893153982Syongari/*
2894153982Syongari * Encapsulate an mbuf chain in the tx ring  by coupling the mbuf data
2895153982Syongari * pointers to descriptors.
2896153982Syongari */
2897153982Syongaristatic int
2898227086Syongariti_encap(struct ti_softc *sc, struct mbuf **m_head)
2899153396Sscottl{
2900227087Syongari	struct ti_txdesc *txd;
2901227087Syongari	struct ti_tx_desc *f;
2902227087Syongari	struct ti_tx_desc txdesc;
2903227087Syongari	struct mbuf *m;
2904227087Syongari	bus_dma_segment_t txsegs[TI_MAXTXSEGS];
2905227089Syongari	uint16_t csum_flags;
2906227087Syongari	int error, frag, i, nseg;
2907153396Sscottl
2908153982Syongari	if ((txd = STAILQ_FIRST(&sc->ti_cdata.ti_txfreeq)) == NULL)
2909153982Syongari		return (ENOBUFS);
2910153396Sscottl
2911153982Syongari	error = bus_dmamap_load_mbuf_sg(sc->ti_mbuftx_dmat, txd->tx_dmamap,
2912161236Syongari	    *m_head, txsegs, &nseg, 0);
2913153982Syongari	if (error == EFBIG) {
2914161236Syongari		m = m_defrag(*m_head, M_DONTWAIT);
2915161236Syongari		if (m == NULL) {
2916161236Syongari			m_freem(*m_head);
2917161236Syongari			*m_head = NULL;
2918153982Syongari			return (ENOMEM);
2919153982Syongari		}
2920161236Syongari		*m_head = m;
2921153982Syongari		error = bus_dmamap_load_mbuf_sg(sc->ti_mbuftx_dmat,
2922161236Syongari		    txd->tx_dmamap, *m_head, txsegs, &nseg, 0);
2923153982Syongari		if (error) {
2924161236Syongari			m_freem(*m_head);
2925161236Syongari			*m_head = NULL;
2926153982Syongari			return (error);
2927153982Syongari		}
2928153982Syongari	} else if (error != 0)
2929153982Syongari		return (error);
2930153982Syongari	if (nseg == 0) {
2931161236Syongari		m_freem(*m_head);
2932161236Syongari		*m_head = NULL;
2933153982Syongari		return (EIO);
2934153776Sscottl	}
2935153776Sscottl
2936153982Syongari	if (sc->ti_txcnt + nseg >= TI_TX_RING_CNT) {
2937153982Syongari		bus_dmamap_unload(sc->ti_mbuftx_dmat, txd->tx_dmamap);
2938153982Syongari		return (ENOBUFS);
2939153982Syongari	}
2940153982Syongari
2941161236Syongari	m = *m_head;
2942161236Syongari	csum_flags = 0;
2943161236Syongari	if (m->m_pkthdr.csum_flags) {
2944161236Syongari		if (m->m_pkthdr.csum_flags & CSUM_IP)
2945161236Syongari			csum_flags |= TI_BDFLAG_IP_CKSUM;
2946161236Syongari		if (m->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
2947161236Syongari			csum_flags |= TI_BDFLAG_TCP_UDP_CKSUM;
2948161236Syongari		if (m->m_flags & M_LASTFRAG)
2949161236Syongari			csum_flags |= TI_BDFLAG_IP_FRAG_END;
2950161236Syongari		else if (m->m_flags & M_FRAG)
2951161236Syongari			csum_flags |= TI_BDFLAG_IP_FRAG;
2952161236Syongari	}
2953161236Syongari
2954153982Syongari	bus_dmamap_sync(sc->ti_mbuftx_dmat, txd->tx_dmamap,
2955153982Syongari	    BUS_DMASYNC_PREWRITE);
2956153982Syongari	bus_dmamap_sync(sc->ti_rdata_dmat, sc->ti_rdata_dmamap,
2957153982Syongari	    BUS_DMASYNC_PREWRITE);
2958153982Syongari
2959153982Syongari	frag = sc->ti_tx_saved_prodidx;
2960153982Syongari	for (i = 0; i < nseg; i++) {
2961153396Sscottl		if (sc->ti_hwrev == TI_HWREV_TIGON) {
2962153770Syongari			bzero(&txdesc, sizeof(txdesc));
2963153770Syongari			f = &txdesc;
2964153396Sscottl		} else
2965153396Sscottl			f = &sc->ti_rdata->ti_tx_ring[frag];
2966153982Syongari		ti_hostaddr64(&f->ti_addr, txsegs[i].ds_addr);
2967153982Syongari		f->ti_len = txsegs[i].ds_len;
2968153396Sscottl		f->ti_flags = csum_flags;
2969162375Sandre		if (m->m_flags & M_VLANTAG) {
2970153396Sscottl			f->ti_flags |= TI_BDFLAG_VLAN_TAG;
2971227094Syongari			f->ti_vlan_tag = m->m_pkthdr.ether_vtag;
2972153396Sscottl		} else {
2973153396Sscottl			f->ti_vlan_tag = 0;
2974153396Sscottl		}
2975153396Sscottl
2976153770Syongari		if (sc->ti_hwrev == TI_HWREV_TIGON)
2977153770Syongari			ti_mem_write(sc, TI_TX_RING_BASE + frag *
2978153770Syongari			    sizeof(txdesc), sizeof(txdesc), &txdesc);
2979153396Sscottl		TI_INC(frag, TI_TX_RING_CNT);
2980153396Sscottl	}
2981153396Sscottl
2982153982Syongari	sc->ti_tx_saved_prodidx = frag;
2983153982Syongari	/* set TI_BDFLAG_END on the last descriptor */
2984153982Syongari	frag = (frag + TI_TX_RING_CNT - 1) % TI_TX_RING_CNT;
2985153770Syongari	if (sc->ti_hwrev == TI_HWREV_TIGON) {
2986153770Syongari		txdesc.ti_flags |= TI_BDFLAG_END;
2987153982Syongari		ti_mem_write(sc, TI_TX_RING_BASE + frag * sizeof(txdesc),
2988153770Syongari		    sizeof(txdesc), &txdesc);
2989153770Syongari	} else
2990153982Syongari		sc->ti_rdata->ti_tx_ring[frag].ti_flags |= TI_BDFLAG_END;
2991153396Sscottl
2992153982Syongari	STAILQ_REMOVE_HEAD(&sc->ti_cdata.ti_txfreeq, tx_q);
2993153982Syongari	STAILQ_INSERT_TAIL(&sc->ti_cdata.ti_txbusyq, txd, tx_q);
2994153982Syongari	txd->tx_m = m;
2995153982Syongari	sc->ti_txcnt += nseg;
299645386Swpaul
2997131654Sbms	return (0);
299845386Swpaul}
299945386Swpaul
3000153770Syongaristatic void
3001227086Syongariti_start(struct ifnet *ifp)
3002153770Syongari{
3003227087Syongari	struct ti_softc *sc;
3004153770Syongari
3005153770Syongari	sc = ifp->if_softc;
3006153770Syongari	TI_LOCK(sc);
3007153770Syongari	ti_start_locked(ifp);
3008153770Syongari	TI_UNLOCK(sc);
3009153770Syongari}
3010153770Syongari
301145386Swpaul/*
301245386Swpaul * Main transmit routine. To avoid having to do mbuf copies, we put pointers
301345386Swpaul * to the mbuf data regions directly in the transmit descriptors.
301445386Swpaul */
3015102336Salfredstatic void
3016227086Syongariti_start_locked(struct ifnet *ifp)
301745386Swpaul{
3018227087Syongari	struct ti_softc *sc;
3019227087Syongari	struct mbuf *m_head = NULL;
3020227087Syongari	int enq = 0;
302145386Swpaul
302245386Swpaul	sc = ifp->if_softc;
302345386Swpaul
3024227099Syongari	for (; !IFQ_DRV_IS_EMPTY(&ifp->if_snd) &&
3025153982Syongari	    sc->ti_txcnt < (TI_TX_RING_CNT - 16);) {
3026227099Syongari		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
302745386Swpaul		if (m_head == NULL)
302845386Swpaul			break;
302945386Swpaul
303045386Swpaul		/*
303158698Sjlemon		 * XXX
303258698Sjlemon		 * safety overkill.  If this is a fragmented packet chain
303358698Sjlemon		 * with delayed TCP/UDP checksums, then only encapsulate
303458698Sjlemon		 * it if we have enough descriptors to handle the entire
303558698Sjlemon		 * chain at once.
303658698Sjlemon		 * (paranoia -- may not actually be needed)
303758698Sjlemon		 */
303858698Sjlemon		if (m_head->m_flags & M_FIRSTFRAG &&
303958698Sjlemon		    m_head->m_pkthdr.csum_flags & (CSUM_DELAY_DATA)) {
304058698Sjlemon			if ((TI_TX_RING_CNT - sc->ti_txcnt) <
304158698Sjlemon			    m_head->m_pkthdr.csum_data + 16) {
3042227099Syongari				IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
3043148887Srwatson				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
304458698Sjlemon				break;
304558698Sjlemon			}
304658698Sjlemon		}
304758698Sjlemon
304858698Sjlemon		/*
304945386Swpaul		 * Pack the data into the transmit ring. If we
305045386Swpaul		 * don't have room, set the OACTIVE flag and wait
305145386Swpaul		 * for the NIC to drain the ring.
305245386Swpaul		 */
3053153982Syongari		if (ti_encap(sc, &m_head)) {
3054153982Syongari			if (m_head == NULL)
3055153982Syongari				break;
3056227099Syongari			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
3057148887Srwatson			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
305845386Swpaul			break;
305945386Swpaul		}
306045386Swpaul
3061153982Syongari		enq++;
306245386Swpaul		/*
306345386Swpaul		 * If there's a BPF listener, bounce a copy of this frame
306445386Swpaul		 * to him.
306545386Swpaul		 */
3066167190Scsjp		ETHER_BPF_MTAP(ifp, m_head);
306745386Swpaul	}
306845386Swpaul
3069153982Syongari	if (enq > 0) {
3070153982Syongari		/* Transmit */
3071153982Syongari		CSR_WRITE_4(sc, TI_MB_SENDPROD_IDX, sc->ti_tx_saved_prodidx);
307245386Swpaul
3073153982Syongari		/*
3074153982Syongari		 * Set a timeout in case the chip goes out to lunch.
3075153982Syongari		 */
3076199559Sjhb		sc->ti_timer = 5;
3077153982Syongari	}
307845386Swpaul}
307945386Swpaul
3080102336Salfredstatic void
3081227086Syongariti_init(void *xsc)
308245386Swpaul{
3083227087Syongari	struct ti_softc *sc;
3084153770Syongari
3085153770Syongari	sc = xsc;
3086153770Syongari	TI_LOCK(sc);
3087153770Syongari	ti_init_locked(sc);
3088153770Syongari	TI_UNLOCK(sc);
3089153770Syongari}
3090153770Syongari
3091153770Syongaristatic void
3092227086Syongariti_init_locked(void *xsc)
3093153770Syongari{
3094227087Syongari	struct ti_softc *sc = xsc;
309545386Swpaul
3096227312Syongari	if (sc->ti_ifp->if_drv_flags & IFF_DRV_RUNNING)
3097227312Syongari		return;
3098227312Syongari
309945386Swpaul	/* Cancel pending I/O and flush buffers. */
310045386Swpaul	ti_stop(sc);
310145386Swpaul
310245386Swpaul	/* Init the gen info block, ring control blocks and firmware. */
310345386Swpaul	if (ti_gibinit(sc)) {
3104162321Sglebius		device_printf(sc->ti_dev, "initialization failure\n");
310545386Swpaul		return;
310645386Swpaul	}
310745386Swpaul}
310845386Swpaul
3109227086Syongaristatic void ti_init2(struct ti_softc *sc)
311045386Swpaul{
3111227087Syongari	struct ti_cmd_desc cmd;
3112227087Syongari	struct ifnet *ifp;
3113227089Syongari	uint8_t *ea;
3114227087Syongari	struct ifmedia *ifm;
3115227087Syongari	int tmp;
311645386Swpaul
3117153770Syongari	TI_LOCK_ASSERT(sc);
3118153770Syongari
3119147256Sbrooks	ifp = sc->ti_ifp;
312045386Swpaul
312145386Swpaul	/* Specify MTU and interface index. */
3122227311Syongari	CSR_WRITE_4(sc, TI_GCR_IFINDEX, device_get_unit(sc->ti_dev));
312345386Swpaul	CSR_WRITE_4(sc, TI_GCR_IFMTU, ifp->if_mtu +
3124118454Ssimokawa	    ETHER_HDR_LEN + ETHER_CRC_LEN + ETHER_VLAN_ENCAP_LEN);
312545386Swpaul	TI_DO_CMD(TI_CMD_UPDATE_GENCOM, 0, 0);
312645386Swpaul
312745386Swpaul	/* Load our MAC address. */
3128153770Syongari	ea = IF_LLADDR(sc->ti_ifp);
3129153770Syongari	CSR_WRITE_4(sc, TI_GCR_PAR0, (ea[0] << 8) | ea[1]);
3130153770Syongari	CSR_WRITE_4(sc, TI_GCR_PAR1,
3131153770Syongari	    (ea[2] << 24) | (ea[3] << 16) | (ea[4] << 8) | ea[5]);
313245386Swpaul	TI_DO_CMD(TI_CMD_SET_MAC_ADDR, 0, 0);
313345386Swpaul
313445386Swpaul	/* Enable or disable promiscuous mode as needed. */
313545386Swpaul	if (ifp->if_flags & IFF_PROMISC) {
313645386Swpaul		TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_ENB, 0);
313745386Swpaul	} else {
313845386Swpaul		TI_DO_CMD(TI_CMD_SET_PROMISC_MODE, TI_CMD_CODE_PROMISC_DIS, 0);
313945386Swpaul	}
314045386Swpaul
314145386Swpaul	/* Program multicast filter. */
314245386Swpaul	ti_setmulti(sc);
314345386Swpaul
314445386Swpaul	/*
314545386Swpaul	 * If this is a Tigon 1, we should tell the
314645386Swpaul	 * firmware to use software packet filtering.
314745386Swpaul	 */
314845386Swpaul	if (sc->ti_hwrev == TI_HWREV_TIGON) {
314945386Swpaul		TI_DO_CMD(TI_CMD_FDR_FILTERING, TI_CMD_CODE_FILT_ENB, 0);
315045386Swpaul	}
315145386Swpaul
315245386Swpaul	/* Init RX ring. */
3153227322Syongari	if (ti_init_rx_ring_std(sc) != 0) {
3154227322Syongari		/* XXX */
3155227322Syongari		device_printf(sc->ti_dev, "no memory for std Rx buffers.\n");
3156227322Syongari		return;
3157227322Syongari	}
315845386Swpaul
315945386Swpaul	/* Init jumbo RX ring. */
3160227322Syongari	if (ifp->if_mtu > (ETHERMTU + ETHER_HDR_LEN + ETHER_CRC_LEN)) {
3161227322Syongari		if (ti_init_rx_ring_jumbo(sc) != 0) {
3162227322Syongari			/* XXX */
3163227322Syongari			device_printf(sc->ti_dev,
3164227322Syongari			    "no memory for jumbo Rx buffers.\n");
3165227322Syongari			return;
3166227322Syongari		}
3167227322Syongari	}
316845386Swpaul
316945386Swpaul	/*
317045386Swpaul	 * If this is a Tigon 2, we can also configure the
317145386Swpaul	 * mini ring.
317245386Swpaul	 */
3173227322Syongari	if (sc->ti_hwrev == TI_HWREV_TIGON_II) {
3174227322Syongari		if (ti_init_rx_ring_mini(sc) != 0) {
3175227322Syongari			/* XXX */
3176227322Syongari			device_printf(sc->ti_dev,
3177227322Syongari			    "no memory for mini Rx buffers.\n");
3178227322Syongari			return;
3179227322Syongari		}
3180227322Syongari	}
318145386Swpaul
318245386Swpaul	CSR_WRITE_4(sc, TI_GCR_RXRETURNCONS_IDX, 0);
318345386Swpaul	sc->ti_rx_saved_considx = 0;
318445386Swpaul
318545386Swpaul	/* Init TX ring. */
318645386Swpaul	ti_init_tx_ring(sc);
318745386Swpaul
318845386Swpaul	/* Tell firmware we're alive. */
318945386Swpaul	TI_DO_CMD(TI_CMD_HOST_STATE, TI_CMD_CODE_STACK_UP, 0);
319045386Swpaul
319145386Swpaul	/* Enable host interrupts. */
319245386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 0);
319345386Swpaul
3194148887Srwatson	ifp->if_drv_flags |= IFF_DRV_RUNNING;
3195148887Srwatson	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
3196199559Sjhb	callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc);
319745386Swpaul
319845386Swpaul	/*
319945386Swpaul	 * Make sure to set media properly. We have to do this
320045386Swpaul	 * here since we have to issue commands in order to set
320145386Swpaul	 * the link negotiation and we can't issue commands until
320245386Swpaul	 * the firmware is running.
320345386Swpaul	 */
320445386Swpaul	ifm = &sc->ifmedia;
320545386Swpaul	tmp = ifm->ifm_media;
320645386Swpaul	ifm->ifm_media = ifm->ifm_cur->ifm_media;
3207227093Syongari	ti_ifmedia_upd_locked(sc);
320845386Swpaul	ifm->ifm_media = tmp;
320945386Swpaul}
321045386Swpaul
321145386Swpaul/*
321245386Swpaul * Set media options.
321345386Swpaul */
3214102336Salfredstatic int
3215227086Syongariti_ifmedia_upd(struct ifnet *ifp)
321645386Swpaul{
3217227087Syongari	struct ti_softc *sc;
3218227093Syongari	int error;
3219227093Syongari
3220227093Syongari	sc = ifp->if_softc;
3221227093Syongari	TI_LOCK(sc);
3222227093Syongari	error = ti_ifmedia_upd(ifp);
3223227093Syongari	TI_UNLOCK(sc);
3224227093Syongari
3225227093Syongari	return (error);
3226227093Syongari}
3227227093Syongari
3228227093Syongaristatic int
3229227093Syongariti_ifmedia_upd_locked(struct ti_softc *sc)
3230227093Syongari{
3231227087Syongari	struct ifmedia *ifm;
3232227087Syongari	struct ti_cmd_desc cmd;
3233227089Syongari	uint32_t flowctl;
323445386Swpaul
323545386Swpaul	ifm = &sc->ifmedia;
323645386Swpaul
323745386Swpaul	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
3238131654Sbms		return (EINVAL);
323945386Swpaul
324098849Sken	flowctl = 0;
324198849Sken
3242131654Sbms	switch (IFM_SUBTYPE(ifm->ifm_media)) {
324345386Swpaul	case IFM_AUTO:
324498849Sken		/*
324598849Sken		 * Transmit flow control doesn't work on the Tigon 1.
324698849Sken		 */
324798849Sken		flowctl = TI_GLNK_RX_FLOWCTL_Y;
324898849Sken
324998849Sken		/*
325098849Sken		 * Transmit flow control can also cause problems on the
325198849Sken		 * Tigon 2, apparantly with both the copper and fiber
325298849Sken		 * boards.  The symptom is that the interface will just
325398849Sken		 * hang.  This was reproduced with Alteon 180 switches.
325498849Sken		 */
325598849Sken#if 0
325698849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
3257131652Sbms			flowctl |= TI_GLNK_TX_FLOWCTL_Y;
325898849Sken#endif
325998849Sken
326045386Swpaul		CSR_WRITE_4(sc, TI_GCR_GLINK, TI_GLNK_PREF|TI_GLNK_1000MB|
326198849Sken		    TI_GLNK_FULL_DUPLEX| flowctl |
326245386Swpaul		    TI_GLNK_AUTONEGENB|TI_GLNK_ENB);
326398849Sken
326498849Sken		flowctl = TI_LNK_RX_FLOWCTL_Y;
326598849Sken#if 0
326698849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
326798849Sken			flowctl |= TI_LNK_TX_FLOWCTL_Y;
326898849Sken#endif
326998849Sken
327045386Swpaul		CSR_WRITE_4(sc, TI_GCR_LINK, TI_LNK_100MB|TI_LNK_10MB|
327198849Sken		    TI_LNK_FULL_DUPLEX|TI_LNK_HALF_DUPLEX| flowctl |
327245386Swpaul		    TI_LNK_AUTONEGENB|TI_LNK_ENB);
327345386Swpaul		TI_DO_CMD(TI_CMD_LINK_NEGOTIATION,
327445386Swpaul		    TI_CMD_CODE_NEGOTIATE_BOTH, 0);
327545386Swpaul		break;
327645386Swpaul	case IFM_1000_SX:
327795673Sphk	case IFM_1000_T:
327898849Sken		flowctl = TI_GLNK_RX_FLOWCTL_Y;
327998849Sken#if 0
328098849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
3281131652Sbms			flowctl |= TI_GLNK_TX_FLOWCTL_Y;
328298849Sken#endif
328398849Sken
328445386Swpaul		CSR_WRITE_4(sc, TI_GCR_GLINK, TI_GLNK_PREF|TI_GLNK_1000MB|
328598849Sken		    flowctl |TI_GLNK_ENB);
328645386Swpaul		CSR_WRITE_4(sc, TI_GCR_LINK, 0);
328763699Swpaul		if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
328863699Swpaul			TI_SETBIT(sc, TI_GCR_GLINK, TI_GLNK_FULL_DUPLEX);
328963699Swpaul		}
329045386Swpaul		TI_DO_CMD(TI_CMD_LINK_NEGOTIATION,
329145386Swpaul		    TI_CMD_CODE_NEGOTIATE_GIGABIT, 0);
329245386Swpaul		break;
329345386Swpaul	case IFM_100_FX:
329445386Swpaul	case IFM_10_FL:
329563699Swpaul	case IFM_100_TX:
329663699Swpaul	case IFM_10_T:
329798849Sken		flowctl = TI_LNK_RX_FLOWCTL_Y;
329898849Sken#if 0
329998849Sken		if (sc->ti_hwrev != TI_HWREV_TIGON)
330098849Sken			flowctl |= TI_LNK_TX_FLOWCTL_Y;
330198849Sken#endif
330298849Sken
330345386Swpaul		CSR_WRITE_4(sc, TI_GCR_GLINK, 0);
330498849Sken		CSR_WRITE_4(sc, TI_GCR_LINK, TI_LNK_ENB|TI_LNK_PREF|flowctl);
330563699Swpaul		if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_FX ||
330663699Swpaul		    IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) {
330745386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_100MB);
330845386Swpaul		} else {
330945386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_10MB);
331045386Swpaul		}
331145386Swpaul		if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
331245386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_FULL_DUPLEX);
331345386Swpaul		} else {
331445386Swpaul			TI_SETBIT(sc, TI_GCR_LINK, TI_LNK_HALF_DUPLEX);
331545386Swpaul		}
331645386Swpaul		TI_DO_CMD(TI_CMD_LINK_NEGOTIATION,
331745386Swpaul		    TI_CMD_CODE_NEGOTIATE_10_100, 0);
331845386Swpaul		break;
331945386Swpaul	}
332045386Swpaul
3321131654Sbms	return (0);
332245386Swpaul}
332345386Swpaul
332445386Swpaul/*
332545386Swpaul * Report current media status.
332645386Swpaul */
3327102336Salfredstatic void
3328227086Syongariti_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
332945386Swpaul{
3330227087Syongari	struct ti_softc *sc;
3331227089Syongari	uint32_t media = 0;
333245386Swpaul
333345386Swpaul	sc = ifp->if_softc;
333445386Swpaul
3335227093Syongari	TI_LOCK(sc);
3336227093Syongari
333745386Swpaul	ifmr->ifm_status = IFM_AVALID;
333845386Swpaul	ifmr->ifm_active = IFM_ETHER;
333945386Swpaul
3340227093Syongari	if (sc->ti_linkstat == TI_EV_CODE_LINK_DOWN) {
3341227093Syongari		TI_UNLOCK(sc);
334245386Swpaul		return;
3343227093Syongari	}
334445386Swpaul
334545386Swpaul	ifmr->ifm_status |= IFM_ACTIVE;
334645386Swpaul
334763699Swpaul	if (sc->ti_linkstat == TI_EV_CODE_GIG_LINK_UP) {
334863699Swpaul		media = CSR_READ_4(sc, TI_GCR_GLINK_STAT);
334963699Swpaul		if (sc->ti_copper)
335095673Sphk			ifmr->ifm_active |= IFM_1000_T;
335163699Swpaul		else
335263699Swpaul			ifmr->ifm_active |= IFM_1000_SX;
335363699Swpaul		if (media & TI_GLNK_FULL_DUPLEX)
335463699Swpaul			ifmr->ifm_active |= IFM_FDX;
335563699Swpaul		else
335663699Swpaul			ifmr->ifm_active |= IFM_HDX;
335763699Swpaul	} else if (sc->ti_linkstat == TI_EV_CODE_LINK_UP) {
335845386Swpaul		media = CSR_READ_4(sc, TI_GCR_LINK_STAT);
335963699Swpaul		if (sc->ti_copper) {
336063699Swpaul			if (media & TI_LNK_100MB)
336163699Swpaul				ifmr->ifm_active |= IFM_100_TX;
336263699Swpaul			if (media & TI_LNK_10MB)
336363699Swpaul				ifmr->ifm_active |= IFM_10_T;
336463699Swpaul		} else {
336563699Swpaul			if (media & TI_LNK_100MB)
336663699Swpaul				ifmr->ifm_active |= IFM_100_FX;
336763699Swpaul			if (media & TI_LNK_10MB)
336863699Swpaul				ifmr->ifm_active |= IFM_10_FL;
336963699Swpaul		}
337045386Swpaul		if (media & TI_LNK_FULL_DUPLEX)
337145386Swpaul			ifmr->ifm_active |= IFM_FDX;
337245386Swpaul		if (media & TI_LNK_HALF_DUPLEX)
337345386Swpaul			ifmr->ifm_active |= IFM_HDX;
337445386Swpaul	}
3375227093Syongari	TI_UNLOCK(sc);
337645386Swpaul}
337745386Swpaul
3378102336Salfredstatic int
3379227086Syongariti_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
338045386Swpaul{
3381227087Syongari	struct ti_softc *sc = ifp->if_softc;
3382227087Syongari	struct ifreq *ifr = (struct ifreq *) data;
3383227087Syongari	struct ti_cmd_desc cmd;
3384227087Syongari	int mask, error = 0;
338545386Swpaul
3386131654Sbms	switch (command) {
338745386Swpaul	case SIOCSIFMTU:
3388153770Syongari		TI_LOCK(sc);
3389227324Syongari		if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > TI_JUMBO_MTU)
339045386Swpaul			error = EINVAL;
339145386Swpaul		else {
339245386Swpaul			ifp->if_mtu = ifr->ifr_mtu;
3393227312Syongari			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3394227312Syongari				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
3395227312Syongari				ti_init_locked(sc);
3396227312Syongari			}
339745386Swpaul		}
3398153770Syongari		TI_UNLOCK(sc);
339945386Swpaul		break;
340045386Swpaul	case SIOCSIFFLAGS:
3401153770Syongari		TI_LOCK(sc);
340245386Swpaul		if (ifp->if_flags & IFF_UP) {
340345386Swpaul			/*
340445386Swpaul			 * If only the state of the PROMISC flag changed,
340545386Swpaul			 * then just use the 'set promisc mode' command
340645386Swpaul			 * instead of reinitializing the entire NIC. Doing
340745386Swpaul			 * a full re-init means reloading the firmware and
340845386Swpaul			 * waiting for it to start up, which may take a
340945386Swpaul			 * second or two.
341045386Swpaul			 */
3411148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
341245386Swpaul			    ifp->if_flags & IFF_PROMISC &&
341345386Swpaul			    !(sc->ti_if_flags & IFF_PROMISC)) {
341445386Swpaul				TI_DO_CMD(TI_CMD_SET_PROMISC_MODE,
341545386Swpaul				    TI_CMD_CODE_PROMISC_ENB, 0);
3416148887Srwatson			} else if (ifp->if_drv_flags & IFF_DRV_RUNNING &&
341745386Swpaul			    !(ifp->if_flags & IFF_PROMISC) &&
341845386Swpaul			    sc->ti_if_flags & IFF_PROMISC) {
341945386Swpaul				TI_DO_CMD(TI_CMD_SET_PROMISC_MODE,
342045386Swpaul				    TI_CMD_CODE_PROMISC_DIS, 0);
342145386Swpaul			} else
3422153770Syongari				ti_init_locked(sc);
342345386Swpaul		} else {
3424148887Srwatson			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
342545386Swpaul				ti_stop(sc);
342645386Swpaul			}
342745386Swpaul		}
342845386Swpaul		sc->ti_if_flags = ifp->if_flags;
3429153770Syongari		TI_UNLOCK(sc);
343045386Swpaul		break;
343145386Swpaul	case SIOCADDMULTI:
343245386Swpaul	case SIOCDELMULTI:
3433153770Syongari		TI_LOCK(sc);
3434153770Syongari		if (ifp->if_drv_flags & IFF_DRV_RUNNING)
343545386Swpaul			ti_setmulti(sc);
3436153770Syongari		TI_UNLOCK(sc);
343745386Swpaul		break;
343845386Swpaul	case SIOCSIFMEDIA:
343945386Swpaul	case SIOCGIFMEDIA:
344045386Swpaul		error = ifmedia_ioctl(ifp, ifr, &sc->ifmedia, command);
344145386Swpaul		break;
344283630Sjlemon	case SIOCSIFCAP:
3443153770Syongari		TI_LOCK(sc);
344483630Sjlemon		mask = ifr->ifr_reqcap ^ ifp->if_capenable;
3445227095Syongari		if ((mask & IFCAP_TXCSUM) != 0 &&
3446227095Syongari		    (ifp->if_capabilities & IFCAP_TXCSUM) != 0) {
3447227095Syongari			ifp->if_capenable ^= IFCAP_TXCSUM;
3448227095Syongari			if ((ifp->if_capenable & IFCAP_TXCSUM) != 0)
3449227095Syongari				ifp->if_hwassist |= TI_CSUM_FEATURES;
3450227095Syongari                        else
3451227095Syongari				ifp->if_hwassist &= ~TI_CSUM_FEATURES;
3452227095Syongari                }
3453227095Syongari		if ((mask & IFCAP_RXCSUM) != 0 &&
3454227095Syongari		    (ifp->if_capabilities & IFCAP_RXCSUM) != 0)
3455227095Syongari			ifp->if_capenable ^= IFCAP_RXCSUM;
3456227095Syongari		if ((mask & IFCAP_VLAN_HWTAGGING) != 0 &&
3457227095Syongari		    (ifp->if_capabilities & IFCAP_VLAN_HWTAGGING) != 0)
3458227095Syongari                        ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING;
3459227095Syongari		if ((mask & IFCAP_VLAN_HWCSUM) != 0 &&
3460227095Syongari		    (ifp->if_capabilities & IFCAP_VLAN_HWCSUM) != 0)
3461227095Syongari			ifp->if_capenable ^= IFCAP_VLAN_HWCSUM;
3462227095Syongari		if ((mask & (IFCAP_TXCSUM | IFCAP_RXCSUM |
3463227095Syongari		    IFCAP_VLAN_HWTAGGING)) != 0) {
3464227095Syongari			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
3465227095Syongari				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
3466153770Syongari				ti_init_locked(sc);
3467227095Syongari			}
3468131655Sbms		}
3469153770Syongari		TI_UNLOCK(sc);
3470227095Syongari		VLAN_CAPABILITIES(ifp);
347183630Sjlemon		break;
347245386Swpaul	default:
3473106936Ssam		error = ether_ioctl(ifp, command, data);
347445386Swpaul		break;
347545386Swpaul	}
347645386Swpaul
3477131654Sbms	return (error);
347845386Swpaul}
347945386Swpaul
348098849Skenstatic int
3481130585Sphkti_open(struct cdev *dev, int flags, int fmt, struct thread *td)
348298849Sken{
348398849Sken	struct ti_softc *sc;
348498849Sken
3485120980Sphk	sc = dev->si_drv1;
348698849Sken	if (sc == NULL)
3487131654Sbms		return (ENODEV);
348898849Sken
348998849Sken	TI_LOCK(sc);
349098849Sken	sc->ti_flags |= TI_FLAG_DEBUGING;
349198849Sken	TI_UNLOCK(sc);
349298849Sken
3493131654Sbms	return (0);
349498849Sken}
349598849Sken
349698849Skenstatic int
3497130585Sphkti_close(struct cdev *dev, int flag, int fmt, struct thread *td)
349898849Sken{
349998849Sken	struct ti_softc *sc;
350098849Sken
3501120980Sphk	sc = dev->si_drv1;
350298849Sken	if (sc == NULL)
3503131654Sbms		return (ENODEV);
350498849Sken
350598849Sken	TI_LOCK(sc);
350698849Sken	sc->ti_flags &= ~TI_FLAG_DEBUGING;
350798849Sken	TI_UNLOCK(sc);
350898849Sken
3509131654Sbms	return (0);
351098849Sken}
351198849Sken
351298849Sken/*
351398849Sken * This ioctl routine goes along with the Tigon character device.
351498849Sken */
3515131652Sbmsstatic int
3516150719Sjhbti_ioctl2(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
3517150719Sjhb    struct thread *td)
351898849Sken{
3519227087Syongari	struct ti_softc *sc;
3520120980Sphk	int error;
352198849Sken
3522120980Sphk	sc = dev->si_drv1;
352398849Sken	if (sc == NULL)
3524131654Sbms		return (ENODEV);
352598849Sken
352698849Sken	error = 0;
352798849Sken
3528131654Sbms	switch (cmd) {
352998849Sken	case TIIOCGETSTATS:
353098849Sken	{
353198849Sken		struct ti_stats *outstats;
353298849Sken
353398849Sken		outstats = (struct ti_stats *)addr;
353498849Sken
3535153281Sscottl		TI_LOCK(sc);
353698849Sken		bcopy(&sc->ti_rdata->ti_info.ti_stats, outstats,
3537227431Syongari		    sizeof(struct ti_stats));
3538153281Sscottl		TI_UNLOCK(sc);
353998849Sken		break;
354098849Sken	}
354198849Sken	case TIIOCGETPARAMS:
354298849Sken	{
3543227087Syongari		struct ti_params *params;
354498849Sken
354598849Sken		params = (struct ti_params *)addr;
354698849Sken
3547153281Sscottl		TI_LOCK(sc);
354898849Sken		params->ti_stat_ticks = sc->ti_stat_ticks;
354998849Sken		params->ti_rx_coal_ticks = sc->ti_rx_coal_ticks;
355098849Sken		params->ti_tx_coal_ticks = sc->ti_tx_coal_ticks;
355198849Sken		params->ti_rx_max_coal_bds = sc->ti_rx_max_coal_bds;
355298849Sken		params->ti_tx_max_coal_bds = sc->ti_tx_max_coal_bds;
355398849Sken		params->ti_tx_buf_ratio = sc->ti_tx_buf_ratio;
355498849Sken		params->param_mask = TI_PARAM_ALL;
3555153281Sscottl		TI_UNLOCK(sc);
355698849Sken		break;
355798849Sken	}
355898849Sken	case TIIOCSETPARAMS:
355998849Sken	{
356098849Sken		struct ti_params *params;
356198849Sken
356298849Sken		params = (struct ti_params *)addr;
356398849Sken
3564153281Sscottl		TI_LOCK(sc);
356598849Sken		if (params->param_mask & TI_PARAM_STAT_TICKS) {
356698849Sken			sc->ti_stat_ticks = params->ti_stat_ticks;
356798849Sken			CSR_WRITE_4(sc, TI_GCR_STAT_TICKS, sc->ti_stat_ticks);
356898849Sken		}
356998849Sken
357098849Sken		if (params->param_mask & TI_PARAM_RX_COAL_TICKS) {
357198849Sken			sc->ti_rx_coal_ticks = params->ti_rx_coal_ticks;
357298849Sken			CSR_WRITE_4(sc, TI_GCR_RX_COAL_TICKS,
357398849Sken				    sc->ti_rx_coal_ticks);
357498849Sken		}
357598849Sken
357698849Sken		if (params->param_mask & TI_PARAM_TX_COAL_TICKS) {
357798849Sken			sc->ti_tx_coal_ticks = params->ti_tx_coal_ticks;
357898849Sken			CSR_WRITE_4(sc, TI_GCR_TX_COAL_TICKS,
357998849Sken				    sc->ti_tx_coal_ticks);
358098849Sken		}
358198849Sken
358298849Sken		if (params->param_mask & TI_PARAM_RX_COAL_BDS) {
358398849Sken			sc->ti_rx_max_coal_bds = params->ti_rx_max_coal_bds;
358498849Sken			CSR_WRITE_4(sc, TI_GCR_RX_MAX_COAL_BD,
358598849Sken				    sc->ti_rx_max_coal_bds);
358698849Sken		}
358798849Sken
358898849Sken		if (params->param_mask & TI_PARAM_TX_COAL_BDS) {
358998849Sken			sc->ti_tx_max_coal_bds = params->ti_tx_max_coal_bds;
359098849Sken			CSR_WRITE_4(sc, TI_GCR_TX_MAX_COAL_BD,
359198849Sken				    sc->ti_tx_max_coal_bds);
359298849Sken		}
359398849Sken
359498849Sken		if (params->param_mask & TI_PARAM_TX_BUF_RATIO) {
359598849Sken			sc->ti_tx_buf_ratio = params->ti_tx_buf_ratio;
359698849Sken			CSR_WRITE_4(sc, TI_GCR_TX_BUFFER_RATIO,
359798849Sken				    sc->ti_tx_buf_ratio);
359898849Sken		}
3599153281Sscottl		TI_UNLOCK(sc);
360098849Sken		break;
360198849Sken	}
360298849Sken	case TIIOCSETTRACE: {
3603227431Syongari		ti_trace_type trace_type;
360498849Sken
360598849Sken		trace_type = *(ti_trace_type *)addr;
360698849Sken
360798849Sken		/*
360898849Sken		 * Set tracing to whatever the user asked for.  Setting
360998849Sken		 * this register to 0 should have the effect of disabling
361098849Sken		 * tracing.
361198849Sken		 */
3612227505Syongari		TI_LOCK(sc);
361398849Sken		CSR_WRITE_4(sc, TI_GCR_NIC_TRACING, trace_type);
3614227505Syongari		TI_UNLOCK(sc);
361598849Sken		break;
361698849Sken	}
361798849Sken	case TIIOCGETTRACE: {
3618227087Syongari		struct ti_trace_buf *trace_buf;
3619227089Syongari		uint32_t trace_start, cur_trace_ptr, trace_len;
362098849Sken
362198849Sken		trace_buf = (struct ti_trace_buf *)addr;
362298849Sken
3623153281Sscottl		TI_LOCK(sc);
362498849Sken		trace_start = CSR_READ_4(sc, TI_GCR_NICTRACE_START);
362598849Sken		cur_trace_ptr = CSR_READ_4(sc, TI_GCR_NICTRACE_PTR);
362698849Sken		trace_len = CSR_READ_4(sc, TI_GCR_NICTRACE_LEN);
362798849Sken#if 0
3628150719Sjhb		if_printf(sc->ti_ifp, "trace_start = %#x, cur_trace_ptr = %#x, "
3629150719Sjhb		       "trace_len = %d\n", trace_start,
363098849Sken		       cur_trace_ptr, trace_len);
3631150719Sjhb		if_printf(sc->ti_ifp, "trace_buf->buf_len = %d\n",
363298849Sken		       trace_buf->buf_len);
363398849Sken#endif
363498849Sken		error = ti_copy_mem(sc, trace_start, min(trace_len,
3635227431Syongari		    trace_buf->buf_len), (caddr_t)trace_buf->buf, 1, 1);
363698849Sken		if (error == 0) {
363798849Sken			trace_buf->fill_len = min(trace_len,
3638227431Syongari			    trace_buf->buf_len);
363998849Sken			if (cur_trace_ptr < trace_start)
364098849Sken				trace_buf->cur_trace_ptr =
3641227431Syongari				    trace_start - cur_trace_ptr;
364298849Sken			else
364398849Sken				trace_buf->cur_trace_ptr =
3644227431Syongari				    cur_trace_ptr - trace_start;
364598849Sken		} else
364698849Sken			trace_buf->fill_len = 0;
3647153281Sscottl		TI_UNLOCK(sc);
364898849Sken		break;
364998849Sken	}
365098849Sken
365198849Sken	/*
365298849Sken	 * For debugging, five ioctls are needed:
365398849Sken	 * ALT_ATTACH
365498849Sken	 * ALT_READ_TG_REG
365598849Sken	 * ALT_WRITE_TG_REG
365698849Sken	 * ALT_READ_TG_MEM
365798849Sken	 * ALT_WRITE_TG_MEM
365898849Sken	 */
365998849Sken	case ALT_ATTACH:
366098849Sken		/*
3661131652Sbms		 * From what I can tell, Alteon's Solaris Tigon driver
366298849Sken		 * only has one character device, so you have to attach
366398849Sken		 * to the Tigon board you're interested in.  This seems
366498849Sken		 * like a not-so-good way to do things, since unless you
366598849Sken		 * subsequently specify the unit number of the device
3666177626Sbrueffer		 * you're interested in every ioctl, you'll only be
366798849Sken		 * able to debug one board at a time.
366898849Sken		 */
366998849Sken		break;
367098849Sken	case ALT_READ_TG_MEM:
367198849Sken	case ALT_WRITE_TG_MEM:
367298849Sken	{
367398849Sken		struct tg_mem *mem_param;
3674227089Syongari		uint32_t sram_end, scratch_end;
367598849Sken
367698849Sken		mem_param = (struct tg_mem *)addr;
367798849Sken
367898849Sken		if (sc->ti_hwrev == TI_HWREV_TIGON) {
367998849Sken			sram_end = TI_END_SRAM_I;
368098849Sken			scratch_end = TI_END_SCRATCH_I;
368198849Sken		} else {
368298849Sken			sram_end = TI_END_SRAM_II;
368398849Sken			scratch_end = TI_END_SCRATCH_II;
368498849Sken		}
368598849Sken
368698849Sken		/*
368798849Sken		 * For now, we'll only handle accessing regular SRAM,
368898849Sken		 * nothing else.
368998849Sken		 */
3690153281Sscottl		TI_LOCK(sc);
3691227431Syongari		if (mem_param->tgAddr >= TI_BEG_SRAM &&
3692227431Syongari		    mem_param->tgAddr + mem_param->len <= sram_end) {
369398849Sken			/*
369498849Sken			 * In this instance, we always copy to/from user
369598849Sken			 * space, so the user space argument is set to 1.
369698849Sken			 */
369798849Sken			error = ti_copy_mem(sc, mem_param->tgAddr,
3698227431Syongari			    mem_param->len, mem_param->userAddr, 1,
3699227431Syongari			    cmd == ALT_READ_TG_MEM ? 1 : 0);
3700227431Syongari		} else if (mem_param->tgAddr >= TI_BEG_SCRATCH &&
3701227431Syongari		    mem_param->tgAddr <= scratch_end) {
370298849Sken			error = ti_copy_scratch(sc, mem_param->tgAddr,
3703227431Syongari			    mem_param->len, mem_param->userAddr, 1,
3704227431Syongari			    cmd == ALT_READ_TG_MEM ?  1 : 0, TI_PROCESSOR_A);
3705227431Syongari		} else if (mem_param->tgAddr >= TI_BEG_SCRATCH_B_DEBUG &&
3706227431Syongari		    mem_param->tgAddr <= TI_BEG_SCRATCH_B_DEBUG) {
370798849Sken			if (sc->ti_hwrev == TI_HWREV_TIGON) {
3708150719Sjhb				if_printf(sc->ti_ifp,
3709150719Sjhb				    "invalid memory range for Tigon I\n");
371098849Sken				error = EINVAL;
371198849Sken				break;
371298849Sken			}
3713131652Sbms			error = ti_copy_scratch(sc, mem_param->tgAddr -
3714227431Syongari			    TI_SCRATCH_DEBUG_OFF, mem_param->len,
3715227431Syongari			    mem_param->userAddr, 1,
3716227431Syongari			    cmd == ALT_READ_TG_MEM ? 1 : 0, TI_PROCESSOR_B);
371798849Sken		} else {
3718150719Sjhb			if_printf(sc->ti_ifp, "memory address %#x len %d is "
3719150719Sjhb			        "out of supported range\n",
372098849Sken			        mem_param->tgAddr, mem_param->len);
372198849Sken			error = EINVAL;
372298849Sken		}
3723153281Sscottl		TI_UNLOCK(sc);
372498849Sken		break;
372598849Sken	}
372698849Sken	case ALT_READ_TG_REG:
372798849Sken	case ALT_WRITE_TG_REG:
372898849Sken	{
3729227431Syongari		struct tg_reg *regs;
3730227431Syongari		uint32_t tmpval;
373198849Sken
373298849Sken		regs = (struct tg_reg *)addr;
373398849Sken
373498849Sken		/*
373598849Sken		 * Make sure the address in question isn't out of range.
373698849Sken		 */
373798849Sken		if (regs->addr > TI_REG_MAX) {
373898849Sken			error = EINVAL;
373998849Sken			break;
374098849Sken		}
3741153281Sscottl		TI_LOCK(sc);
374298849Sken		if (cmd == ALT_READ_TG_REG) {
374398849Sken			bus_space_read_region_4(sc->ti_btag, sc->ti_bhandle,
3744227431Syongari			    regs->addr, &tmpval, 1);
374598849Sken			regs->data = ntohl(tmpval);
374698849Sken#if 0
374798849Sken			if ((regs->addr == TI_CPU_STATE)
374898849Sken			 || (regs->addr == TI_CPU_CTL_B)) {
3749150719Sjhb				if_printf(sc->ti_ifp, "register %#x = %#x\n",
3750150719Sjhb				       regs->addr, tmpval);
375198849Sken			}
375298849Sken#endif
375398849Sken		} else {
375498849Sken			tmpval = htonl(regs->data);
375598849Sken			bus_space_write_region_4(sc->ti_btag, sc->ti_bhandle,
3756227431Syongari			    regs->addr, &tmpval, 1);
375798849Sken		}
3758153281Sscottl		TI_UNLOCK(sc);
375998849Sken		break;
376098849Sken	}
376198849Sken	default:
376298849Sken		error = ENOTTY;
376398849Sken		break;
376498849Sken	}
3765131654Sbms	return (error);
376698849Sken}
376798849Sken
3768102336Salfredstatic void
3769199559Sjhbti_watchdog(void *arg)
377045386Swpaul{
3771227087Syongari	struct ti_softc *sc;
3772227087Syongari	struct ifnet *ifp;
377345386Swpaul
3774199559Sjhb	sc = arg;
3775199559Sjhb	TI_LOCK_ASSERT(sc);
3776199559Sjhb	callout_reset(&sc->ti_watchdog, hz, ti_watchdog, sc);
3777199559Sjhb	if (sc->ti_timer == 0 || --sc->ti_timer > 0)
3778199559Sjhb		return;
377945386Swpaul
378098849Sken	/*
378198849Sken	 * When we're debugging, the chip is often stopped for long periods
378298849Sken	 * of time, and that would normally cause the watchdog timer to fire.
378398849Sken	 * Since that impedes debugging, we don't want to do that.
378498849Sken	 */
3785199559Sjhb	if (sc->ti_flags & TI_FLAG_DEBUGING)
378698849Sken		return;
378798849Sken
3788199559Sjhb	ifp = sc->ti_ifp;
3789150719Sjhb	if_printf(ifp, "watchdog timeout -- resetting\n");
3790227312Syongari	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
3791153770Syongari	ti_init_locked(sc);
379245386Swpaul
379345386Swpaul	ifp->if_oerrors++;
379445386Swpaul}
379545386Swpaul
379645386Swpaul/*
379745386Swpaul * Stop the adapter and free any mbufs allocated to the
379845386Swpaul * RX and TX lists.
379945386Swpaul */
3800102336Salfredstatic void
3801227086Syongariti_stop(struct ti_softc *sc)
380245386Swpaul{
3803227087Syongari	struct ifnet *ifp;
3804227087Syongari	struct ti_cmd_desc cmd;
380545386Swpaul
3806153770Syongari	TI_LOCK_ASSERT(sc);
380767087Swpaul
3808147256Sbrooks	ifp = sc->ti_ifp;
380945386Swpaul
381045386Swpaul	/* Disable host interrupts. */
381145386Swpaul	CSR_WRITE_4(sc, TI_MB_HOSTINTR, 1);
381245386Swpaul	/*
381345386Swpaul	 * Tell firmware we're shutting down.
381445386Swpaul	 */
381545386Swpaul	TI_DO_CMD(TI_CMD_HOST_STATE, TI_CMD_CODE_STACK_DOWN, 0);
381645386Swpaul
381745386Swpaul	/* Halt and reinitialize. */
3818227323Syongari	if (ti_chipinit(sc) == 0) {
3819227323Syongari		ti_mem_zero(sc, 0x2000, 0x100000 - 0x2000);
3820227323Syongari		/* XXX ignore init errors. */
3821227323Syongari		ti_chipinit(sc);
3822227323Syongari	}
382345386Swpaul
382445386Swpaul	/* Free the RX lists. */
382545386Swpaul	ti_free_rx_ring_std(sc);
382645386Swpaul
382745386Swpaul	/* Free jumbo RX list. */
382845386Swpaul	ti_free_rx_ring_jumbo(sc);
382945386Swpaul
383045386Swpaul	/* Free mini RX list. */
383145386Swpaul	ti_free_rx_ring_mini(sc);
383245386Swpaul
383345386Swpaul	/* Free TX buffers. */
383445386Swpaul	ti_free_tx_ring(sc);
383545386Swpaul
383645386Swpaul	sc->ti_ev_prodidx.ti_idx = 0;
383745386Swpaul	sc->ti_return_prodidx.ti_idx = 0;
383845386Swpaul	sc->ti_tx_considx.ti_idx = 0;
383945386Swpaul	sc->ti_tx_saved_considx = TI_TXCONS_UNSET;
384045386Swpaul
3841148887Srwatson	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3842199559Sjhb	callout_stop(&sc->ti_watchdog);
384345386Swpaul}
384445386Swpaul
384545386Swpaul/*
384645386Swpaul * Stop all chip I/O so that the kernel's probe routines don't
384745386Swpaul * get confused by errant DMAs when rebooting.
384845386Swpaul */
3849173839Syongaristatic int
3850227086Syongariti_shutdown(device_t dev)
385145386Swpaul{
3852227087Syongari	struct ti_softc *sc;
385345386Swpaul
385449011Swpaul	sc = device_get_softc(dev);
385567087Swpaul	TI_LOCK(sc);
385645386Swpaul	ti_chipinit(sc);
385767087Swpaul	TI_UNLOCK(sc);
3858173839Syongari
3859173839Syongari	return (0);
386045386Swpaul}
3861