if_txp.c revision 148654
1/*	$OpenBSD: if_txp.c,v 1.48 2001/06/27 06:34:50 kjc Exp $	*/
2
3/*-
4 * Copyright (c) 2001
5 *	Jason L. Wright <jason@thought.net>, Theo de Raadt, and
6 *	Aaron Campbell <aaron@monkey.org>.  All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by Jason L. Wright,
19 *	Theo de Raadt and Aaron Campbell.
20 * 4. Neither the name of the author nor the names of any co-contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
34 * THE POSSIBILITY OF SUCH DAMAGE.
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/dev/txp/if_txp.c 148654 2005-08-03 00:18:35Z rwatson $");
39
40/*
41 * Driver for 3c990 (Typhoon) Ethernet ASIC
42 */
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: head/sys/dev/txp/if_txp.c 148654 2005-08-03 00:18:35Z rwatson $");
46
47#include <sys/param.h>
48#include <sys/systm.h>
49#include <sys/sockio.h>
50#include <sys/mbuf.h>
51#include <sys/malloc.h>
52#include <sys/kernel.h>
53#include <sys/module.h>
54#include <sys/socket.h>
55
56#include <net/if.h>
57#include <net/if_arp.h>
58#include <net/ethernet.h>
59#include <net/if_dl.h>
60#include <net/if_types.h>
61#include <net/if_vlan_var.h>
62
63#include <netinet/in.h>
64#include <netinet/in_systm.h>
65#include <netinet/in_var.h>
66#include <netinet/ip.h>
67#include <netinet/if_ether.h>
68#include <machine/in_cksum.h>
69
70#include <net/if_media.h>
71
72#include <net/bpf.h>
73
74#include <vm/vm.h>              /* for vtophys */
75#include <vm/pmap.h>            /* for vtophys */
76#include <machine/clock.h>	/* for DELAY */
77#include <machine/bus.h>
78#include <machine/resource.h>
79#include <sys/bus.h>
80#include <sys/rman.h>
81
82#include <dev/mii/mii.h>
83#include <dev/mii/miivar.h>
84#include <dev/pci/pcireg.h>
85#include <dev/pci/pcivar.h>
86
87#define TXP_USEIOSPACE
88#define __STRICT_ALIGNMENT
89
90#include <dev/txp/if_txpreg.h>
91#include <dev/txp/3c990img.h>
92
93#ifndef lint
94static const char rcsid[] =
95  "$FreeBSD: head/sys/dev/txp/if_txp.c 148654 2005-08-03 00:18:35Z rwatson $";
96#endif
97
98/*
99 * Various supported device vendors/types and their names.
100 */
101static struct txp_type txp_devs[] = {
102	{ TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_TX_95,
103	    "3Com 3cR990-TX-95 Etherlink with 3XP Processor" },
104	{ TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_TX_97,
105	    "3Com 3cR990-TX-97 Etherlink with 3XP Processor" },
106	{ TXP_VENDORID_3COM, TXP_DEVICEID_3CR990B_TXM,
107	    "3Com 3cR990B-TXM Etherlink with 3XP Processor" },
108	{ TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_SRV_95,
109	    "3Com 3cR990-SRV-95 Etherlink Server with 3XP Processor" },
110	{ TXP_VENDORID_3COM, TXP_DEVICEID_3CR990_SRV_97,
111	    "3Com 3cR990-SRV-97 Etherlink Server with 3XP Processor" },
112	{ TXP_VENDORID_3COM, TXP_DEVICEID_3CR990B_SRV,
113	    "3Com 3cR990B-SRV Etherlink Server with 3XP Processor" },
114	{ 0, 0, NULL }
115};
116
117static int txp_probe	(device_t);
118static int txp_attach	(device_t);
119static int txp_detach	(device_t);
120static void txp_intr	(void *);
121static void txp_tick	(void *);
122static int txp_shutdown	(device_t);
123static int txp_ioctl	(struct ifnet *, u_long, caddr_t);
124static void txp_start	(struct ifnet *);
125static void txp_stop	(struct txp_softc *);
126static void txp_init	(void *);
127static void txp_watchdog	(struct ifnet *);
128
129static void txp_release_resources(struct txp_softc *);
130static int txp_chip_init(struct txp_softc *);
131static int txp_reset_adapter(struct txp_softc *);
132static int txp_download_fw(struct txp_softc *);
133static int txp_download_fw_wait(struct txp_softc *);
134static int txp_download_fw_section (struct txp_softc *,
135    struct txp_fw_section_header *, int);
136static int txp_alloc_rings(struct txp_softc *);
137static int txp_rxring_fill(struct txp_softc *);
138static void txp_rxring_empty(struct txp_softc *);
139static void txp_set_filter(struct txp_softc *);
140
141static int txp_cmd_desc_numfree(struct txp_softc *);
142static int txp_command (struct txp_softc *, u_int16_t, u_int16_t, u_int32_t,
143    u_int32_t, u_int16_t *, u_int32_t *, u_int32_t *, int);
144static int txp_command2 (struct txp_softc *, u_int16_t, u_int16_t,
145    u_int32_t, u_int32_t, struct txp_ext_desc *, u_int8_t,
146    struct txp_rsp_desc **, int);
147static int txp_response (struct txp_softc *, u_int32_t, u_int16_t, u_int16_t,
148    struct txp_rsp_desc **);
149static void txp_rsp_fixup (struct txp_softc *, struct txp_rsp_desc *,
150    struct txp_rsp_desc *);
151static void txp_capabilities(struct txp_softc *);
152
153static void txp_ifmedia_sts(struct ifnet *, struct ifmediareq *);
154static int txp_ifmedia_upd(struct ifnet *);
155#ifdef TXP_DEBUG
156static void txp_show_descriptor(void *);
157#endif
158static void txp_tx_reclaim(struct txp_softc *, struct txp_tx_ring *);
159static void txp_rxbuf_reclaim(struct txp_softc *);
160static void txp_rx_reclaim(struct txp_softc *, struct txp_rx_ring *);
161
162#ifdef TXP_USEIOSPACE
163#define TXP_RES			SYS_RES_IOPORT
164#define TXP_RID			TXP_PCI_LOIO
165#else
166#define TXP_RES			SYS_RES_MEMORY
167#define TXP_RID			TXP_PCI_LOMEM
168#endif
169
170static device_method_t txp_methods[] = {
171        /* Device interface */
172	DEVMETHOD(device_probe,		txp_probe),
173	DEVMETHOD(device_attach,	txp_attach),
174	DEVMETHOD(device_detach,	txp_detach),
175	DEVMETHOD(device_shutdown,	txp_shutdown),
176	{ 0, 0 }
177};
178
179static driver_t txp_driver = {
180	"txp",
181	txp_methods,
182	sizeof(struct txp_softc)
183};
184
185static devclass_t txp_devclass;
186
187DRIVER_MODULE(txp, pci, txp_driver, txp_devclass, 0, 0);
188MODULE_DEPEND(txp, pci, 1, 1, 1);
189MODULE_DEPEND(txp, ether, 1, 1, 1);
190
191static int
192txp_probe(dev)
193	device_t dev;
194{
195	struct txp_type *t;
196
197	t = txp_devs;
198
199	while(t->txp_name != NULL) {
200		if ((pci_get_vendor(dev) == t->txp_vid) &&
201		    (pci_get_device(dev) == t->txp_did)) {
202			device_set_desc(dev, t->txp_name);
203			return(BUS_PROBE_DEFAULT);
204		}
205		t++;
206	}
207
208	return(ENXIO);
209}
210
211static int
212txp_attach(dev)
213	device_t dev;
214{
215	struct txp_softc *sc;
216	struct ifnet *ifp;
217	u_int16_t p1;
218	u_int32_t p2;
219	int unit, error = 0, rid;
220	u_char eaddr[6];
221
222	sc = device_get_softc(dev);
223	unit = device_get_unit(dev);
224	sc->sc_dev = dev;
225	sc->sc_cold = 1;
226
227	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
228	    MTX_DEF | MTX_RECURSE);
229	/*
230	 * Map control/status registers.
231	 */
232	pci_enable_busmaster(dev);
233
234	rid = TXP_RID;
235	sc->sc_res = bus_alloc_resource_any(dev, TXP_RES, &rid,
236	    RF_ACTIVE);
237
238	if (sc->sc_res == NULL) {
239		device_printf(dev, "couldn't map ports/memory\n");
240		error = ENXIO;
241		goto fail;
242	}
243
244	sc->sc_bt = rman_get_bustag(sc->sc_res);
245	sc->sc_bh = rman_get_bushandle(sc->sc_res);
246
247	/* Allocate interrupt */
248	rid = 0;
249	sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
250	    RF_SHAREABLE | RF_ACTIVE);
251
252	if (sc->sc_irq == NULL) {
253		device_printf(dev, "couldn't map interrupt\n");
254		txp_release_resources(sc);
255		error = ENXIO;
256		goto fail;
257	}
258
259	error = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_NET,
260	    txp_intr, sc, &sc->sc_intrhand);
261
262	if (error) {
263		txp_release_resources(sc);
264		device_printf(dev, "couldn't set up irq\n");
265		goto fail;
266	}
267
268	if (txp_chip_init(sc)) {
269		txp_release_resources(sc);
270		/* XXX: set error to ??? */
271		goto fail;
272	}
273
274	sc->sc_fwbuf = contigmalloc(32768, M_DEVBUF,
275	    M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
276	error = txp_download_fw(sc);
277	contigfree(sc->sc_fwbuf, 32768, M_DEVBUF);
278	sc->sc_fwbuf = NULL;
279
280	if (error) {
281		txp_release_resources(sc);
282		goto fail;
283	}
284
285	sc->sc_ldata = contigmalloc(sizeof(struct txp_ldata), M_DEVBUF,
286	    M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
287	bzero(sc->sc_ldata, sizeof(struct txp_ldata));
288
289	if (txp_alloc_rings(sc)) {
290		txp_release_resources(sc);
291		/* XXX: set error to ??? */
292		goto fail;
293	}
294
295	if (txp_command(sc, TXP_CMD_MAX_PKT_SIZE_WRITE, TXP_MAX_PKTLEN, 0, 0,
296	    NULL, NULL, NULL, 1)) {
297		txp_release_resources(sc);
298		/* XXX: set error to ??? */
299		goto fail;
300	}
301
302	if (txp_command(sc, TXP_CMD_STATION_ADDRESS_READ, 0, 0, 0,
303	    &p1, &p2, NULL, 1)) {
304		txp_release_resources(sc);
305		/* XXX: set error to ??? */
306		goto fail;
307	}
308
309	txp_set_filter(sc);
310
311	eaddr[0] = ((u_int8_t *)&p1)[1];
312	eaddr[1] = ((u_int8_t *)&p1)[0];
313	eaddr[2] = ((u_int8_t *)&p2)[3];
314	eaddr[3] = ((u_int8_t *)&p2)[2];
315	eaddr[4] = ((u_int8_t *)&p2)[1];
316	eaddr[5] = ((u_int8_t *)&p2)[0];
317
318	sc->sc_cold = 0;
319
320	ifmedia_init(&sc->sc_ifmedia, 0, txp_ifmedia_upd, txp_ifmedia_sts);
321	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T, 0, NULL);
322	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
323	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
324	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX, 0, NULL);
325	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_HDX, 0, NULL);
326	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL);
327	ifmedia_add(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
328
329	sc->sc_xcvr = TXP_XCVR_AUTO;
330	txp_command(sc, TXP_CMD_XCVR_SELECT, TXP_XCVR_AUTO, 0, 0,
331	    NULL, NULL, NULL, 0);
332	ifmedia_set(&sc->sc_ifmedia, IFM_ETHER|IFM_AUTO);
333
334	ifp = sc->sc_ifp = if_alloc(IFT_ETHER);
335	if (ifp == NULL) {
336		txp_release_resources(sc);
337		device_printf(dev, "couldn't set up irq\n");
338		error = ENOSPC;
339		goto fail;
340	}
341	ifp->if_softc = sc;
342	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
343	ifp->if_mtu = ETHERMTU;
344	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST |
345	    IFF_NEEDSGIANT;
346	ifp->if_ioctl = txp_ioctl;
347	ifp->if_start = txp_start;
348	ifp->if_watchdog = txp_watchdog;
349	ifp->if_init = txp_init;
350	ifp->if_baudrate = 100000000;
351	ifp->if_snd.ifq_maxlen = TX_ENTRIES;
352	ifp->if_hwassist = 0;
353	txp_capabilities(sc);
354
355	/*
356	 * Attach us everywhere
357	 */
358	ether_ifattach(ifp, eaddr);
359	callout_handle_init(&sc->sc_tick);
360	return(0);
361
362fail:
363	txp_release_resources(sc);
364	mtx_destroy(&sc->sc_mtx);
365	return(error);
366}
367
368static int
369txp_detach(dev)
370	device_t dev;
371{
372	struct txp_softc *sc;
373	struct ifnet *ifp;
374	int i;
375
376	sc = device_get_softc(dev);
377	ifp = sc->sc_ifp;
378
379	txp_stop(sc);
380	txp_shutdown(dev);
381
382	ifmedia_removeall(&sc->sc_ifmedia);
383	ether_ifdetach(ifp);
384
385	for (i = 0; i < RXBUF_ENTRIES; i++)
386		free(sc->sc_rxbufs[i].rb_sd, M_DEVBUF);
387
388	txp_release_resources(sc);
389
390	mtx_destroy(&sc->sc_mtx);
391	return(0);
392}
393
394static void
395txp_release_resources(sc)
396	struct txp_softc *sc;
397{
398	device_t dev;
399
400	dev = sc->sc_dev;
401
402	if (sc->sc_ifp)
403		if_free(sc->sc_ifp);
404
405	if (sc->sc_intrhand != NULL)
406		bus_teardown_intr(dev, sc->sc_irq, sc->sc_intrhand);
407
408	if (sc->sc_irq != NULL)
409		bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_irq);
410
411	if (sc->sc_res != NULL)
412		bus_release_resource(dev, TXP_RES, TXP_RID, sc->sc_res);
413
414	if (sc->sc_ldata != NULL)
415		contigfree(sc->sc_ldata, sizeof(struct txp_ldata), M_DEVBUF);
416
417	return;
418}
419
420static int
421txp_chip_init(sc)
422	struct txp_softc *sc;
423{
424	/* disable interrupts */
425	WRITE_REG(sc, TXP_IER, 0);
426	WRITE_REG(sc, TXP_IMR,
427	    TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
428	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
429	    TXP_INT_LATCH);
430
431	/* ack all interrupts */
432	WRITE_REG(sc, TXP_ISR, TXP_INT_RESERVED | TXP_INT_LATCH |
433	    TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
434	    TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
435	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
436	    TXP_INT_A2H_3 | TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0);
437
438	if (txp_reset_adapter(sc))
439		return (-1);
440
441	/* disable interrupts */
442	WRITE_REG(sc, TXP_IER, 0);
443	WRITE_REG(sc, TXP_IMR,
444	    TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
445	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
446	    TXP_INT_LATCH);
447
448	/* ack all interrupts */
449	WRITE_REG(sc, TXP_ISR, TXP_INT_RESERVED | TXP_INT_LATCH |
450	    TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
451	    TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
452	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
453	    TXP_INT_A2H_3 | TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0);
454
455	return (0);
456}
457
458static int
459txp_reset_adapter(sc)
460	struct txp_softc *sc;
461{
462	u_int32_t r;
463	int i;
464
465	r = 0;
466	WRITE_REG(sc, TXP_SRR, TXP_SRR_ALL);
467	DELAY(1000);
468	WRITE_REG(sc, TXP_SRR, 0);
469
470	/* Should wait max 6 seconds */
471	for (i = 0; i < 6000; i++) {
472		r = READ_REG(sc, TXP_A2H_0);
473		if (r == STAT_WAITING_FOR_HOST_REQUEST)
474			break;
475		DELAY(1000);
476	}
477
478	if (r != STAT_WAITING_FOR_HOST_REQUEST) {
479		device_printf(sc->sc_dev, "reset hung\n");
480		return (-1);
481	}
482
483	return (0);
484}
485
486static int
487txp_download_fw(sc)
488	struct txp_softc *sc;
489{
490	struct txp_fw_file_header *fileheader;
491	struct txp_fw_section_header *secthead;
492	int sect;
493	u_int32_t r, i, ier, imr;
494
495	r = 0;
496	ier = READ_REG(sc, TXP_IER);
497	WRITE_REG(sc, TXP_IER, ier | TXP_INT_A2H_0);
498
499	imr = READ_REG(sc, TXP_IMR);
500	WRITE_REG(sc, TXP_IMR, imr | TXP_INT_A2H_0);
501
502	for (i = 0; i < 10000; i++) {
503		r = READ_REG(sc, TXP_A2H_0);
504		if (r == STAT_WAITING_FOR_HOST_REQUEST)
505			break;
506		DELAY(50);
507	}
508	if (r != STAT_WAITING_FOR_HOST_REQUEST) {
509		device_printf(sc->sc_dev, "not waiting for host request\n");
510		return (-1);
511	}
512
513	/* Ack the status */
514	WRITE_REG(sc, TXP_ISR, TXP_INT_A2H_0);
515
516	fileheader = (struct txp_fw_file_header *)tc990image;
517	if (bcmp("TYPHOON", fileheader->magicid, sizeof(fileheader->magicid))) {
518		device_printf(sc->sc_dev, "fw invalid magic\n");
519		return (-1);
520	}
521
522	/* Tell boot firmware to get ready for image */
523	WRITE_REG(sc, TXP_H2A_1, fileheader->addr);
524	WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_RUNTIME_IMAGE);
525
526	if (txp_download_fw_wait(sc)) {
527		device_printf(sc->sc_dev, "fw wait failed, initial\n");
528		return (-1);
529	}
530
531	secthead = (struct txp_fw_section_header *)(((u_int8_t *)tc990image) +
532	    sizeof(struct txp_fw_file_header));
533
534	for (sect = 0; sect < fileheader->nsections; sect++) {
535		if (txp_download_fw_section(sc, secthead, sect))
536			return (-1);
537		secthead = (struct txp_fw_section_header *)
538		    (((u_int8_t *)secthead) + secthead->nbytes +
539		    sizeof(*secthead));
540	}
541
542	WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_DOWNLOAD_COMPLETE);
543
544	for (i = 0; i < 10000; i++) {
545		r = READ_REG(sc, TXP_A2H_0);
546		if (r == STAT_WAITING_FOR_BOOT)
547			break;
548		DELAY(50);
549	}
550	if (r != STAT_WAITING_FOR_BOOT) {
551		device_printf(sc->sc_dev, "not waiting for boot\n");
552		return (-1);
553	}
554
555	WRITE_REG(sc, TXP_IER, ier);
556	WRITE_REG(sc, TXP_IMR, imr);
557
558	return (0);
559}
560
561static int
562txp_download_fw_wait(sc)
563	struct txp_softc *sc;
564{
565	u_int32_t i, r;
566
567	r = 0;
568	for (i = 0; i < 10000; i++) {
569		r = READ_REG(sc, TXP_ISR);
570		if (r & TXP_INT_A2H_0)
571			break;
572		DELAY(50);
573	}
574
575	if (!(r & TXP_INT_A2H_0)) {
576		device_printf(sc->sc_dev, "fw wait failed comm0\n");
577		return (-1);
578	}
579
580	WRITE_REG(sc, TXP_ISR, TXP_INT_A2H_0);
581
582	r = READ_REG(sc, TXP_A2H_0);
583	if (r != STAT_WAITING_FOR_SEGMENT) {
584		device_printf(sc->sc_dev, "fw not waiting for segment\n");
585		return (-1);
586	}
587	return (0);
588}
589
590static int
591txp_download_fw_section(sc, sect, sectnum)
592	struct txp_softc *sc;
593	struct txp_fw_section_header *sect;
594	int sectnum;
595{
596	vm_offset_t dma;
597	int rseg, err = 0;
598	struct mbuf m;
599	u_int16_t csum;
600
601	/* Skip zero length sections */
602	if (sect->nbytes == 0)
603		return (0);
604
605	/* Make sure we aren't past the end of the image */
606	rseg = ((u_int8_t *)sect) - ((u_int8_t *)tc990image);
607	if (rseg >= sizeof(tc990image)) {
608		device_printf(sc->sc_dev, "fw invalid section address, "
609		    "section %d\n", sectnum);
610		return (-1);
611	}
612
613	/* Make sure this section doesn't go past the end */
614	rseg += sect->nbytes;
615	if (rseg >= sizeof(tc990image)) {
616		device_printf(sc->sc_dev, "fw truncated section %d\n",
617		    sectnum);
618		return (-1);
619	}
620
621	bcopy(((u_int8_t *)sect) + sizeof(*sect), sc->sc_fwbuf, sect->nbytes);
622	dma = vtophys(sc->sc_fwbuf);
623
624	/*
625	 * dummy up mbuf and verify section checksum
626	 */
627	m.m_type = MT_DATA;
628	m.m_next = m.m_nextpkt = NULL;
629	m.m_len = sect->nbytes;
630	m.m_data = sc->sc_fwbuf;
631	m.m_flags = 0;
632	csum = in_cksum(&m, sect->nbytes);
633	if (csum != sect->cksum) {
634		device_printf(sc->sc_dev, "fw section %d, bad "
635		    "cksum (expected 0x%x got 0x%x)\n",
636		    sectnum, sect->cksum, csum);
637		err = -1;
638		goto bail;
639	}
640
641	WRITE_REG(sc, TXP_H2A_1, sect->nbytes);
642	WRITE_REG(sc, TXP_H2A_2, sect->cksum);
643	WRITE_REG(sc, TXP_H2A_3, sect->addr);
644	WRITE_REG(sc, TXP_H2A_4, 0);
645	WRITE_REG(sc, TXP_H2A_5, dma & 0xffffffff);
646	WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_SEGMENT_AVAILABLE);
647
648	if (txp_download_fw_wait(sc)) {
649		device_printf(sc->sc_dev, "fw wait failed, "
650		    "section %d\n", sectnum);
651		err = -1;
652	}
653
654bail:
655	return (err);
656}
657
658static void
659txp_intr(vsc)
660	void *vsc;
661{
662	struct txp_softc *sc = vsc;
663	struct txp_hostvar *hv = sc->sc_hostvar;
664	u_int32_t isr;
665
666	/* mask all interrupts */
667	WRITE_REG(sc, TXP_IMR, TXP_INT_RESERVED | TXP_INT_SELF |
668	    TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
669	    TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0 |
670	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
671	    TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |  TXP_INT_LATCH);
672
673	isr = READ_REG(sc, TXP_ISR);
674	while (isr) {
675		WRITE_REG(sc, TXP_ISR, isr);
676
677		if ((*sc->sc_rxhir.r_roff) != (*sc->sc_rxhir.r_woff))
678			txp_rx_reclaim(sc, &sc->sc_rxhir);
679		if ((*sc->sc_rxlor.r_roff) != (*sc->sc_rxlor.r_woff))
680			txp_rx_reclaim(sc, &sc->sc_rxlor);
681
682		if (hv->hv_rx_buf_write_idx == hv->hv_rx_buf_read_idx)
683			txp_rxbuf_reclaim(sc);
684
685		if (sc->sc_txhir.r_cnt && (sc->sc_txhir.r_cons !=
686		    TXP_OFFSET2IDX(*(sc->sc_txhir.r_off))))
687			txp_tx_reclaim(sc, &sc->sc_txhir);
688
689		if (sc->sc_txlor.r_cnt && (sc->sc_txlor.r_cons !=
690		    TXP_OFFSET2IDX(*(sc->sc_txlor.r_off))))
691			txp_tx_reclaim(sc, &sc->sc_txlor);
692
693		isr = READ_REG(sc, TXP_ISR);
694	}
695
696	/* unmask all interrupts */
697	WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3);
698
699	txp_start(sc->sc_ifp);
700
701	return;
702}
703
704static void
705txp_rx_reclaim(sc, r)
706	struct txp_softc *sc;
707	struct txp_rx_ring *r;
708{
709	struct ifnet *ifp = sc->sc_ifp;
710	struct txp_rx_desc *rxd;
711	struct mbuf *m;
712	struct txp_swdesc *sd = NULL;
713	u_int32_t roff, woff;
714
715	roff = *r->r_roff;
716	woff = *r->r_woff;
717	rxd = r->r_desc + (roff / sizeof(struct txp_rx_desc));
718
719	while (roff != woff) {
720
721		if (rxd->rx_flags & RX_FLAGS_ERROR) {
722			device_printf(sc->sc_dev, "error 0x%x\n",
723			    rxd->rx_stat);
724			ifp->if_ierrors++;
725			goto next;
726		}
727
728		/* retrieve stashed pointer */
729		sd = rxd->rx_sd;
730
731		m = sd->sd_mbuf;
732		sd->sd_mbuf = NULL;
733
734		m->m_pkthdr.len = m->m_len = rxd->rx_len;
735
736#ifdef __STRICT_ALIGNMENT
737		{
738			/*
739			 * XXX Nice chip, except it won't accept "off by 2"
740			 * buffers, so we're force to copy.  Supposedly
741			 * this will be fixed in a newer firmware rev
742			 * and this will be temporary.
743			 */
744			struct mbuf *mnew;
745
746			MGETHDR(mnew, M_DONTWAIT, MT_DATA);
747			if (mnew == NULL) {
748				m_freem(m);
749				goto next;
750			}
751			if (m->m_len > (MHLEN - 2)) {
752				MCLGET(mnew, M_DONTWAIT);
753				if (!(mnew->m_flags & M_EXT)) {
754					m_freem(mnew);
755					m_freem(m);
756					goto next;
757				}
758			}
759			mnew->m_pkthdr.rcvif = ifp;
760			m_adj(mnew, 2);
761			mnew->m_pkthdr.len = mnew->m_len = m->m_len;
762			m_copydata(m, 0, m->m_pkthdr.len, mtod(mnew, caddr_t));
763			m_freem(m);
764			m = mnew;
765		}
766#endif
767
768		if (rxd->rx_stat & RX_STAT_IPCKSUMBAD)
769			m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
770		else if (rxd->rx_stat & RX_STAT_IPCKSUMGOOD)
771		 	m->m_pkthdr.csum_flags |=
772			    CSUM_IP_CHECKED|CSUM_IP_VALID;
773
774		if ((rxd->rx_stat & RX_STAT_TCPCKSUMGOOD) ||
775		    (rxd->rx_stat & RX_STAT_UDPCKSUMGOOD)) {
776			m->m_pkthdr.csum_flags |=
777			    CSUM_DATA_VALID|CSUM_PSEUDO_HDR;
778			m->m_pkthdr.csum_data = 0xffff;
779		}
780
781		if (rxd->rx_stat & RX_STAT_VLAN) {
782			VLAN_INPUT_TAG(ifp,
783				m, htons(rxd->rx_vlan >> 16), goto next);
784		}
785
786		(*ifp->if_input)(ifp, m);
787
788next:
789
790		roff += sizeof(struct txp_rx_desc);
791		if (roff == (RX_ENTRIES * sizeof(struct txp_rx_desc))) {
792			roff = 0;
793			rxd = r->r_desc;
794		} else
795			rxd++;
796		woff = *r->r_woff;
797	}
798
799	*r->r_roff = woff;
800
801	return;
802}
803
804static void
805txp_rxbuf_reclaim(sc)
806	struct txp_softc *sc;
807{
808	struct ifnet *ifp = sc->sc_ifp;
809	struct txp_hostvar *hv = sc->sc_hostvar;
810	struct txp_rxbuf_desc *rbd;
811	struct txp_swdesc *sd;
812	u_int32_t i;
813
814	if (!(ifp->if_flags & IFF_RUNNING))
815		return;
816
817	i = sc->sc_rxbufprod;
818	rbd = sc->sc_rxbufs + i;
819
820	while (1) {
821		sd = rbd->rb_sd;
822		if (sd->sd_mbuf != NULL)
823			break;
824
825		MGETHDR(sd->sd_mbuf, M_DONTWAIT, MT_DATA);
826		if (sd->sd_mbuf == NULL)
827			goto err_sd;
828
829		MCLGET(sd->sd_mbuf, M_DONTWAIT);
830		if ((sd->sd_mbuf->m_flags & M_EXT) == 0)
831			goto err_mbuf;
832		sd->sd_mbuf->m_pkthdr.rcvif = ifp;
833		sd->sd_mbuf->m_pkthdr.len = sd->sd_mbuf->m_len = MCLBYTES;
834
835		rbd->rb_paddrlo = vtophys(mtod(sd->sd_mbuf, vm_offset_t))
836		    & 0xffffffff;
837		rbd->rb_paddrhi = 0;
838
839		hv->hv_rx_buf_write_idx = TXP_IDX2OFFSET(i);
840
841		if (++i == RXBUF_ENTRIES) {
842			i = 0;
843			rbd = sc->sc_rxbufs;
844		} else
845			rbd++;
846	}
847
848	sc->sc_rxbufprod = i;
849
850	return;
851
852err_mbuf:
853	m_freem(sd->sd_mbuf);
854err_sd:
855	free(sd, M_DEVBUF);
856}
857
858/*
859 * Reclaim mbufs and entries from a transmit ring.
860 */
861static void
862txp_tx_reclaim(sc, r)
863	struct txp_softc *sc;
864	struct txp_tx_ring *r;
865{
866	struct ifnet *ifp = sc->sc_ifp;
867	u_int32_t idx = TXP_OFFSET2IDX(*(r->r_off));
868	u_int32_t cons = r->r_cons, cnt = r->r_cnt;
869	struct txp_tx_desc *txd = r->r_desc + cons;
870	struct txp_swdesc *sd = sc->sc_txd + cons;
871	struct mbuf *m;
872
873	while (cons != idx) {
874		if (cnt == 0)
875			break;
876
877		if ((txd->tx_flags & TX_FLAGS_TYPE_M) ==
878		    TX_FLAGS_TYPE_DATA) {
879			m = sd->sd_mbuf;
880			if (m != NULL) {
881				m_freem(m);
882				txd->tx_addrlo = 0;
883				txd->tx_addrhi = 0;
884				ifp->if_opackets++;
885			}
886		}
887		ifp->if_flags &= ~IFF_OACTIVE;
888
889		if (++cons == TX_ENTRIES) {
890			txd = r->r_desc;
891			cons = 0;
892			sd = sc->sc_txd;
893		} else {
894			txd++;
895			sd++;
896		}
897
898		cnt--;
899	}
900
901	r->r_cons = cons;
902	r->r_cnt = cnt;
903	if (cnt == 0)
904		ifp->if_timer = 0;
905}
906
907static int
908txp_shutdown(dev)
909	device_t dev;
910{
911	struct txp_softc *sc;
912
913	sc = device_get_softc(dev);
914
915	/* mask all interrupts */
916	WRITE_REG(sc, TXP_IMR,
917	    TXP_INT_SELF | TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |
918	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
919	    TXP_INT_LATCH);
920
921	txp_command(sc, TXP_CMD_TX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 0);
922	txp_command(sc, TXP_CMD_RX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 0);
923	txp_command(sc, TXP_CMD_HALT, 0, 0, 0, NULL, NULL, NULL, 0);
924
925	return(0);
926}
927
928static int
929txp_alloc_rings(sc)
930	struct txp_softc *sc;
931{
932	struct txp_boot_record *boot;
933	struct txp_ldata *ld;
934	u_int32_t r;
935	int i;
936
937	r = 0;
938	ld = sc->sc_ldata;
939	boot = &ld->txp_boot;
940
941	/* boot record */
942	sc->sc_boot = boot;
943
944	/* host variables */
945	bzero(&ld->txp_hostvar, sizeof(struct txp_hostvar));
946	boot->br_hostvar_lo = vtophys(&ld->txp_hostvar);
947	boot->br_hostvar_hi = 0;
948	sc->sc_hostvar = (struct txp_hostvar *)&ld->txp_hostvar;
949
950	/* hi priority tx ring */
951	boot->br_txhipri_lo = vtophys(&ld->txp_txhiring);;
952	boot->br_txhipri_hi = 0;
953	boot->br_txhipri_siz = TX_ENTRIES * sizeof(struct txp_tx_desc);
954	sc->sc_txhir.r_reg = TXP_H2A_1;
955	sc->sc_txhir.r_desc = (struct txp_tx_desc *)&ld->txp_txhiring;
956	sc->sc_txhir.r_cons = sc->sc_txhir.r_prod = sc->sc_txhir.r_cnt = 0;
957	sc->sc_txhir.r_off = &sc->sc_hostvar->hv_tx_hi_desc_read_idx;
958
959	/* lo priority tx ring */
960	boot->br_txlopri_lo = vtophys(&ld->txp_txloring);
961	boot->br_txlopri_hi = 0;
962	boot->br_txlopri_siz = TX_ENTRIES * sizeof(struct txp_tx_desc);
963	sc->sc_txlor.r_reg = TXP_H2A_3;
964	sc->sc_txlor.r_desc = (struct txp_tx_desc *)&ld->txp_txloring;
965	sc->sc_txlor.r_cons = sc->sc_txlor.r_prod = sc->sc_txlor.r_cnt = 0;
966	sc->sc_txlor.r_off = &sc->sc_hostvar->hv_tx_lo_desc_read_idx;
967
968	/* high priority rx ring */
969	boot->br_rxhipri_lo = vtophys(&ld->txp_rxhiring);
970	boot->br_rxhipri_hi = 0;
971	boot->br_rxhipri_siz = RX_ENTRIES * sizeof(struct txp_rx_desc);
972	sc->sc_rxhir.r_desc = (struct txp_rx_desc *)&ld->txp_rxhiring;
973	sc->sc_rxhir.r_roff = &sc->sc_hostvar->hv_rx_hi_read_idx;
974	sc->sc_rxhir.r_woff = &sc->sc_hostvar->hv_rx_hi_write_idx;
975
976	/* low priority rx ring */
977	boot->br_rxlopri_lo = vtophys(&ld->txp_rxloring);
978	boot->br_rxlopri_hi = 0;
979	boot->br_rxlopri_siz = RX_ENTRIES * sizeof(struct txp_rx_desc);
980	sc->sc_rxlor.r_desc = (struct txp_rx_desc *)&ld->txp_rxloring;
981	sc->sc_rxlor.r_roff = &sc->sc_hostvar->hv_rx_lo_read_idx;
982	sc->sc_rxlor.r_woff = &sc->sc_hostvar->hv_rx_lo_write_idx;
983
984	/* command ring */
985	bzero(&ld->txp_cmdring, sizeof(struct txp_cmd_desc) * CMD_ENTRIES);
986	boot->br_cmd_lo = vtophys(&ld->txp_cmdring);
987	boot->br_cmd_hi = 0;
988	boot->br_cmd_siz = CMD_ENTRIES * sizeof(struct txp_cmd_desc);
989	sc->sc_cmdring.base = (struct txp_cmd_desc *)&ld->txp_cmdring;
990	sc->sc_cmdring.size = CMD_ENTRIES * sizeof(struct txp_cmd_desc);
991	sc->sc_cmdring.lastwrite = 0;
992
993	/* response ring */
994	bzero(&ld->txp_rspring, sizeof(struct txp_rsp_desc) * RSP_ENTRIES);
995	boot->br_resp_lo = vtophys(&ld->txp_rspring);
996	boot->br_resp_hi = 0;
997	boot->br_resp_siz = CMD_ENTRIES * sizeof(struct txp_rsp_desc);
998	sc->sc_rspring.base = (struct txp_rsp_desc *)&ld->txp_rspring;
999	sc->sc_rspring.size = RSP_ENTRIES * sizeof(struct txp_rsp_desc);
1000	sc->sc_rspring.lastwrite = 0;
1001
1002	/* receive buffer ring */
1003	boot->br_rxbuf_lo = vtophys(&ld->txp_rxbufs);
1004	boot->br_rxbuf_hi = 0;
1005	boot->br_rxbuf_siz = RXBUF_ENTRIES * sizeof(struct txp_rxbuf_desc);
1006	sc->sc_rxbufs = (struct txp_rxbuf_desc *)&ld->txp_rxbufs;
1007
1008	for (i = 0; i < RXBUF_ENTRIES; i++) {
1009		struct txp_swdesc *sd;
1010		if (sc->sc_rxbufs[i].rb_sd != NULL)
1011			continue;
1012		sc->sc_rxbufs[i].rb_sd = malloc(sizeof(struct txp_swdesc),
1013		    M_DEVBUF, M_NOWAIT);
1014		if (sc->sc_rxbufs[i].rb_sd == NULL)
1015			return(ENOBUFS);
1016		sd = sc->sc_rxbufs[i].rb_sd;
1017		sd->sd_mbuf = NULL;
1018	}
1019	sc->sc_rxbufprod = 0;
1020
1021	/* zero dma */
1022	bzero(&ld->txp_zero, sizeof(u_int32_t));
1023	boot->br_zero_lo = vtophys(&ld->txp_zero);
1024	boot->br_zero_hi = 0;
1025
1026	/* See if it's waiting for boot, and try to boot it */
1027	for (i = 0; i < 10000; i++) {
1028		r = READ_REG(sc, TXP_A2H_0);
1029		if (r == STAT_WAITING_FOR_BOOT)
1030			break;
1031		DELAY(50);
1032	}
1033
1034	if (r != STAT_WAITING_FOR_BOOT) {
1035		device_printf(sc->sc_dev, "not waiting for boot\n");
1036		return(ENXIO);
1037	}
1038
1039	WRITE_REG(sc, TXP_H2A_2, 0);
1040	WRITE_REG(sc, TXP_H2A_1, vtophys(sc->sc_boot));
1041	WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_REGISTER_BOOT_RECORD);
1042
1043	/* See if it booted */
1044	for (i = 0; i < 10000; i++) {
1045		r = READ_REG(sc, TXP_A2H_0);
1046		if (r == STAT_RUNNING)
1047			break;
1048		DELAY(50);
1049	}
1050	if (r != STAT_RUNNING) {
1051		device_printf(sc->sc_dev, "fw not running\n");
1052		return(ENXIO);
1053	}
1054
1055	/* Clear TX and CMD ring write registers */
1056	WRITE_REG(sc, TXP_H2A_1, TXP_BOOTCMD_NULL);
1057	WRITE_REG(sc, TXP_H2A_2, TXP_BOOTCMD_NULL);
1058	WRITE_REG(sc, TXP_H2A_3, TXP_BOOTCMD_NULL);
1059	WRITE_REG(sc, TXP_H2A_0, TXP_BOOTCMD_NULL);
1060
1061	return (0);
1062}
1063
1064static int
1065txp_ioctl(ifp, command, data)
1066	struct ifnet *ifp;
1067	u_long command;
1068	caddr_t data;
1069{
1070	struct txp_softc *sc = ifp->if_softc;
1071	struct ifreq *ifr = (struct ifreq *)data;
1072	int s, error = 0;
1073
1074	s = splnet();
1075
1076	switch(command) {
1077	case SIOCSIFFLAGS:
1078		if (ifp->if_flags & IFF_UP) {
1079			txp_init(sc);
1080		} else {
1081			if (ifp->if_flags & IFF_RUNNING)
1082				txp_stop(sc);
1083		}
1084		break;
1085	case SIOCADDMULTI:
1086	case SIOCDELMULTI:
1087		/*
1088		 * Multicast list has changed; set the hardware
1089		 * filter accordingly.
1090		 */
1091		txp_set_filter(sc);
1092		error = 0;
1093		break;
1094	case SIOCGIFMEDIA:
1095	case SIOCSIFMEDIA:
1096		error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, command);
1097		break;
1098	default:
1099		error = ether_ioctl(ifp, command, data);
1100		break;
1101	}
1102
1103	(void)splx(s);
1104
1105	return(error);
1106}
1107
1108static int
1109txp_rxring_fill(sc)
1110	struct txp_softc *sc;
1111{
1112	int i;
1113	struct ifnet *ifp;
1114	struct txp_swdesc *sd;
1115
1116	ifp = sc->sc_ifp;
1117
1118	for (i = 0; i < RXBUF_ENTRIES; i++) {
1119		sd = sc->sc_rxbufs[i].rb_sd;
1120		MGETHDR(sd->sd_mbuf, M_DONTWAIT, MT_DATA);
1121		if (sd->sd_mbuf == NULL)
1122			return(ENOBUFS);
1123
1124		MCLGET(sd->sd_mbuf, M_DONTWAIT);
1125		if ((sd->sd_mbuf->m_flags & M_EXT) == 0) {
1126			m_freem(sd->sd_mbuf);
1127			return(ENOBUFS);
1128		}
1129		sd->sd_mbuf->m_pkthdr.len = sd->sd_mbuf->m_len = MCLBYTES;
1130		sd->sd_mbuf->m_pkthdr.rcvif = ifp;
1131
1132		sc->sc_rxbufs[i].rb_paddrlo =
1133		    vtophys(mtod(sd->sd_mbuf, vm_offset_t));
1134		sc->sc_rxbufs[i].rb_paddrhi = 0;
1135	}
1136
1137	sc->sc_hostvar->hv_rx_buf_write_idx = (RXBUF_ENTRIES - 1) *
1138	    sizeof(struct txp_rxbuf_desc);
1139
1140	return(0);
1141}
1142
1143static void
1144txp_rxring_empty(sc)
1145	struct txp_softc *sc;
1146{
1147	int i;
1148	struct txp_swdesc *sd;
1149
1150	if (sc->sc_rxbufs == NULL)
1151		return;
1152
1153	for (i = 0; i < RXBUF_ENTRIES; i++) {
1154		if (&sc->sc_rxbufs[i] == NULL)
1155			continue;
1156		sd = sc->sc_rxbufs[i].rb_sd;
1157		if (sd == NULL)
1158			continue;
1159		if (sd->sd_mbuf != NULL) {
1160			m_freem(sd->sd_mbuf);
1161			sd->sd_mbuf = NULL;
1162		}
1163	}
1164
1165	return;
1166}
1167
1168static void
1169txp_init(xsc)
1170	void *xsc;
1171{
1172	struct txp_softc *sc;
1173	struct ifnet *ifp;
1174	u_int16_t p1;
1175	u_int32_t p2;
1176	int s;
1177
1178	sc = xsc;
1179	ifp = sc->sc_ifp;
1180
1181	if (ifp->if_flags & IFF_RUNNING)
1182		return;
1183
1184	txp_stop(sc);
1185
1186	s = splnet();
1187
1188	txp_command(sc, TXP_CMD_MAX_PKT_SIZE_WRITE, TXP_MAX_PKTLEN, 0, 0,
1189	    NULL, NULL, NULL, 1);
1190
1191	/* Set station address. */
1192	((u_int8_t *)&p1)[1] = IFP2ENADDR(sc->sc_ifp)[0];
1193	((u_int8_t *)&p1)[0] = IFP2ENADDR(sc->sc_ifp)[1];
1194	((u_int8_t *)&p2)[3] = IFP2ENADDR(sc->sc_ifp)[2];
1195	((u_int8_t *)&p2)[2] = IFP2ENADDR(sc->sc_ifp)[3];
1196	((u_int8_t *)&p2)[1] = IFP2ENADDR(sc->sc_ifp)[4];
1197	((u_int8_t *)&p2)[0] = IFP2ENADDR(sc->sc_ifp)[5];
1198	txp_command(sc, TXP_CMD_STATION_ADDRESS_WRITE, p1, p2, 0,
1199	    NULL, NULL, NULL, 1);
1200
1201	txp_set_filter(sc);
1202
1203	txp_rxring_fill(sc);
1204
1205	txp_command(sc, TXP_CMD_TX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1);
1206	txp_command(sc, TXP_CMD_RX_ENABLE, 0, 0, 0, NULL, NULL, NULL, 1);
1207
1208	WRITE_REG(sc, TXP_IER, TXP_INT_RESERVED | TXP_INT_SELF |
1209	    TXP_INT_A2H_7 | TXP_INT_A2H_6 | TXP_INT_A2H_5 | TXP_INT_A2H_4 |
1210	    TXP_INT_A2H_2 | TXP_INT_A2H_1 | TXP_INT_A2H_0 |
1211	    TXP_INT_DMA3 | TXP_INT_DMA2 | TXP_INT_DMA1 | TXP_INT_DMA0 |
1212	    TXP_INT_PCI_TABORT | TXP_INT_PCI_MABORT |  TXP_INT_LATCH);
1213	WRITE_REG(sc, TXP_IMR, TXP_INT_A2H_3);
1214
1215	ifp->if_flags |= IFF_RUNNING;
1216	ifp->if_flags &= ~IFF_OACTIVE;
1217	ifp->if_timer = 0;
1218
1219	sc->sc_tick = timeout(txp_tick, sc, hz);
1220
1221	splx(s);
1222}
1223
1224static void
1225txp_tick(vsc)
1226	void *vsc;
1227{
1228	struct txp_softc *sc = vsc;
1229	struct ifnet *ifp = sc->sc_ifp;
1230	struct txp_rsp_desc *rsp = NULL;
1231	struct txp_ext_desc *ext;
1232	int s;
1233
1234	s = splnet();
1235	txp_rxbuf_reclaim(sc);
1236
1237	if (txp_command2(sc, TXP_CMD_READ_STATISTICS, 0, 0, 0, NULL, 0,
1238	    &rsp, 1))
1239		goto out;
1240	if (rsp->rsp_numdesc != 6)
1241		goto out;
1242	if (txp_command(sc, TXP_CMD_CLEAR_STATISTICS, 0, 0, 0,
1243	    NULL, NULL, NULL, 1))
1244		goto out;
1245	ext = (struct txp_ext_desc *)(rsp + 1);
1246
1247	ifp->if_ierrors += ext[3].ext_2 + ext[3].ext_3 + ext[3].ext_4 +
1248	    ext[4].ext_1 + ext[4].ext_4;
1249	ifp->if_oerrors += ext[0].ext_1 + ext[1].ext_1 + ext[1].ext_4 +
1250	    ext[2].ext_1;
1251	ifp->if_collisions += ext[0].ext_2 + ext[0].ext_3 + ext[1].ext_2 +
1252	    ext[1].ext_3;
1253	ifp->if_opackets += rsp->rsp_par2;
1254	ifp->if_ipackets += ext[2].ext_3;
1255
1256out:
1257	if (rsp != NULL)
1258		free(rsp, M_DEVBUF);
1259
1260	splx(s);
1261	sc->sc_tick = timeout(txp_tick, sc, hz);
1262
1263	return;
1264}
1265
1266static void
1267txp_start(ifp)
1268	struct ifnet *ifp;
1269{
1270	struct txp_softc *sc = ifp->if_softc;
1271	struct txp_tx_ring *r = &sc->sc_txhir;
1272	struct txp_tx_desc *txd;
1273	struct txp_frag_desc *fxd;
1274	struct mbuf *m, *m0;
1275	struct txp_swdesc *sd;
1276	u_int32_t firstprod, firstcnt, prod, cnt;
1277	struct m_tag *mtag;
1278
1279	if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
1280		return;
1281
1282	prod = r->r_prod;
1283	cnt = r->r_cnt;
1284
1285	while (1) {
1286		IF_DEQUEUE(&ifp->if_snd, m);
1287		if (m == NULL)
1288			break;
1289
1290		firstprod = prod;
1291		firstcnt = cnt;
1292
1293		sd = sc->sc_txd + prod;
1294		sd->sd_mbuf = m;
1295
1296		if ((TX_ENTRIES - cnt) < 4)
1297			goto oactive;
1298
1299		txd = r->r_desc + prod;
1300
1301		txd->tx_flags = TX_FLAGS_TYPE_DATA;
1302		txd->tx_numdesc = 0;
1303		txd->tx_addrlo = 0;
1304		txd->tx_addrhi = 0;
1305		txd->tx_totlen = 0;
1306		txd->tx_pflags = 0;
1307
1308		if (++prod == TX_ENTRIES)
1309			prod = 0;
1310
1311		if (++cnt >= (TX_ENTRIES - 4))
1312			goto oactive;
1313
1314		mtag = VLAN_OUTPUT_TAG(ifp, m);
1315		if (mtag != NULL) {
1316			txd->tx_pflags = TX_PFLAGS_VLAN |
1317			    (htons(VLAN_TAG_VALUE(mtag)) << TX_PFLAGS_VLANTAG_S);
1318		}
1319
1320		if (m->m_pkthdr.csum_flags & CSUM_IP)
1321			txd->tx_pflags |= TX_PFLAGS_IPCKSUM;
1322
1323#if 0
1324		if (m->m_pkthdr.csum_flags & CSUM_TCP)
1325			txd->tx_pflags |= TX_PFLAGS_TCPCKSUM;
1326		if (m->m_pkthdr.csum_flags & CSUM_UDP)
1327			txd->tx_pflags |= TX_PFLAGS_UDPCKSUM;
1328#endif
1329
1330		fxd = (struct txp_frag_desc *)(r->r_desc + prod);
1331		for (m0 = m; m0 != NULL; m0 = m0->m_next) {
1332			if (m0->m_len == 0)
1333				continue;
1334			if (++cnt >= (TX_ENTRIES - 4))
1335				goto oactive;
1336
1337			txd->tx_numdesc++;
1338
1339			fxd->frag_flags = FRAG_FLAGS_TYPE_FRAG;
1340			fxd->frag_rsvd1 = 0;
1341			fxd->frag_len = m0->m_len;
1342			fxd->frag_addrlo = vtophys(mtod(m0, vm_offset_t));
1343			fxd->frag_addrhi = 0;
1344			fxd->frag_rsvd2 = 0;
1345
1346			if (++prod == TX_ENTRIES) {
1347				fxd = (struct txp_frag_desc *)r->r_desc;
1348				prod = 0;
1349			} else
1350				fxd++;
1351
1352		}
1353
1354		ifp->if_timer = 5;
1355
1356		BPF_MTAP(ifp, m);
1357		WRITE_REG(sc, r->r_reg, TXP_IDX2OFFSET(prod));
1358	}
1359
1360	r->r_prod = prod;
1361	r->r_cnt = cnt;
1362	return;
1363
1364oactive:
1365	ifp->if_flags |= IFF_OACTIVE;
1366	r->r_prod = firstprod;
1367	r->r_cnt = firstcnt;
1368	IF_PREPEND(&ifp->if_snd, m);
1369	return;
1370}
1371
1372/*
1373 * Handle simple commands sent to the typhoon
1374 */
1375static int
1376txp_command(sc, id, in1, in2, in3, out1, out2, out3, wait)
1377	struct txp_softc *sc;
1378	u_int16_t id, in1, *out1;
1379	u_int32_t in2, in3, *out2, *out3;
1380	int wait;
1381{
1382	struct txp_rsp_desc *rsp = NULL;
1383
1384	if (txp_command2(sc, id, in1, in2, in3, NULL, 0, &rsp, wait))
1385		return (-1);
1386
1387	if (!wait)
1388		return (0);
1389
1390	if (out1 != NULL)
1391		*out1 = rsp->rsp_par1;
1392	if (out2 != NULL)
1393		*out2 = rsp->rsp_par2;
1394	if (out3 != NULL)
1395		*out3 = rsp->rsp_par3;
1396	free(rsp, M_DEVBUF);
1397	return (0);
1398}
1399
1400static int
1401txp_command2(sc, id, in1, in2, in3, in_extp, in_extn, rspp, wait)
1402	struct txp_softc *sc;
1403	u_int16_t id, in1;
1404	u_int32_t in2, in3;
1405	struct txp_ext_desc *in_extp;
1406	u_int8_t in_extn;
1407	struct txp_rsp_desc **rspp;
1408	int wait;
1409{
1410	struct txp_hostvar *hv = sc->sc_hostvar;
1411	struct txp_cmd_desc *cmd;
1412	struct txp_ext_desc *ext;
1413	u_int32_t idx, i;
1414	u_int16_t seq;
1415
1416	if (txp_cmd_desc_numfree(sc) < (in_extn + 1)) {
1417		device_printf(sc->sc_dev, "no free cmd descriptors\n");
1418		return (-1);
1419	}
1420
1421	idx = sc->sc_cmdring.lastwrite;
1422	cmd = (struct txp_cmd_desc *)(((u_int8_t *)sc->sc_cmdring.base) + idx);
1423	bzero(cmd, sizeof(*cmd));
1424
1425	cmd->cmd_numdesc = in_extn;
1426	cmd->cmd_seq = seq = sc->sc_seq++;
1427	cmd->cmd_id = id;
1428	cmd->cmd_par1 = in1;
1429	cmd->cmd_par2 = in2;
1430	cmd->cmd_par3 = in3;
1431	cmd->cmd_flags = CMD_FLAGS_TYPE_CMD |
1432	    (wait ? CMD_FLAGS_RESP : 0) | CMD_FLAGS_VALID;
1433
1434	idx += sizeof(struct txp_cmd_desc);
1435	if (idx == sc->sc_cmdring.size)
1436		idx = 0;
1437
1438	for (i = 0; i < in_extn; i++) {
1439		ext = (struct txp_ext_desc *)(((u_int8_t *)sc->sc_cmdring.base) + idx);
1440		bcopy(in_extp, ext, sizeof(struct txp_ext_desc));
1441		in_extp++;
1442		idx += sizeof(struct txp_cmd_desc);
1443		if (idx == sc->sc_cmdring.size)
1444			idx = 0;
1445	}
1446
1447	sc->sc_cmdring.lastwrite = idx;
1448
1449	WRITE_REG(sc, TXP_H2A_2, sc->sc_cmdring.lastwrite);
1450
1451	if (!wait)
1452		return (0);
1453
1454	for (i = 0; i < 10000; i++) {
1455		idx = hv->hv_resp_read_idx;
1456		if (idx != hv->hv_resp_write_idx) {
1457			*rspp = NULL;
1458			if (txp_response(sc, idx, id, seq, rspp))
1459				return (-1);
1460			if (*rspp != NULL)
1461				break;
1462		}
1463		DELAY(50);
1464	}
1465	if (i == 1000 || (*rspp) == NULL) {
1466		device_printf(sc->sc_dev, "0x%x command failed\n", id);
1467		return (-1);
1468	}
1469
1470	return (0);
1471}
1472
1473static int
1474txp_response(sc, ridx, id, seq, rspp)
1475	struct txp_softc *sc;
1476	u_int32_t ridx;
1477	u_int16_t id;
1478	u_int16_t seq;
1479	struct txp_rsp_desc **rspp;
1480{
1481	struct txp_hostvar *hv = sc->sc_hostvar;
1482	struct txp_rsp_desc *rsp;
1483
1484	while (ridx != hv->hv_resp_write_idx) {
1485		rsp = (struct txp_rsp_desc *)(((u_int8_t *)sc->sc_rspring.base) + ridx);
1486
1487		if (id == rsp->rsp_id && rsp->rsp_seq == seq) {
1488			*rspp = (struct txp_rsp_desc *)malloc(
1489			    sizeof(struct txp_rsp_desc) * (rsp->rsp_numdesc + 1),
1490			    M_DEVBUF, M_NOWAIT);
1491			if ((*rspp) == NULL)
1492				return (-1);
1493			txp_rsp_fixup(sc, rsp, *rspp);
1494			return (0);
1495		}
1496
1497		if (rsp->rsp_flags & RSP_FLAGS_ERROR) {
1498			device_printf(sc->sc_dev, "response error!\n");
1499			txp_rsp_fixup(sc, rsp, NULL);
1500			ridx = hv->hv_resp_read_idx;
1501			continue;
1502		}
1503
1504		switch (rsp->rsp_id) {
1505		case TXP_CMD_CYCLE_STATISTICS:
1506		case TXP_CMD_MEDIA_STATUS_READ:
1507			break;
1508		case TXP_CMD_HELLO_RESPONSE:
1509			device_printf(sc->sc_dev, "hello\n");
1510			break;
1511		default:
1512			device_printf(sc->sc_dev, "unknown id(0x%x)\n",
1513			    rsp->rsp_id);
1514		}
1515
1516		txp_rsp_fixup(sc, rsp, NULL);
1517		ridx = hv->hv_resp_read_idx;
1518		hv->hv_resp_read_idx = ridx;
1519	}
1520
1521	return (0);
1522}
1523
1524static void
1525txp_rsp_fixup(sc, rsp, dst)
1526	struct txp_softc *sc;
1527	struct txp_rsp_desc *rsp, *dst;
1528{
1529	struct txp_rsp_desc *src = rsp;
1530	struct txp_hostvar *hv = sc->sc_hostvar;
1531	u_int32_t i, ridx;
1532
1533	ridx = hv->hv_resp_read_idx;
1534
1535	for (i = 0; i < rsp->rsp_numdesc + 1; i++) {
1536		if (dst != NULL)
1537			bcopy(src, dst++, sizeof(struct txp_rsp_desc));
1538		ridx += sizeof(struct txp_rsp_desc);
1539		if (ridx == sc->sc_rspring.size) {
1540			src = sc->sc_rspring.base;
1541			ridx = 0;
1542		} else
1543			src++;
1544		sc->sc_rspring.lastwrite = hv->hv_resp_read_idx = ridx;
1545	}
1546
1547	hv->hv_resp_read_idx = ridx;
1548}
1549
1550static int
1551txp_cmd_desc_numfree(sc)
1552	struct txp_softc *sc;
1553{
1554	struct txp_hostvar *hv = sc->sc_hostvar;
1555	struct txp_boot_record *br = sc->sc_boot;
1556	u_int32_t widx, ridx, nfree;
1557
1558	widx = sc->sc_cmdring.lastwrite;
1559	ridx = hv->hv_cmd_read_idx;
1560
1561	if (widx == ridx) {
1562		/* Ring is completely free */
1563		nfree = br->br_cmd_siz - sizeof(struct txp_cmd_desc);
1564	} else {
1565		if (widx > ridx)
1566			nfree = br->br_cmd_siz -
1567			    (widx - ridx + sizeof(struct txp_cmd_desc));
1568		else
1569			nfree = ridx - widx - sizeof(struct txp_cmd_desc);
1570	}
1571
1572	return (nfree / sizeof(struct txp_cmd_desc));
1573}
1574
1575static void
1576txp_stop(sc)
1577	struct txp_softc *sc;
1578{
1579	struct ifnet *ifp;
1580
1581	ifp = sc->sc_ifp;
1582
1583	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
1584
1585	untimeout(txp_tick, sc, sc->sc_tick);
1586
1587	txp_command(sc, TXP_CMD_TX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 1);
1588	txp_command(sc, TXP_CMD_RX_DISABLE, 0, 0, 0, NULL, NULL, NULL, 1);
1589
1590	txp_rxring_empty(sc);
1591
1592	return;
1593}
1594
1595static void
1596txp_watchdog(ifp)
1597	struct ifnet *ifp;
1598{
1599	return;
1600}
1601
1602static int
1603txp_ifmedia_upd(ifp)
1604	struct ifnet *ifp;
1605{
1606	struct txp_softc *sc = ifp->if_softc;
1607	struct ifmedia *ifm = &sc->sc_ifmedia;
1608	u_int16_t new_xcvr;
1609
1610	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
1611		return (EINVAL);
1612
1613	if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) {
1614		if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
1615			new_xcvr = TXP_XCVR_10_FDX;
1616		else
1617			new_xcvr = TXP_XCVR_10_HDX;
1618	} else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_100_TX) {
1619		if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX)
1620			new_xcvr = TXP_XCVR_100_FDX;
1621		else
1622			new_xcvr = TXP_XCVR_100_HDX;
1623	} else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) {
1624		new_xcvr = TXP_XCVR_AUTO;
1625	} else
1626		return (EINVAL);
1627
1628	/* nothing to do */
1629	if (sc->sc_xcvr == new_xcvr)
1630		return (0);
1631
1632	txp_command(sc, TXP_CMD_XCVR_SELECT, new_xcvr, 0, 0,
1633	    NULL, NULL, NULL, 0);
1634	sc->sc_xcvr = new_xcvr;
1635
1636	return (0);
1637}
1638
1639static void
1640txp_ifmedia_sts(ifp, ifmr)
1641	struct ifnet *ifp;
1642	struct ifmediareq *ifmr;
1643{
1644	struct txp_softc *sc = ifp->if_softc;
1645	struct ifmedia *ifm = &sc->sc_ifmedia;
1646	u_int16_t bmsr, bmcr, anlpar;
1647
1648	ifmr->ifm_status = IFM_AVALID;
1649	ifmr->ifm_active = IFM_ETHER;
1650
1651	if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMSR, 0,
1652	    &bmsr, NULL, NULL, 1))
1653		goto bail;
1654	if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMSR, 0,
1655	    &bmsr, NULL, NULL, 1))
1656		goto bail;
1657
1658	if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_BMCR, 0,
1659	    &bmcr, NULL, NULL, 1))
1660		goto bail;
1661
1662	if (txp_command(sc, TXP_CMD_PHY_MGMT_READ, 0, MII_ANLPAR, 0,
1663	    &anlpar, NULL, NULL, 1))
1664		goto bail;
1665
1666	if (bmsr & BMSR_LINK)
1667		ifmr->ifm_status |= IFM_ACTIVE;
1668
1669	if (bmcr & BMCR_ISO) {
1670		ifmr->ifm_active |= IFM_NONE;
1671		ifmr->ifm_status = 0;
1672		return;
1673	}
1674
1675	if (bmcr & BMCR_LOOP)
1676		ifmr->ifm_active |= IFM_LOOP;
1677
1678	if (bmcr & BMCR_AUTOEN) {
1679		if ((bmsr & BMSR_ACOMP) == 0) {
1680			ifmr->ifm_active |= IFM_NONE;
1681			return;
1682		}
1683
1684		if (anlpar & ANLPAR_T4)
1685			ifmr->ifm_active |= IFM_100_T4;
1686		else if (anlpar & ANLPAR_TX_FD)
1687			ifmr->ifm_active |= IFM_100_TX|IFM_FDX;
1688		else if (anlpar & ANLPAR_TX)
1689			ifmr->ifm_active |= IFM_100_TX;
1690		else if (anlpar & ANLPAR_10_FD)
1691			ifmr->ifm_active |= IFM_10_T|IFM_FDX;
1692		else if (anlpar & ANLPAR_10)
1693			ifmr->ifm_active |= IFM_10_T;
1694		else
1695			ifmr->ifm_active |= IFM_NONE;
1696	} else
1697		ifmr->ifm_active = ifm->ifm_cur->ifm_media;
1698	return;
1699
1700bail:
1701	ifmr->ifm_active |= IFM_NONE;
1702	ifmr->ifm_status &= ~IFM_AVALID;
1703}
1704
1705#ifdef TXP_DEBUG
1706static void
1707txp_show_descriptor(d)
1708	void *d;
1709{
1710	struct txp_cmd_desc *cmd = d;
1711	struct txp_rsp_desc *rsp = d;
1712	struct txp_tx_desc *txd = d;
1713	struct txp_frag_desc *frgd = d;
1714
1715	switch (cmd->cmd_flags & CMD_FLAGS_TYPE_M) {
1716	case CMD_FLAGS_TYPE_CMD:
1717		/* command descriptor */
1718		printf("[cmd flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n",
1719		    cmd->cmd_flags, cmd->cmd_numdesc, cmd->cmd_id, cmd->cmd_seq,
1720		    cmd->cmd_par1, cmd->cmd_par2, cmd->cmd_par3);
1721		break;
1722	case CMD_FLAGS_TYPE_RESP:
1723		/* response descriptor */
1724		printf("[rsp flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n",
1725		    rsp->rsp_flags, rsp->rsp_numdesc, rsp->rsp_id, rsp->rsp_seq,
1726		    rsp->rsp_par1, rsp->rsp_par2, rsp->rsp_par3);
1727		break;
1728	case CMD_FLAGS_TYPE_DATA:
1729		/* data header (assuming tx for now) */
1730		printf("[data flags 0x%x num %d totlen %d addr 0x%x/0x%x pflags 0x%x]",
1731		    txd->tx_flags, txd->tx_numdesc, txd->tx_totlen,
1732		    txd->tx_addrlo, txd->tx_addrhi, txd->tx_pflags);
1733		break;
1734	case CMD_FLAGS_TYPE_FRAG:
1735		/* fragment descriptor */
1736		printf("[frag flags 0x%x rsvd1 0x%x len %d addr 0x%x/0x%x rsvd2 0x%x]",
1737		    frgd->frag_flags, frgd->frag_rsvd1, frgd->frag_len,
1738		    frgd->frag_addrlo, frgd->frag_addrhi, frgd->frag_rsvd2);
1739		break;
1740	default:
1741		printf("[unknown(%x) flags 0x%x num %d id %d seq %d par1 0x%x par2 0x%x par3 0x%x]\n",
1742		    cmd->cmd_flags & CMD_FLAGS_TYPE_M,
1743		    cmd->cmd_flags, cmd->cmd_numdesc, cmd->cmd_id, cmd->cmd_seq,
1744		    cmd->cmd_par1, cmd->cmd_par2, cmd->cmd_par3);
1745		break;
1746	}
1747}
1748#endif
1749
1750static void
1751txp_set_filter(sc)
1752	struct txp_softc *sc;
1753{
1754	struct ifnet *ifp = sc->sc_ifp;
1755	u_int32_t crc, carry, hashbit, hash[2];
1756	u_int16_t filter;
1757	u_int8_t octet;
1758	int i, j, mcnt = 0;
1759	struct ifmultiaddr *ifma;
1760	char *enm;
1761
1762	if (ifp->if_flags & IFF_PROMISC) {
1763		filter = TXP_RXFILT_PROMISC;
1764		goto setit;
1765	}
1766
1767	filter = TXP_RXFILT_DIRECT;
1768
1769	if (ifp->if_flags & IFF_BROADCAST)
1770		filter |= TXP_RXFILT_BROADCAST;
1771
1772	if (ifp->if_flags & IFF_ALLMULTI)
1773		filter |= TXP_RXFILT_ALLMULTI;
1774	else {
1775		hash[0] = hash[1] = 0;
1776
1777		IF_ADDR_LOCK(ifp);
1778		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1779			if (ifma->ifma_addr->sa_family != AF_LINK)
1780				continue;
1781
1782			enm = LLADDR((struct sockaddr_dl *)ifma->ifma_addr);
1783			mcnt++;
1784			crc = 0xffffffff;
1785
1786			for (i = 0; i < ETHER_ADDR_LEN; i++) {
1787				octet = enm[i];
1788				for (j = 0; j < 8; j++) {
1789					carry = ((crc & 0x80000000) ? 1 : 0) ^
1790					    (octet & 1);
1791					crc <<= 1;
1792					octet >>= 1;
1793					if (carry)
1794						crc = (crc ^ TXP_POLYNOMIAL) |
1795						    carry;
1796				}
1797			}
1798			hashbit = (u_int16_t)(crc & (64 - 1));
1799			hash[hashbit / 32] |= (1 << hashbit % 32);
1800		}
1801		IF_ADDR_UNLOCK(ifp);
1802
1803		if (mcnt > 0) {
1804			filter |= TXP_RXFILT_HASHMULTI;
1805			txp_command(sc, TXP_CMD_MCAST_HASH_MASK_WRITE,
1806			    2, hash[0], hash[1], NULL, NULL, NULL, 0);
1807		}
1808	}
1809
1810setit:
1811
1812	txp_command(sc, TXP_CMD_RX_FILTER_WRITE, filter, 0, 0,
1813	    NULL, NULL, NULL, 1);
1814
1815	return;
1816}
1817
1818static void
1819txp_capabilities(sc)
1820	struct txp_softc *sc;
1821{
1822	struct ifnet *ifp = sc->sc_ifp;
1823	struct txp_rsp_desc *rsp = NULL;
1824	struct txp_ext_desc *ext;
1825
1826	if (txp_command2(sc, TXP_CMD_OFFLOAD_READ, 0, 0, 0, NULL, 0, &rsp, 1))
1827		goto out;
1828
1829	if (rsp->rsp_numdesc != 1)
1830		goto out;
1831	ext = (struct txp_ext_desc *)(rsp + 1);
1832
1833	sc->sc_tx_capability = ext->ext_1 & OFFLOAD_MASK;
1834	sc->sc_rx_capability = ext->ext_2 & OFFLOAD_MASK;
1835	ifp->if_capabilities = 0;
1836
1837	if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_VLAN) {
1838		sc->sc_tx_capability |= OFFLOAD_VLAN;
1839		sc->sc_rx_capability |= OFFLOAD_VLAN;
1840		ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
1841	}
1842
1843#if 0
1844	/* not ready yet */
1845	if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_IPSEC) {
1846		sc->sc_tx_capability |= OFFLOAD_IPSEC;
1847		sc->sc_rx_capability |= OFFLOAD_IPSEC;
1848		ifp->if_capabilities |= IFCAP_IPSEC;
1849	}
1850#endif
1851
1852	if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_IPCKSUM) {
1853		sc->sc_tx_capability |= OFFLOAD_IPCKSUM;
1854		sc->sc_rx_capability |= OFFLOAD_IPCKSUM;
1855		ifp->if_capabilities |= IFCAP_HWCSUM;
1856		ifp->if_hwassist |= CSUM_IP;
1857	}
1858
1859	if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_TCPCKSUM) {
1860#if 0
1861		sc->sc_tx_capability |= OFFLOAD_TCPCKSUM;
1862#endif
1863		sc->sc_rx_capability |= OFFLOAD_TCPCKSUM;
1864		ifp->if_capabilities |= IFCAP_HWCSUM;
1865	}
1866
1867	if (rsp->rsp_par2 & rsp->rsp_par3 & OFFLOAD_UDPCKSUM) {
1868#if 0
1869		sc->sc_tx_capability |= OFFLOAD_UDPCKSUM;
1870#endif
1871		sc->sc_rx_capability |= OFFLOAD_UDPCKSUM;
1872		ifp->if_capabilities |= IFCAP_HWCSUM;
1873	}
1874	ifp->if_capenable = ifp->if_capabilities;
1875
1876	if (txp_command(sc, TXP_CMD_OFFLOAD_WRITE, 0,
1877	    sc->sc_tx_capability, sc->sc_rx_capability, NULL, NULL, NULL, 1))
1878		goto out;
1879
1880out:
1881	if (rsp != NULL)
1882		free(rsp, M_DEVBUF);
1883
1884	return;
1885}
1886