if_bce.c revision 157724
1157642Sps/*-
2157642Sps * Copyright (c) 2006 Broadcom Corporation
3157642Sps *	David Christensen <davidch@broadcom.com>.  All rights reserved.
4157642Sps *
5157642Sps * Redistribution and use in source and binary forms, with or without
6157642Sps * modification, are permitted provided that the following conditions
7157642Sps * are met:
8157642Sps *
9157642Sps * 1. Redistributions of source code must retain the above copyright
10157642Sps *    notice, this list of conditions and the following disclaimer.
11157642Sps * 2. Redistributions in binary form must reproduce the above copyright
12157642Sps *    notice, this list of conditions and the following disclaimer in the
13157642Sps *    documentation and/or other materials provided with the distribution.
14157642Sps * 3. Neither the name of Broadcom Corporation nor the name of its contributors
15157642Sps *    may be used to endorse or promote products derived from this software
16157642Sps *    without specific prior written consent.
17157642Sps *
18157642Sps * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
19157642Sps * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20157642Sps * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21157642Sps * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
22157642Sps * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23157642Sps * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24157642Sps * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25157642Sps * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26157642Sps * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27157642Sps * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28157642Sps * THE POSSIBILITY OF SUCH DAMAGE.
29157642Sps */
30157642Sps
31157642Sps#include <sys/cdefs.h>
32157642Sps__FBSDID("$FreeBSD: head/sys/dev/bce/if_bce.c 157724 2006-04-13 14:12:26Z ru $");
33157642Sps
34157642Sps/*
35157642Sps * The following controllers are supported by this driver:
36157642Sps *   BCM5706C A2, A3
37157642Sps *   BCM5708C B1
38157642Sps *
39157642Sps * The following controllers are not supported by this driver:
40157642Sps * (These are not "Production" versions of the controller.)
41157642Sps *
42157642Sps *   BCM5706C A0, A1
43157642Sps *   BCM5706S A0, A1, A2, A3
44157642Sps *   BCM5708C A0, B0
45157642Sps *   BCM5708S A0, B0, B1
46157642Sps */
47157642Sps
48157643Sps#include "opt_bce.h"
49157643Sps
50157642Sps#include <dev/bce/if_bcereg.h>
51157642Sps#include <dev/bce/if_bcefw.h>
52157642Sps
53157642Sps/****************************************************************************/
54157642Sps/* BCE Driver Version                                                       */
55157642Sps/****************************************************************************/
56157642Spschar bce_driver_version[] = "v0.9.5";
57157642Sps
58157642Sps
59157642Sps/****************************************************************************/
60157642Sps/* BCE Debug Options                                                        */
61157642Sps/****************************************************************************/
62157642Sps#ifdef BCE_DEBUG
63157642Sps	u32 bce_debug = BCE_WARN;
64157642Sps
65157642Sps	/*          0 = Never              */
66157642Sps	/*          1 = 1 in 2,147,483,648 */
67157642Sps	/*        256 = 1 in     8,388,608 */
68157642Sps	/*       2048 = 1 in     1,048,576 */
69157642Sps	/*      65536 = 1 in        32,768 */
70157642Sps	/*    1048576 = 1 in         2,048 */
71157642Sps	/*  268435456 =	1 in             8 */
72157642Sps	/*  536870912 = 1 in             4 */
73157642Sps	/* 1073741824 = 1 in             2 */
74157642Sps
75157642Sps	/* Controls how often the l2_fhdr frame error check will fail. */
76157642Sps	int bce_debug_l2fhdr_status_check = 0;
77157642Sps
78157642Sps	/* Controls how often the unexpected attention check will fail. */
79157642Sps	int bce_debug_unexpected_attention = 0;
80157642Sps
81157642Sps	/* Controls how often to simulate an mbuf allocation failure. */
82157642Sps	int bce_debug_mbuf_allocation_failure = 0;
83157642Sps
84157642Sps	/* Controls how often to simulate a DMA mapping failure. */
85157642Sps	int bce_debug_dma_map_addr_failure = 0;
86157642Sps
87157642Sps	/* Controls how often to simulate a bootcode failure. */
88157642Sps	int bce_debug_bootcode_running_failure = 0;
89157642Sps#endif
90157642Sps
91157642Sps
92157642Sps/****************************************************************************/
93157642Sps/* PCI Device ID Table                                                      */
94157642Sps/*                                                                          */
95157642Sps/* Used by bce_probe() to identify the devices supported by this driver.    */
96157642Sps/****************************************************************************/
97157642Sps#define BCE_DEVDESC_MAX		64
98157642Sps
99157642Spsstatic struct bce_type bce_devs[] = {
100157642Sps	/* BCM5706C Controllers and OEM boards. */
101157642Sps	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3101,
102157642Sps		"HP NC370T Multifunction Gigabit Server Adapter" },
103157642Sps	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  HP_VENDORID, 0x3106,
104157642Sps		"HP NC370i Multifunction Gigabit Server Adapter" },
105157642Sps	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706,  PCI_ANY_ID,  PCI_ANY_ID,
106157642Sps		"Broadcom NetXtreme II BCM5706 1000Base-T" },
107157642Sps
108157642Sps	/* BCM5706S controllers and OEM boards. */
109157642Sps	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, HP_VENDORID, 0x3102,
110157642Sps		"HP NC370F Multifunction Gigabit Server Adapter" },
111157642Sps	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5706S, PCI_ANY_ID,  PCI_ANY_ID,
112157642Sps		"Broadcom NetXtreme II BCM5706 1000Base-SX" },
113157642Sps
114157642Sps	/* BCM5708C controllers and OEM boards. */
115157642Sps	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708,  PCI_ANY_ID,  PCI_ANY_ID,
116157642Sps		"Broadcom NetXtreme II BCM5708 1000Base-T" },
117157642Sps
118157642Sps	/* BCM5708S controllers and OEM boards. */
119157642Sps	{ BRCM_VENDORID, BRCM_DEVICEID_BCM5708,  PCI_ANY_ID,  PCI_ANY_ID,
120157642Sps		"Broadcom NetXtreme II BCM5708 1000Base-T" },
121157642Sps	{ 0, 0, 0, 0, NULL }
122157642Sps};
123157642Sps
124157642Sps
125157642Sps/****************************************************************************/
126157642Sps/* Supported Flash NVRAM device data.                                       */
127157642Sps/****************************************************************************/
128157642Spsstatic struct flash_spec flash_table[] =
129157642Sps{
130157642Sps	/* Slow EEPROM */
131157642Sps	{0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
132157642Sps	 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
133157642Sps	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
134157642Sps	 "EEPROM - slow"},
135157642Sps	/* Expansion entry 0001 */
136157642Sps	{0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
137157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
138157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
139157642Sps	 "Entry 0001"},
140157642Sps	/* Saifun SA25F010 (non-buffered flash) */
141157642Sps	/* strap, cfg1, & write1 need updates */
142157642Sps	{0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
143157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
144157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
145157642Sps	 "Non-buffered flash (128kB)"},
146157642Sps	/* Saifun SA25F020 (non-buffered flash) */
147157642Sps	/* strap, cfg1, & write1 need updates */
148157642Sps	{0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
149157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
150157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
151157642Sps	 "Non-buffered flash (256kB)"},
152157642Sps	/* Expansion entry 0100 */
153157642Sps	{0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
154157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
155157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
156157642Sps	 "Entry 0100"},
157157642Sps	/* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
158157642Sps	{0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
159157642Sps	 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
160157642Sps	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
161157642Sps	 "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
162157642Sps	/* Entry 0110: ST M45PE20 (non-buffered flash)*/
163157642Sps	{0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
164157642Sps	 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
165157642Sps	 ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
166157642Sps	 "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
167157642Sps	/* Saifun SA25F005 (non-buffered flash) */
168157642Sps	/* strap, cfg1, & write1 need updates */
169157642Sps	{0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
170157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
171157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
172157642Sps	 "Non-buffered flash (64kB)"},
173157642Sps	/* Fast EEPROM */
174157642Sps	{0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
175157642Sps	 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
176157642Sps	 SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
177157642Sps	 "EEPROM - fast"},
178157642Sps	/* Expansion entry 1001 */
179157642Sps	{0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
180157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
181157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
182157642Sps	 "Entry 1001"},
183157642Sps	/* Expansion entry 1010 */
184157642Sps	{0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
185157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
186157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
187157642Sps	 "Entry 1010"},
188157642Sps	/* ATMEL AT45DB011B (buffered flash) */
189157642Sps	{0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
190157642Sps	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
191157642Sps	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
192157642Sps	 "Buffered flash (128kB)"},
193157642Sps	/* Expansion entry 1100 */
194157642Sps	{0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
195157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
196157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
197157642Sps	 "Entry 1100"},
198157642Sps	/* Expansion entry 1101 */
199157642Sps	{0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
200157642Sps	 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
201157642Sps	 SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
202157642Sps	 "Entry 1101"},
203157642Sps	/* Ateml Expansion entry 1110 */
204157642Sps	{0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
205157642Sps	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
206157642Sps	 BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
207157642Sps	 "Entry 1110 (Atmel)"},
208157642Sps	/* ATMEL AT45DB021B (buffered flash) */
209157642Sps	{0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
210157642Sps	 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
211157642Sps	 BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
212157642Sps	 "Buffered flash (256kB)"},
213157642Sps};
214157642Sps
215157642Sps
216157642Sps/****************************************************************************/
217157642Sps/* FreeBSD device entry points.                                             */
218157642Sps/****************************************************************************/
219157642Spsstatic int  bce_probe				(device_t);
220157642Spsstatic int  bce_attach				(device_t);
221157642Spsstatic int  bce_detach				(device_t);
222157642Spsstatic void bce_shutdown			(device_t);
223157642Sps
224157642Sps
225157642Sps/****************************************************************************/
226157642Sps/* BCE Debug Data Structure Dump Routines                                   */
227157642Sps/****************************************************************************/
228157642Sps#ifdef BCE_DEBUG
229157642Spsstatic void bce_dump_mbuf 			(struct bce_softc *, struct mbuf *);
230157642Spsstatic void bce_dump_tx_mbuf_chain	(struct bce_softc *, int, int);
231157642Spsstatic void bce_dump_rx_mbuf_chain	(struct bce_softc *, int, int);
232157642Spsstatic void bce_dump_txbd			(struct bce_softc *, int, struct tx_bd *);
233157642Spsstatic void bce_dump_rxbd			(struct bce_softc *, int, struct rx_bd *);
234157642Spsstatic void bce_dump_l2fhdr			(struct bce_softc *, int, struct l2_fhdr *);
235157642Spsstatic void bce_dump_tx_chain		(struct bce_softc *, int, int);
236157642Spsstatic void bce_dump_rx_chain		(struct bce_softc *, int, int);
237157642Spsstatic void bce_dump_status_block	(struct bce_softc *);
238157642Spsstatic void bce_dump_stats_block	(struct bce_softc *);
239157642Spsstatic void bce_dump_driver_state	(struct bce_softc *);
240157642Spsstatic void bce_dump_hw_state		(struct bce_softc *);
241157642Spsstatic void bce_breakpoint			(struct bce_softc *);
242157642Sps#endif
243157642Sps
244157642Sps
245157642Sps/****************************************************************************/
246157642Sps/* BCE Register/Memory Access Routines                                      */
247157642Sps/****************************************************************************/
248157642Spsstatic u32  bce_reg_rd_ind			(struct bce_softc *, u32);
249157642Spsstatic void bce_reg_wr_ind			(struct bce_softc *, u32, u32);
250157642Spsstatic void bce_ctx_wr				(struct bce_softc *, u32, u32, u32);
251157642Spsstatic int  bce_miibus_read_reg		(device_t, int, int);
252157642Spsstatic int  bce_miibus_write_reg	(device_t, int, int, int);
253157642Spsstatic void bce_miibus_statchg		(device_t);
254157642Sps
255157642Sps
256157642Sps/****************************************************************************/
257157642Sps/* BCE NVRAM Access Routines                                                */
258157642Sps/****************************************************************************/
259157642Spsstatic int  bce_acquire_nvram_lock	(struct bce_softc *);
260157642Spsstatic int  bce_release_nvram_lock	(struct bce_softc *);
261157642Spsstatic void bce_enable_nvram_access	(struct bce_softc *);
262157642Spsstatic void	bce_disable_nvram_access(struct bce_softc *);
263157642Spsstatic int  bce_nvram_read_dword	(struct bce_softc *, u32, u8 *, u32);
264157642Spsstatic int  bce_init_nvram			(struct bce_softc *);
265157642Spsstatic int  bce_nvram_read			(struct bce_softc *, u32, u8 *, int);
266157642Spsstatic int  bce_nvram_test			(struct bce_softc *);
267157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT
268157642Spsstatic int  bce_enable_nvram_write	(struct bce_softc *);
269157642Spsstatic void bce_disable_nvram_write	(struct bce_softc *);
270157642Spsstatic int  bce_nvram_erase_page	(struct bce_softc *, u32);
271157642Spsstatic int  bce_nvram_write_dword	(struct bce_softc *, u32, u8 *, u32);
272157642Spsstatic int  bce_nvram_write			(struct bce_softc *, u32, u8 *, int);
273157642Sps#endif
274157642Sps
275157642Sps/****************************************************************************/
276157642Sps/*                                                                          */
277157642Sps/****************************************************************************/
278157642Spsstatic void bce_dma_map_addr		(void *, bus_dma_segment_t *, int, int);
279157642Spsstatic void bce_dma_map_tx_desc		(void *, bus_dma_segment_t *, int, bus_size_t, int);
280157642Spsstatic int  bce_dma_alloc			(device_t);
281157642Spsstatic void bce_dma_free			(struct bce_softc *);
282157642Spsstatic void bce_release_resources	(struct bce_softc *);
283157642Sps
284157642Sps/****************************************************************************/
285157642Sps/* BCE Firmware Synchronization and Load                                    */
286157642Sps/****************************************************************************/
287157642Spsstatic int  bce_fw_sync				(struct bce_softc *, u32);
288157642Spsstatic void bce_load_rv2p_fw		(struct bce_softc *, u32 *, u32, u32);
289157642Spsstatic void bce_load_cpu_fw			(struct bce_softc *, struct cpu_reg *, struct fw_info *);
290157642Spsstatic void bce_init_cpus			(struct bce_softc *);
291157642Sps
292157642Spsstatic void bce_stop				(struct bce_softc *);
293157642Spsstatic int  bce_reset				(struct bce_softc *, u32);
294157642Spsstatic int  bce_chipinit 			(struct bce_softc *);
295157642Spsstatic int  bce_blockinit 			(struct bce_softc *);
296157642Spsstatic int  bce_get_buf				(struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *);
297157642Sps
298157642Spsstatic int  bce_init_tx_chain		(struct bce_softc *);
299157642Spsstatic int  bce_init_rx_chain		(struct bce_softc *);
300157642Spsstatic void bce_free_rx_chain		(struct bce_softc *);
301157642Spsstatic void bce_free_tx_chain		(struct bce_softc *);
302157642Sps
303157642Spsstatic int  bce_tx_encap			(struct bce_softc *, struct mbuf *, u16 *, u16 *, u32 *);
304157642Spsstatic void bce_start_locked		(struct ifnet *);
305157642Spsstatic void bce_start				(struct ifnet *);
306157642Spsstatic int  bce_ioctl				(struct ifnet *, u_long, caddr_t);
307157642Spsstatic void bce_watchdog			(struct ifnet *);
308157642Spsstatic int  bce_ifmedia_upd			(struct ifnet *);
309157642Spsstatic void bce_ifmedia_sts			(struct ifnet *, struct ifmediareq *);
310157642Spsstatic void bce_init_locked			(struct bce_softc *);
311157642Spsstatic void bce_init				(void *);
312157642Sps
313157642Spsstatic void bce_init_context		(struct bce_softc *);
314157642Spsstatic void bce_get_mac_addr		(struct bce_softc *);
315157642Spsstatic void bce_set_mac_addr		(struct bce_softc *);
316157642Spsstatic void bce_phy_intr			(struct bce_softc *);
317157642Spsstatic void bce_rx_intr				(struct bce_softc *);
318157642Spsstatic void bce_tx_intr				(struct bce_softc *);
319157642Spsstatic void bce_disable_intr		(struct bce_softc *);
320157642Spsstatic void bce_enable_intr			(struct bce_softc *);
321157642Sps
322157642Sps#ifdef DEVICE_POLLING
323157642Spsstatic void bce_poll_locked			(struct ifnet *, enum poll_cmd, int);
324157642Spsstatic void bce_poll				(struct ifnet *, enum poll_cmd, int);
325157642Sps#endif
326157642Spsstatic void bce_intr				(void *);
327157642Spsstatic void bce_set_rx_mode			(struct bce_softc *);
328157642Spsstatic void bce_stats_update		(struct bce_softc *);
329157642Spsstatic void bce_tick_locked			(struct bce_softc *);
330157642Spsstatic void bce_tick				(void *);
331157642Spsstatic void bce_add_sysctls			(struct bce_softc *);
332157642Sps
333157642Sps
334157642Sps/****************************************************************************/
335157642Sps/* FreeBSD device dispatch table.                                           */
336157642Sps/****************************************************************************/
337157642Spsstatic device_method_t bce_methods[] = {
338157642Sps	/* Device interface */
339157642Sps	DEVMETHOD(device_probe,		bce_probe),
340157642Sps	DEVMETHOD(device_attach,	bce_attach),
341157642Sps	DEVMETHOD(device_detach,	bce_detach),
342157642Sps	DEVMETHOD(device_shutdown,	bce_shutdown),
343157642Sps
344157642Sps	/* bus interface */
345157642Sps	DEVMETHOD(bus_print_child,	bus_generic_print_child),
346157642Sps	DEVMETHOD(bus_driver_added,	bus_generic_driver_added),
347157642Sps
348157642Sps	/* MII interface */
349157642Sps	DEVMETHOD(miibus_readreg,	bce_miibus_read_reg),
350157642Sps	DEVMETHOD(miibus_writereg,	bce_miibus_write_reg),
351157642Sps	DEVMETHOD(miibus_statchg,	bce_miibus_statchg),
352157642Sps
353157642Sps	{ 0, 0 }
354157642Sps};
355157642Sps
356157642Spsstatic driver_t bce_driver = {
357157642Sps	"bce",
358157642Sps	bce_methods,
359157642Sps	sizeof(struct bce_softc)
360157642Sps};
361157642Sps
362157642Spsstatic devclass_t bce_devclass;
363157642Sps
364157642SpsMODULE_DEPEND(bce, pci, 1, 1, 1);
365157642SpsMODULE_DEPEND(bce, ether, 1, 1, 1);
366157642SpsMODULE_DEPEND(bce, miibus, 1, 1, 1);
367157642Sps
368157642SpsDRIVER_MODULE(bce, pci, bce_driver, bce_devclass, 0, 0);
369157642SpsDRIVER_MODULE(miibus, bce, miibus_driver, miibus_devclass, 0, 0);
370157642Sps
371157642Sps
372157642Sps/****************************************************************************/
373157642Sps/* Device probe function.                                                   */
374157642Sps/*                                                                          */
375157642Sps/* Compares the device to the driver's list of supported devices and        */
376157642Sps/* reports back to the OS whether this is the right driver for the device.  */
377157642Sps/*                                                                          */
378157642Sps/* Returns:                                                                 */
379157642Sps/*   BUS_PROBE_DEFAULT on success, positive value on failure.               */
380157642Sps/****************************************************************************/
381157642Spsstatic int
382157642Spsbce_probe(device_t dev)
383157642Sps{
384157642Sps	struct bce_type *t;
385157642Sps	struct bce_softc *sc;
386157642Sps	char *descbuf;
387157642Sps	u16 vid = 0, did = 0, svid = 0, sdid = 0;
388157642Sps
389157642Sps	t = bce_devs;
390157642Sps
391157642Sps	sc = device_get_softc(dev);
392157642Sps	bzero(sc, sizeof(struct bce_softc));
393157642Sps	sc->bce_unit = device_get_unit(dev);
394157642Sps	sc->bce_dev = dev;
395157642Sps
396157642Sps	/* Get the data for the device to be probed. */
397157642Sps	vid  = pci_get_vendor(dev);
398157642Sps	did  = pci_get_device(dev);
399157642Sps	svid = pci_get_subvendor(dev);
400157642Sps	sdid = pci_get_subdevice(dev);
401157642Sps
402157642Sps	DBPRINT(sc, BCE_VERBOSE_LOAD,
403157642Sps		"%s(); VID = 0x%04X, DID = 0x%04X, SVID = 0x%04X, "
404157642Sps		"SDID = 0x%04X\n", __FUNCTION__, vid, did, svid, sdid);
405157642Sps
406157642Sps	/* Look through the list of known devices for a match. */
407157642Sps	while(t->bce_name != NULL) {
408157642Sps
409157642Sps		if ((vid == t->bce_vid) && (did == t->bce_did) &&
410157642Sps			((svid == t->bce_svid) || (t->bce_svid == PCI_ANY_ID)) &&
411157642Sps			((sdid == t->bce_sdid) || (t->bce_sdid == PCI_ANY_ID))) {
412157642Sps
413157642Sps			descbuf = malloc(BCE_DEVDESC_MAX, M_TEMP, M_NOWAIT);
414157642Sps
415157642Sps			if (descbuf == NULL)
416157642Sps				return(ENOMEM);
417157642Sps
418157642Sps			/* Print out the device identity. */
419157642Sps			snprintf(descbuf, BCE_DEVDESC_MAX, "%s (%c%d), %s",
420157642Sps				t->bce_name,
421157642Sps			    (((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
422157642Sps			    (pci_read_config(dev, PCIR_REVID, 4) & 0xf),
423157642Sps			    bce_driver_version);
424157642Sps
425157642Sps			device_set_desc_copy(dev, descbuf);
426157642Sps			free(descbuf, M_TEMP);
427157642Sps			return(BUS_PROBE_DEFAULT);
428157642Sps		}
429157642Sps		t++;
430157642Sps	}
431157642Sps
432157642Sps	DBPRINT(sc, BCE_VERBOSE_LOAD, "%s(%d): No IOCTL match found!\n",
433157642Sps		__FILE__, __LINE__);
434157642Sps
435157642Sps	return(ENXIO);
436157642Sps}
437157642Sps
438157642Sps
439157642Sps/****************************************************************************/
440157642Sps/* Device attach function.                                                  */
441157642Sps/*                                                                          */
442157642Sps/* Allocates device resources, performs secondary chip identification,      */
443157642Sps/* resets and initializes the hardware, and initializes driver instance     */
444157642Sps/* variables.                                                               */
445157642Sps/*                                                                          */
446157642Sps/* Returns:                                                                 */
447157642Sps/*   0 on success, positive value on failure.                               */
448157642Sps/****************************************************************************/
449157642Spsstatic int
450157642Spsbce_attach(device_t dev)
451157642Sps{
452157642Sps	struct bce_softc *sc;
453157642Sps	struct ifnet *ifp;
454157642Sps	u32 val;
455157642Sps	int mbuf, rid, rc = 0;
456157642Sps
457157642Sps	sc = device_get_softc(dev);
458157642Sps	sc->bce_dev = dev;
459157642Sps
460157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
461157642Sps
462157642Sps	mbuf = device_get_unit(dev);
463157642Sps	sc->bce_unit = mbuf;
464157642Sps
465157642Sps	pci_enable_busmaster(dev);
466157642Sps
467157642Sps	/* Allocate PCI memory resources. */
468157642Sps	rid = PCIR_BAR(0);
469157642Sps	sc->bce_res = bus_alloc_resource_any(
470157642Sps		dev, 							/* dev */
471157642Sps		SYS_RES_MEMORY, 				/* type */
472157642Sps		&rid,							/* rid */
473157642Sps	    RF_ACTIVE | PCI_RF_DENSE);		/* flags */
474157642Sps
475157642Sps	if (sc->bce_res == NULL) {
476157642Sps		BCE_PRINTF(sc, "%s(%d): PCI memory allocation failed\n",
477157642Sps			__FILE__, __LINE__);
478157642Sps		rc = ENXIO;
479157642Sps		goto bce_attach_fail;
480157642Sps	}
481157642Sps
482157642Sps	/* Get various resource handles. */
483157642Sps	sc->bce_btag    = rman_get_bustag(sc->bce_res);
484157642Sps	sc->bce_bhandle = rman_get_bushandle(sc->bce_res);
485157642Sps	sc->bce_vhandle = (vm_offset_t) rman_get_virtual(sc->bce_res);
486157642Sps
487157642Sps	/* Allocate PCI IRQ resources. */
488157642Sps	rid = 0;
489157642Sps	sc->bce_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
490157642Sps	    RF_SHAREABLE | RF_ACTIVE);
491157642Sps
492157642Sps	if (sc->bce_irq == NULL) {
493157642Sps		BCE_PRINTF(sc, "%s(%d): PCI map interrupt failed\n",
494157642Sps			__FILE__, __LINE__);
495157642Sps		rc = ENXIO;
496157642Sps		goto bce_attach_fail;
497157642Sps	}
498157642Sps
499157642Sps	/* Initialize mutex for the current device instance. */
500157642Sps	BCE_LOCK_INIT(sc, device_get_nameunit(dev));
501157642Sps
502157642Sps	/*
503157642Sps	 * Configure byte swap and enable indirect register access.
504157642Sps	 * Rely on CPU to do target byte swapping on big endian systems.
505157642Sps	 * Access to registers outside of PCI configurtion space are not
506157642Sps	 * valid until this is done.
507157642Sps	 */
508157642Sps	pci_write_config(dev, BCE_PCICFG_MISC_CONFIG,
509157642Sps			       BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
510157642Sps			       BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP, 4);
511157642Sps
512157642Sps	/* Save ASIC revsion info. */
513157642Sps	sc->bce_chipid =  REG_RD(sc, BCE_MISC_ID);
514157642Sps
515157642Sps	/* Weed out any non-production controller revisions. */
516157642Sps	switch(BCE_CHIP_ID(sc)) {
517157642Sps		case BCE_CHIP_ID_5706_A0:
518157642Sps		case BCE_CHIP_ID_5706_A1:
519157642Sps		case BCE_CHIP_ID_5708_A0:
520157642Sps		case BCE_CHIP_ID_5708_B0:
521157642Sps			BCE_PRINTF(sc, "%s(%d): Unsupported controller revision (%c%d)!\n",
522157642Sps				__FILE__, __LINE__,
523157642Sps				(((pci_read_config(dev, PCIR_REVID, 4) & 0xf0) >> 4) + 'A'),
524157642Sps			    (pci_read_config(dev, PCIR_REVID, 4) & 0xf));
525157642Sps			rc = ENODEV;
526157642Sps			goto bce_attach_fail;
527157642Sps	}
528157642Sps
529157642Sps	if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) {
530157642Sps		BCE_PRINTF(sc, "%s(%d): SerDes controllers are not supported!\n",
531157642Sps			__FILE__, __LINE__);
532157642Sps		rc = ENODEV;
533157642Sps		goto bce_attach_fail;
534157642Sps	}
535157642Sps
536157642Sps	/*
537157642Sps	 * The embedded PCIe to PCI-X bridge (EPB)
538157642Sps	 * in the 5708 cannot address memory above
539157642Sps	 * 40 bits (E7_5708CB1_23043 & E6_5708SB1_23043).
540157642Sps	 */
541157642Sps	if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708)
542157642Sps		sc->max_bus_addr = BCE_BUS_SPACE_MAXADDR;
543157642Sps	else
544157642Sps		sc->max_bus_addr = BUS_SPACE_MAXADDR;
545157642Sps
546157642Sps	/*
547157642Sps	 * Find the base address for shared memory access.
548157642Sps	 * Newer versions of bootcode use a signature and offset
549157642Sps	 * while older versions use a fixed address.
550157642Sps	 */
551157642Sps	val = REG_RD_IND(sc, BCE_SHM_HDR_SIGNATURE);
552157642Sps	if ((val & BCE_SHM_HDR_SIGNATURE_SIG_MASK) == BCE_SHM_HDR_SIGNATURE_SIG)
553157642Sps		sc->bce_shmem_base = REG_RD_IND(sc, BCE_SHM_HDR_ADDR_0);
554157642Sps	else
555157642Sps		sc->bce_shmem_base = HOST_VIEW_SHMEM_BASE;
556157642Sps
557157642Sps	DBPRINT(sc, BCE_INFO, "bce_shmem_base = 0x%08X\n", sc->bce_shmem_base);
558157642Sps
559157642Sps	/* Set initial device and PHY flags */
560157642Sps	sc->bce_flags = 0;
561157642Sps	sc->bce_phy_flags = 0;
562157642Sps
563157642Sps	/* Get PCI bus information (speed and type). */
564157642Sps	val = REG_RD(sc, BCE_PCICFG_MISC_STATUS);
565157642Sps	if (val & BCE_PCICFG_MISC_STATUS_PCIX_DET) {
566157642Sps		u32 clkreg;
567157642Sps
568157642Sps		sc->bce_flags |= BCE_PCIX_FLAG;
569157642Sps
570157642Sps		clkreg = REG_RD(sc, BCE_PCICFG_PCI_CLOCK_CONTROL_BITS);
571157642Sps
572157642Sps		clkreg &= BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
573157642Sps		switch (clkreg) {
574157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
575157642Sps			sc->bus_speed_mhz = 133;
576157642Sps			break;
577157642Sps
578157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
579157642Sps			sc->bus_speed_mhz = 100;
580157642Sps			break;
581157642Sps
582157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
583157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
584157642Sps			sc->bus_speed_mhz = 66;
585157642Sps			break;
586157642Sps
587157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
588157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
589157642Sps			sc->bus_speed_mhz = 50;
590157642Sps			break;
591157642Sps
592157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
593157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
594157642Sps		case BCE_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
595157642Sps			sc->bus_speed_mhz = 33;
596157642Sps			break;
597157642Sps		}
598157642Sps	} else {
599157642Sps		if (val & BCE_PCICFG_MISC_STATUS_M66EN)
600157642Sps			sc->bus_speed_mhz = 66;
601157642Sps		else
602157642Sps			sc->bus_speed_mhz = 33;
603157642Sps	}
604157642Sps
605157642Sps	if (val & BCE_PCICFG_MISC_STATUS_32BIT_DET)
606157642Sps		sc->bce_flags |= BCE_PCI_32BIT_FLAG;
607157642Sps
608157642Sps	BCE_PRINTF(sc, "ASIC ID 0x%08X; Revision (%c%d); PCI%s %s %dMHz\n",
609157642Sps		sc->bce_chipid,
610157642Sps		((BCE_CHIP_ID(sc) & 0xf000) >> 12) + 'A',
611157642Sps		((BCE_CHIP_ID(sc) & 0x0ff0) >> 4),
612157642Sps		((sc->bce_flags & BCE_PCIX_FLAG) ? "-X" : ""),
613157642Sps		((sc->bce_flags & BCE_PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
614157642Sps		sc->bus_speed_mhz);
615157642Sps
616157642Sps	/* Reset the controller. */
617157642Sps	if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) {
618157642Sps		rc = ENXIO;
619157642Sps		goto bce_attach_fail;
620157642Sps	}
621157642Sps
622157642Sps	/* Initialize the controller. */
623157642Sps	if (bce_chipinit(sc)) {
624157642Sps		BCE_PRINTF(sc, "%s(%d): Controller initialization failed!\n",
625157642Sps			__FILE__, __LINE__);
626157642Sps		rc = ENXIO;
627157642Sps		goto bce_attach_fail;
628157642Sps	}
629157642Sps
630157642Sps	/* Perform NVRAM test. */
631157642Sps	if (bce_nvram_test(sc)) {
632157642Sps		BCE_PRINTF(sc, "%s(%d): NVRAM test failed!\n",
633157642Sps			__FILE__, __LINE__);
634157642Sps		rc = ENXIO;
635157642Sps		goto bce_attach_fail;
636157642Sps	}
637157642Sps
638157642Sps	/* Fetch the permanent Ethernet MAC address. */
639157642Sps	bce_get_mac_addr(sc);
640157642Sps
641157642Sps	/*
642157642Sps	 * Trip points control how many BDs
643157642Sps	 * should be ready before generating an
644157642Sps	 * interrupt while ticks control how long
645157642Sps	 * a BD can sit in the chain before
646157642Sps	 * generating an interrupt.  Set the default
647157642Sps	 * values for the RX and TX rings.
648157642Sps	 */
649157642Sps
650157642Sps#ifdef BCE_DRBUG
651157642Sps	/* Force more frequent interrupts. */
652157642Sps	sc->bce_tx_quick_cons_trip_int = 1;
653157642Sps	sc->bce_tx_quick_cons_trip     = 1;
654157642Sps	sc->bce_tx_ticks_int           = 0;
655157642Sps	sc->bce_tx_ticks               = 0;
656157642Sps
657157642Sps	sc->bce_rx_quick_cons_trip_int = 1;
658157642Sps	sc->bce_rx_quick_cons_trip     = 1;
659157642Sps	sc->bce_rx_ticks_int           = 0;
660157642Sps	sc->bce_rx_ticks               = 0;
661157642Sps#else
662157642Sps	sc->bce_tx_quick_cons_trip_int = 20;
663157642Sps	sc->bce_tx_quick_cons_trip     = 20;
664157642Sps	sc->bce_tx_ticks_int           = 80;
665157642Sps	sc->bce_tx_ticks               = 80;
666157642Sps
667157642Sps	sc->bce_rx_quick_cons_trip_int = 6;
668157642Sps	sc->bce_rx_quick_cons_trip     = 6;
669157642Sps	sc->bce_rx_ticks_int           = 18;
670157642Sps	sc->bce_rx_ticks               = 18;
671157642Sps#endif
672157642Sps
673157642Sps	/* Update statistics once every second. */
674157642Sps	sc->bce_stats_ticks = 1000000 & 0xffff00;
675157642Sps
676157642Sps	/*
677157642Sps	 * The copper based NetXtreme II controllers
678157642Sps	 * use an integrated PHY at address 1 while
679157642Sps	 * the SerDes controllers use a PHY at
680157642Sps	 * address 2.
681157642Sps	 */
682157642Sps	sc->bce_phy_addr = 1;
683157642Sps
684157642Sps	if (BCE_CHIP_BOND_ID(sc) & BCE_CHIP_BOND_ID_SERDES_BIT) {
685157642Sps		sc->bce_phy_flags |= BCE_PHY_SERDES_FLAG;
686157642Sps		sc->bce_flags |= BCE_NO_WOL_FLAG;
687157642Sps		if (BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5708) {
688157642Sps			sc->bce_phy_addr = 2;
689157642Sps			val = REG_RD_IND(sc, sc->bce_shmem_base +
690157642Sps					 BCE_SHARED_HW_CFG_CONFIG);
691157642Sps			if (val & BCE_SHARED_HW_CFG_PHY_2_5G)
692157642Sps				sc->bce_phy_flags |= BCE_PHY_2_5G_CAPABLE_FLAG;
693157642Sps		}
694157642Sps	}
695157642Sps
696157642Sps	/* Allocate DMA memory resources. */
697157642Sps	if (bce_dma_alloc(dev)) {
698157642Sps		BCE_PRINTF(sc, "%s(%d): DMA resource allocation failed!\n",
699157642Sps		    __FILE__, __LINE__);
700157642Sps		rc = ENXIO;
701157642Sps		goto bce_attach_fail;
702157642Sps	}
703157642Sps
704157642Sps	/* Allocate an ifnet structure. */
705157642Sps	ifp = sc->bce_ifp = if_alloc(IFT_ETHER);
706157642Sps	if (ifp == NULL) {
707157642Sps		BCE_PRINTF(sc, "%s(%d): Interface allocation failed!\n",
708157642Sps			__FILE__, __LINE__);
709157642Sps		rc = ENXIO;
710157642Sps		goto bce_attach_fail;
711157642Sps	}
712157642Sps
713157642Sps	/* Initialize the ifnet interface. */
714157642Sps	ifp->if_softc        = sc;
715157642Sps	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
716157642Sps	ifp->if_flags        = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
717157642Sps	ifp->if_ioctl        = bce_ioctl;
718157642Sps	ifp->if_start        = bce_start;
719157642Sps	ifp->if_timer        = 0;
720157642Sps	ifp->if_watchdog     = bce_watchdog;
721157642Sps	ifp->if_init         = bce_init;
722157642Sps	ifp->if_mtu          = ETHERMTU;
723157642Sps	ifp->if_hwassist     = BCE_IF_HWASSIST;
724157642Sps	ifp->if_capabilities = BCE_IF_CAPABILITIES;
725157642Sps	ifp->if_capenable    = ifp->if_capabilities;
726157642Sps
727157642Sps	/* Assume a standard 1500 byte MTU size for mbuf allocations. */
728157642Sps	sc->mbuf_alloc_size  = MCLBYTES;
729157642Sps#ifdef DEVICE_POLLING
730157642Sps	ifp->if_capabilities |= IFCAP_POLLING;
731157642Sps#endif
732157642Sps
733157642Sps	ifp->if_snd.ifq_drv_maxlen = USABLE_TX_BD;
734157642Sps	if (sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)
735157642Sps		ifp->if_baudrate = IF_Gbps(2.5);
736157642Sps	else
737157642Sps		ifp->if_baudrate = IF_Gbps(1);
738157642Sps
739157642Sps	IFQ_SET_MAXLEN(&ifp->if_snd, ifp->if_snd.ifq_drv_maxlen);
740157642Sps	IFQ_SET_READY(&ifp->if_snd);
741157642Sps
742157642Sps	if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) {
743157642Sps		BCE_PRINTF(sc, "%s(%d): SerDes is not supported by this driver!\n",
744157642Sps			__FILE__, __LINE__);
745157642Sps		rc = ENODEV;
746157642Sps		goto bce_attach_fail;
747157642Sps	} else {
748157642Sps		/* Look for our PHY. */
749157642Sps		if (mii_phy_probe(dev, &sc->bce_miibus, bce_ifmedia_upd,
750157642Sps			bce_ifmedia_sts)) {
751157642Sps			BCE_PRINTF(sc, "%s(%d): PHY probe failed!\n",
752157642Sps				__FILE__, __LINE__);
753157642Sps			rc = ENXIO;
754157642Sps			goto bce_attach_fail;
755157642Sps		}
756157642Sps	}
757157642Sps
758157642Sps	/* Attach to the Ethernet interface list. */
759157642Sps	ether_ifattach(ifp, sc->eaddr);
760157642Sps
761157642Sps#if __FreeBSD_version < 500000
762157642Sps	callout_init(&sc->bce_stat_ch);
763157642Sps#else
764157642Sps	callout_init(&sc->bce_stat_ch, CALLOUT_MPSAFE);
765157642Sps#endif
766157642Sps
767157642Sps	/* Hookup IRQ last. */
768157642Sps	rc = bus_setup_intr(dev, sc->bce_irq, INTR_TYPE_NET | INTR_MPSAFE,
769157642Sps	   bce_intr, sc, &sc->bce_intrhand);
770157642Sps
771157642Sps	if (rc) {
772157642Sps		BCE_PRINTF(sc, "%s(%d): Failed to setup IRQ!\n",
773157642Sps			__FILE__, __LINE__);
774157642Sps		bce_detach(dev);
775157642Sps		goto bce_attach_exit;
776157642Sps	}
777157642Sps
778157642Sps	/* Print some important debugging info. */
779157642Sps	DBRUN(BCE_INFO, bce_dump_driver_state(sc));
780157642Sps
781157642Sps	/* Add the supported sysctls to the kernel. */
782157642Sps	bce_add_sysctls(sc);
783157642Sps
784157642Sps	goto bce_attach_exit;
785157642Sps
786157642Spsbce_attach_fail:
787157642Sps	bce_release_resources(sc);
788157642Sps
789157642Spsbce_attach_exit:
790157642Sps
791157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
792157642Sps
793157642Sps	return(rc);
794157642Sps}
795157642Sps
796157642Sps
797157642Sps/****************************************************************************/
798157642Sps/* Device detach function.                                                  */
799157642Sps/*                                                                          */
800157642Sps/* Stops the controller, resets the controller, and releases resources.     */
801157642Sps/*                                                                          */
802157642Sps/* Returns:                                                                 */
803157642Sps/*   0 on success, positive value on failure.                               */
804157642Sps/****************************************************************************/
805157642Spsstatic int
806157642Spsbce_detach(device_t dev)
807157642Sps{
808157642Sps	struct bce_softc *sc;
809157642Sps	struct ifnet *ifp;
810157642Sps
811157642Sps	sc = device_get_softc(dev);
812157642Sps
813157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
814157642Sps
815157642Sps	ifp = sc->bce_ifp;
816157642Sps
817157642Sps#ifdef DEVICE_POLLING
818157642Sps	if (ifp->if_capenable & IFCAP_POLLING)
819157642Sps		ether_poll_deregister(ifp);
820157642Sps#endif
821157642Sps
822157642Sps	/* Stop and reset the controller. */
823157642Sps	BCE_LOCK(sc);
824157642Sps	bce_stop(sc);
825157642Sps	bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
826157642Sps	BCE_UNLOCK(sc);
827157642Sps
828157642Sps	ether_ifdetach(ifp);
829157642Sps
830157642Sps	/* If we have a child device on the MII bus remove it too. */
831157642Sps	if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) {
832157642Sps		ifmedia_removeall(&sc->bce_ifmedia);
833157642Sps	} else {
834157642Sps		bus_generic_detach(dev);
835157642Sps		device_delete_child(dev, sc->bce_miibus);
836157642Sps	}
837157642Sps
838157642Sps	/* Release all remaining resources. */
839157642Sps	bce_release_resources(sc);
840157642Sps
841157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
842157642Sps
843157642Sps	return(0);
844157642Sps}
845157642Sps
846157642Sps
847157642Sps/****************************************************************************/
848157642Sps/* Device shutdown function.                                                */
849157642Sps/*                                                                          */
850157642Sps/* Stops and resets the controller.                                         */
851157642Sps/*                                                                          */
852157642Sps/* Returns:                                                                 */
853157642Sps/*   Nothing                                                                */
854157642Sps/****************************************************************************/
855157642Spsstatic void
856157642Spsbce_shutdown(device_t dev)
857157642Sps{
858157642Sps	struct bce_softc *sc = device_get_softc(dev);
859157642Sps
860157642Sps	BCE_LOCK(sc);
861157642Sps	bce_stop(sc);
862157642Sps	bce_reset(sc, BCE_DRV_MSG_CODE_RESET);
863157642Sps	BCE_UNLOCK(sc);
864157642Sps}
865157642Sps
866157642Sps
867157642Sps/****************************************************************************/
868157642Sps/* Indirect register read.                                                  */
869157642Sps/*                                                                          */
870157642Sps/* Reads NetXtreme II registers using an index/data register pair in PCI    */
871157642Sps/* configuration space.  Using this mechanism avoids issues with posted     */
872157642Sps/* reads but is much slower than memory-mapped I/O.                         */
873157642Sps/*                                                                          */
874157642Sps/* Returns:                                                                 */
875157642Sps/*   The value of the register.                                             */
876157642Sps/****************************************************************************/
877157642Spsstatic u32
878157642Spsbce_reg_rd_ind(struct bce_softc *sc, u32 offset)
879157642Sps{
880157642Sps	device_t dev;
881157642Sps	dev = sc->bce_dev;
882157642Sps
883157642Sps	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
884157642Sps#ifdef BCE_DEBUG
885157642Sps	{
886157642Sps		u32 val;
887157642Sps		val = pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
888157642Sps		DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
889157642Sps			__FUNCTION__, offset, val);
890157642Sps		return val;
891157642Sps	}
892157642Sps#else
893157642Sps	return pci_read_config(dev, BCE_PCICFG_REG_WINDOW, 4);
894157642Sps#endif
895157642Sps}
896157642Sps
897157642Sps
898157642Sps/****************************************************************************/
899157642Sps/* Indirect register write.                                                 */
900157642Sps/*                                                                          */
901157642Sps/* Writes NetXtreme II registers using an index/data register pair in PCI   */
902157642Sps/* configuration space.  Using this mechanism avoids issues with posted     */
903157642Sps/* writes but is muchh slower than memory-mapped I/O.                       */
904157642Sps/*                                                                          */
905157642Sps/* Returns:                                                                 */
906157642Sps/*   Nothing.                                                               */
907157642Sps/****************************************************************************/
908157642Spsstatic void
909157642Spsbce_reg_wr_ind(struct bce_softc *sc, u32 offset, u32 val)
910157642Sps{
911157642Sps	device_t dev;
912157642Sps	dev = sc->bce_dev;
913157642Sps
914157642Sps	DBPRINT(sc, BCE_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
915157642Sps		__FUNCTION__, offset, val);
916157642Sps
917157642Sps	pci_write_config(dev, BCE_PCICFG_REG_WINDOW_ADDRESS, offset, 4);
918157642Sps	pci_write_config(dev, BCE_PCICFG_REG_WINDOW, val, 4);
919157642Sps}
920157642Sps
921157642Sps
922157642Sps/****************************************************************************/
923157642Sps/* Context memory write.                                                    */
924157642Sps/*                                                                          */
925157642Sps/* The NetXtreme II controller uses context memory to track connection      */
926157642Sps/* information for L2 and higher network protocols.                         */
927157642Sps/*                                                                          */
928157642Sps/* Returns:                                                                 */
929157642Sps/*   Nothing.                                                               */
930157642Sps/****************************************************************************/
931157642Spsstatic void
932157642Spsbce_ctx_wr(struct bce_softc *sc, u32 cid_addr, u32 offset, u32 val)
933157642Sps{
934157642Sps
935157642Sps	DBPRINT(sc, BCE_EXCESSIVE, "%s(); cid_addr = 0x%08X, offset = 0x%08X, "
936157642Sps		"val = 0x%08X\n", __FUNCTION__, cid_addr, offset, val);
937157642Sps
938157642Sps	offset += cid_addr;
939157642Sps	REG_WR(sc, BCE_CTX_DATA_ADR, offset);
940157642Sps	REG_WR(sc, BCE_CTX_DATA, val);
941157642Sps}
942157642Sps
943157642Sps
944157642Sps/****************************************************************************/
945157642Sps/* PHY register read.                                                       */
946157642Sps/*                                                                          */
947157642Sps/* Implements register reads on the MII bus.                                */
948157642Sps/*                                                                          */
949157642Sps/* Returns:                                                                 */
950157642Sps/*   The value of the register.                                             */
951157642Sps/****************************************************************************/
952157642Spsstatic int
953157642Spsbce_miibus_read_reg(device_t dev, int phy, int reg)
954157642Sps{
955157642Sps	struct bce_softc *sc;
956157642Sps	u32 val;
957157642Sps	int i;
958157642Sps
959157642Sps	sc = device_get_softc(dev);
960157642Sps
961157642Sps	/* Make sure we are accessing the correct PHY address. */
962157642Sps	if (phy != sc->bce_phy_addr) {
963157642Sps		DBPRINT(sc, BCE_VERBOSE, "Invalid PHY address %d for PHY read!\n", phy);
964157642Sps		return(0);
965157642Sps	}
966157642Sps
967157642Sps	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
968157642Sps		val = REG_RD(sc, BCE_EMAC_MDIO_MODE);
969157642Sps		val &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL;
970157642Sps
971157642Sps		REG_WR(sc, BCE_EMAC_MDIO_MODE, val);
972157642Sps		REG_RD(sc, BCE_EMAC_MDIO_MODE);
973157642Sps
974157642Sps		DELAY(40);
975157642Sps	}
976157642Sps
977157642Sps	val = BCE_MIPHY(phy) | BCE_MIREG(reg) |
978157642Sps		BCE_EMAC_MDIO_COMM_COMMAND_READ | BCE_EMAC_MDIO_COMM_DISEXT |
979157642Sps		BCE_EMAC_MDIO_COMM_START_BUSY;
980157642Sps	REG_WR(sc, BCE_EMAC_MDIO_COMM, val);
981157642Sps
982157642Sps	for (i = 0; i < BCE_PHY_TIMEOUT; i++) {
983157642Sps		DELAY(10);
984157642Sps
985157642Sps		val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
986157642Sps		if (!(val & BCE_EMAC_MDIO_COMM_START_BUSY)) {
987157642Sps			DELAY(5);
988157642Sps
989157642Sps			val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
990157642Sps			val &= BCE_EMAC_MDIO_COMM_DATA;
991157642Sps
992157642Sps			break;
993157642Sps		}
994157642Sps	}
995157642Sps
996157642Sps	if (val & BCE_EMAC_MDIO_COMM_START_BUSY) {
997157642Sps		BCE_PRINTF(sc, "%s(%d): Error: PHY read timeout! phy = %d, reg = 0x%04X\n",
998157642Sps			__FILE__, __LINE__, phy, reg);
999157642Sps		val = 0x0;
1000157642Sps	} else {
1001157642Sps		val = REG_RD(sc, BCE_EMAC_MDIO_COMM);
1002157642Sps	}
1003157642Sps
1004157642Sps	DBPRINT(sc, BCE_EXCESSIVE, "%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n",
1005157642Sps		__FUNCTION__, phy, (u16) reg & 0xffff, (u16) val & 0xffff);
1006157642Sps
1007157642Sps	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
1008157642Sps		val = REG_RD(sc, BCE_EMAC_MDIO_MODE);
1009157642Sps		val |= BCE_EMAC_MDIO_MODE_AUTO_POLL;
1010157642Sps
1011157642Sps		REG_WR(sc, BCE_EMAC_MDIO_MODE, val);
1012157642Sps		REG_RD(sc, BCE_EMAC_MDIO_MODE);
1013157642Sps
1014157642Sps		DELAY(40);
1015157642Sps	}
1016157642Sps
1017157642Sps	return (val & 0xffff);
1018157642Sps
1019157642Sps}
1020157642Sps
1021157642Sps
1022157642Sps/****************************************************************************/
1023157642Sps/* PHY register write.                                                      */
1024157642Sps/*                                                                          */
1025157642Sps/* Implements register writes on the MII bus.                               */
1026157642Sps/*                                                                          */
1027157642Sps/* Returns:                                                                 */
1028157642Sps/*   The value of the register.                                             */
1029157642Sps/****************************************************************************/
1030157642Spsstatic int
1031157642Spsbce_miibus_write_reg(device_t dev, int phy, int reg, int val)
1032157642Sps{
1033157642Sps	struct bce_softc *sc;
1034157642Sps	u32 val1;
1035157642Sps	int i;
1036157642Sps
1037157642Sps	sc = device_get_softc(dev);
1038157642Sps
1039157642Sps	/* Make sure we are accessing the correct PHY address. */
1040157642Sps	if (phy != sc->bce_phy_addr) {
1041157642Sps		DBPRINT(sc, BCE_WARN, "Invalid PHY address %d for PHY write!\n", phy);
1042157642Sps		return(0);
1043157642Sps	}
1044157642Sps
1045157642Sps	DBPRINT(sc, BCE_EXCESSIVE, "%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n",
1046157642Sps		__FUNCTION__, phy, (u16) reg & 0xffff, (u16) val & 0xffff);
1047157642Sps
1048157642Sps	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
1049157642Sps		val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE);
1050157642Sps		val1 &= ~BCE_EMAC_MDIO_MODE_AUTO_POLL;
1051157642Sps
1052157642Sps		REG_WR(sc, BCE_EMAC_MDIO_MODE, val1);
1053157642Sps		REG_RD(sc, BCE_EMAC_MDIO_MODE);
1054157642Sps
1055157642Sps		DELAY(40);
1056157642Sps	}
1057157642Sps
1058157642Sps	val1 = BCE_MIPHY(phy) | BCE_MIREG(reg) | val |
1059157642Sps		BCE_EMAC_MDIO_COMM_COMMAND_WRITE |
1060157642Sps		BCE_EMAC_MDIO_COMM_START_BUSY | BCE_EMAC_MDIO_COMM_DISEXT;
1061157642Sps	REG_WR(sc, BCE_EMAC_MDIO_COMM, val1);
1062157642Sps
1063157642Sps	for (i = 0; i < BCE_PHY_TIMEOUT; i++) {
1064157642Sps		DELAY(10);
1065157642Sps
1066157642Sps		val1 = REG_RD(sc, BCE_EMAC_MDIO_COMM);
1067157642Sps		if (!(val1 & BCE_EMAC_MDIO_COMM_START_BUSY)) {
1068157642Sps			DELAY(5);
1069157642Sps			break;
1070157642Sps		}
1071157642Sps	}
1072157642Sps
1073157642Sps	if (val1 & BCE_EMAC_MDIO_COMM_START_BUSY)
1074157642Sps		BCE_PRINTF(sc, "%s(%d): PHY write timeout!\n",
1075157642Sps			__FILE__, __LINE__);
1076157642Sps
1077157642Sps	if (sc->bce_phy_flags & BCE_PHY_INT_MODE_AUTO_POLLING_FLAG) {
1078157642Sps		val1 = REG_RD(sc, BCE_EMAC_MDIO_MODE);
1079157642Sps		val1 |= BCE_EMAC_MDIO_MODE_AUTO_POLL;
1080157642Sps
1081157642Sps		REG_WR(sc, BCE_EMAC_MDIO_MODE, val1);
1082157642Sps		REG_RD(sc, BCE_EMAC_MDIO_MODE);
1083157642Sps
1084157642Sps		DELAY(40);
1085157642Sps	}
1086157642Sps
1087157642Sps	return 0;
1088157642Sps}
1089157642Sps
1090157642Sps
1091157642Sps/****************************************************************************/
1092157642Sps/* MII bus status change.                                                   */
1093157642Sps/*                                                                          */
1094157642Sps/* Called by the MII bus driver when the PHY establishes link to set the    */
1095157642Sps/* MAC interface registers.                                                 */
1096157642Sps/*                                                                          */
1097157642Sps/* Returns:                                                                 */
1098157642Sps/*   Nothing.                                                               */
1099157642Sps/****************************************************************************/
1100157642Spsstatic void
1101157642Spsbce_miibus_statchg(device_t dev)
1102157642Sps{
1103157642Sps	struct bce_softc *sc;
1104157642Sps	struct mii_data *mii;
1105157642Sps
1106157642Sps	sc = device_get_softc(dev);
1107157642Sps
1108157642Sps	mii = device_get_softc(sc->bce_miibus);
1109157642Sps
1110157642Sps	BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT);
1111157642Sps
1112157642Sps	/* Set MII or GMII inerface based on the speed negotiated by the PHY. */
1113157642Sps	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
1114157642Sps		DBPRINT(sc, BCE_INFO, "Setting GMII interface.\n");
1115157642Sps		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_GMII);
1116157642Sps	} else {
1117157642Sps		DBPRINT(sc, BCE_INFO, "Setting MII interface.\n");
1118157642Sps		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_PORT_MII);
1119157642Sps	}
1120157642Sps
1121157642Sps	/* Set half or full duplex based on the duplicity negotiated by the PHY. */
1122157642Sps	if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
1123157642Sps		DBPRINT(sc, BCE_INFO, "Setting Full-Duplex interface.\n");
1124157642Sps		BCE_CLRBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX);
1125157642Sps	} else {
1126157642Sps		DBPRINT(sc, BCE_INFO, "Setting Half-Duplex interface.\n");
1127157642Sps		BCE_SETBIT(sc, BCE_EMAC_MODE, BCE_EMAC_MODE_HALF_DUPLEX);
1128157642Sps	}
1129157642Sps}
1130157642Sps
1131157642Sps
1132157642Sps/****************************************************************************/
1133157642Sps/* Acquire NVRAM lock.                                                      */
1134157642Sps/*                                                                          */
1135157642Sps/* Before the NVRAM can be accessed the caller must acquire an NVRAM lock.  */
1136157642Sps/* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is     */
1137157642Sps/* for use by the driver.                                                   */
1138157642Sps/*                                                                          */
1139157642Sps/* Returns:                                                                 */
1140157642Sps/*   0 on success, positive value on failure.                               */
1141157642Sps/****************************************************************************/
1142157642Spsstatic int
1143157642Spsbce_acquire_nvram_lock(struct bce_softc *sc)
1144157642Sps{
1145157642Sps	u32 val;
1146157642Sps	int j;
1147157642Sps
1148157642Sps	DBPRINT(sc, BCE_VERBOSE, "Acquiring NVRAM lock.\n");
1149157642Sps
1150157642Sps	/* Request access to the flash interface. */
1151157642Sps	REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_SET2);
1152157642Sps	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
1153157642Sps		val = REG_RD(sc, BCE_NVM_SW_ARB);
1154157642Sps		if (val & BCE_NVM_SW_ARB_ARB_ARB2)
1155157642Sps			break;
1156157642Sps
1157157642Sps		DELAY(5);
1158157642Sps	}
1159157642Sps
1160157642Sps	if (j >= NVRAM_TIMEOUT_COUNT) {
1161157642Sps		DBPRINT(sc, BCE_WARN, "Timeout acquiring NVRAM lock!\n");
1162157642Sps		return EBUSY;
1163157642Sps	}
1164157642Sps
1165157642Sps	return 0;
1166157642Sps}
1167157642Sps
1168157642Sps
1169157642Sps/****************************************************************************/
1170157642Sps/* Release NVRAM lock.                                                      */
1171157642Sps/*                                                                          */
1172157642Sps/* When the caller is finished accessing NVRAM the lock must be released.   */
1173157642Sps/* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is     */
1174157642Sps/* for use by the driver.                                                   */
1175157642Sps/*                                                                          */
1176157642Sps/* Returns:                                                                 */
1177157642Sps/*   0 on success, positive value on failure.                               */
1178157642Sps/****************************************************************************/
1179157642Spsstatic int
1180157642Spsbce_release_nvram_lock(struct bce_softc *sc)
1181157642Sps{
1182157642Sps	int j;
1183157642Sps	u32 val;
1184157642Sps
1185157642Sps	DBPRINT(sc, BCE_VERBOSE, "Releasing NVRAM lock.\n");
1186157642Sps
1187157642Sps	/*
1188157642Sps	 * Relinquish nvram interface.
1189157642Sps	 */
1190157642Sps	REG_WR(sc, BCE_NVM_SW_ARB, BCE_NVM_SW_ARB_ARB_REQ_CLR2);
1191157642Sps
1192157642Sps	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
1193157642Sps		val = REG_RD(sc, BCE_NVM_SW_ARB);
1194157642Sps		if (!(val & BCE_NVM_SW_ARB_ARB_ARB2))
1195157642Sps			break;
1196157642Sps
1197157642Sps		DELAY(5);
1198157642Sps	}
1199157642Sps
1200157642Sps	if (j >= NVRAM_TIMEOUT_COUNT) {
1201157642Sps		DBPRINT(sc, BCE_WARN, "Timeout reeasing NVRAM lock!\n");
1202157642Sps		return EBUSY;
1203157642Sps	}
1204157642Sps
1205157642Sps	return 0;
1206157642Sps}
1207157642Sps
1208157642Sps
1209157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT
1210157642Sps/****************************************************************************/
1211157642Sps/* Enable NVRAM write access.                                               */
1212157642Sps/*                                                                          */
1213157642Sps/* Before writing to NVRAM the caller must enable NVRAM writes.             */
1214157642Sps/*                                                                          */
1215157642Sps/* Returns:                                                                 */
1216157642Sps/*   0 on success, positive value on failure.                               */
1217157642Sps/****************************************************************************/
1218157642Spsstatic int
1219157642Spsbce_enable_nvram_write(struct bce_softc *sc)
1220157642Sps{
1221157642Sps	u32 val;
1222157642Sps
1223157642Sps	DBPRINT(sc, BCE_VERBOSE, "Enabling NVRAM write.\n");
1224157642Sps
1225157642Sps	val = REG_RD(sc, BCE_MISC_CFG);
1226157642Sps	REG_WR(sc, BCE_MISC_CFG, val | BCE_MISC_CFG_NVM_WR_EN_PCI);
1227157642Sps
1228157642Sps	if (!sc->bce_flash_info->buffered) {
1229157642Sps		int j;
1230157642Sps
1231157642Sps		REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
1232157642Sps		REG_WR(sc, BCE_NVM_COMMAND,	BCE_NVM_COMMAND_WREN | BCE_NVM_COMMAND_DOIT);
1233157642Sps
1234157642Sps		for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
1235157642Sps			DELAY(5);
1236157642Sps
1237157642Sps			val = REG_RD(sc, BCE_NVM_COMMAND);
1238157642Sps			if (val & BCE_NVM_COMMAND_DONE)
1239157642Sps				break;
1240157642Sps		}
1241157642Sps
1242157642Sps		if (j >= NVRAM_TIMEOUT_COUNT) {
1243157642Sps			DBPRINT(sc, BCE_WARN, "Timeout writing NVRAM!\n");
1244157642Sps			return EBUSY;
1245157642Sps		}
1246157642Sps	}
1247157642Sps	return 0;
1248157642Sps}
1249157642Sps
1250157642Sps
1251157642Sps/****************************************************************************/
1252157642Sps/* Disable NVRAM write access.                                              */
1253157642Sps/*                                                                          */
1254157642Sps/* When the caller is finished writing to NVRAM write access must be        */
1255157642Sps/* disabled.                                                                */
1256157642Sps/*                                                                          */
1257157642Sps/* Returns:                                                                 */
1258157642Sps/*   Nothing.                                                               */
1259157642Sps/****************************************************************************/
1260157642Spsstatic void
1261157642Spsbce_disable_nvram_write(struct bce_softc *sc)
1262157642Sps{
1263157642Sps	u32 val;
1264157642Sps
1265157642Sps	DBPRINT(sc, BCE_VERBOSE,  "Disabling NVRAM write.\n");
1266157642Sps
1267157642Sps	val = REG_RD(sc, BCE_MISC_CFG);
1268157642Sps	REG_WR(sc, BCE_MISC_CFG, val & ~BCE_MISC_CFG_NVM_WR_EN);
1269157642Sps}
1270157642Sps#endif
1271157642Sps
1272157642Sps
1273157642Sps/****************************************************************************/
1274157642Sps/* Enable NVRAM access.                                                     */
1275157642Sps/*                                                                          */
1276157642Sps/* Before accessing NVRAM for read or write operations the caller must      */
1277157642Sps/* enabled NVRAM access.                                                    */
1278157642Sps/*                                                                          */
1279157642Sps/* Returns:                                                                 */
1280157642Sps/*   Nothing.                                                               */
1281157642Sps/****************************************************************************/
1282157642Spsstatic void
1283157642Spsbce_enable_nvram_access(struct bce_softc *sc)
1284157642Sps{
1285157642Sps	u32 val;
1286157642Sps
1287157642Sps	DBPRINT(sc, BCE_VERBOSE, "Enabling NVRAM access.\n");
1288157642Sps
1289157642Sps	val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
1290157642Sps	/* Enable both bits, even on read. */
1291157642Sps	REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
1292157642Sps	       val | BCE_NVM_ACCESS_ENABLE_EN | BCE_NVM_ACCESS_ENABLE_WR_EN);
1293157642Sps}
1294157642Sps
1295157642Sps
1296157642Sps/****************************************************************************/
1297157642Sps/* Disable NVRAM access.                                                    */
1298157642Sps/*                                                                          */
1299157642Sps/* When the caller is finished accessing NVRAM access must be disabled.     */
1300157642Sps/*                                                                          */
1301157642Sps/* Returns:                                                                 */
1302157642Sps/*   Nothing.                                                               */
1303157642Sps/****************************************************************************/
1304157642Spsstatic void
1305157642Spsbce_disable_nvram_access(struct bce_softc *sc)
1306157642Sps{
1307157642Sps	u32 val;
1308157642Sps
1309157642Sps	DBPRINT(sc, BCE_VERBOSE, "Disabling NVRAM access.\n");
1310157642Sps
1311157642Sps	val = REG_RD(sc, BCE_NVM_ACCESS_ENABLE);
1312157642Sps
1313157642Sps	/* Disable both bits, even after read. */
1314157642Sps	REG_WR(sc, BCE_NVM_ACCESS_ENABLE,
1315157642Sps		val & ~(BCE_NVM_ACCESS_ENABLE_EN |
1316157642Sps			BCE_NVM_ACCESS_ENABLE_WR_EN));
1317157642Sps}
1318157642Sps
1319157642Sps
1320157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT
1321157642Sps/****************************************************************************/
1322157642Sps/* Erase NVRAM page before writing.                                         */
1323157642Sps/*                                                                          */
1324157642Sps/* Non-buffered flash parts require that a page be erased before it is      */
1325157642Sps/* written.                                                                 */
1326157642Sps/*                                                                          */
1327157642Sps/* Returns:                                                                 */
1328157642Sps/*   0 on success, positive value on failure.                               */
1329157642Sps/****************************************************************************/
1330157642Spsstatic int
1331157642Spsbce_nvram_erase_page(struct bce_softc *sc, u32 offset)
1332157642Sps{
1333157642Sps	u32 cmd;
1334157642Sps	int j;
1335157642Sps
1336157642Sps	/* Buffered flash doesn't require an erase. */
1337157642Sps	if (sc->bce_flash_info->buffered)
1338157642Sps		return 0;
1339157642Sps
1340157642Sps	DBPRINT(sc, BCE_VERBOSE, "Erasing NVRAM page.\n");
1341157642Sps
1342157642Sps	/* Build an erase command. */
1343157642Sps	cmd = BCE_NVM_COMMAND_ERASE | BCE_NVM_COMMAND_WR |
1344157642Sps	      BCE_NVM_COMMAND_DOIT;
1345157642Sps
1346157642Sps	/*
1347157642Sps	 * Clear the DONE bit separately, set the NVRAM adress to erase,
1348157642Sps	 * and issue the erase command.
1349157642Sps	 */
1350157642Sps	REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
1351157642Sps	REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE);
1352157642Sps	REG_WR(sc, BCE_NVM_COMMAND, cmd);
1353157642Sps
1354157642Sps	/* Wait for completion. */
1355157642Sps	 */
1356157642Sps	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
1357157642Sps		u32 val;
1358157642Sps
1359157642Sps		DELAY(5);
1360157642Sps
1361157642Sps		val = REG_RD(sc, BCE_NVM_COMMAND);
1362157642Sps		if (val & BCE_NVM_COMMAND_DONE)
1363157642Sps			break;
1364157642Sps	}
1365157642Sps
1366157642Sps	if (j >= NVRAM_TIMEOUT_COUNT) {
1367157642Sps		DBPRINT(sc, BCE_WARN, "Timeout erasing NVRAM.\n");
1368157642Sps		return EBUSY;
1369157642Sps	}
1370157642Sps
1371157642Sps	return 0;
1372157642Sps}
1373157642Sps#endif /* BCE_NVRAM_WRITE_SUPPORT */
1374157642Sps
1375157642Sps
1376157642Sps/****************************************************************************/
1377157642Sps/* Read a dword (32 bits) from NVRAM.                                       */
1378157642Sps/*                                                                          */
1379157642Sps/* Read a 32 bit word from NVRAM.  The caller is assumed to have already    */
1380157642Sps/* obtained the NVRAM lock and enabled the controller for NVRAM access.     */
1381157642Sps/*                                                                          */
1382157642Sps/* Returns:                                                                 */
1383157642Sps/*   0 on success and the 32 bit value read, positive value on failure.     */
1384157642Sps/****************************************************************************/
1385157642Spsstatic int
1386157642Spsbce_nvram_read_dword(struct bce_softc *sc, u32 offset, u8 *ret_val,
1387157642Sps							u32 cmd_flags)
1388157642Sps{
1389157642Sps	u32 cmd;
1390157642Sps	int i, rc = 0;
1391157642Sps
1392157642Sps	/* Build the command word. */
1393157642Sps	cmd = BCE_NVM_COMMAND_DOIT | cmd_flags;
1394157642Sps
1395157642Sps	/* Calculate the offset for buffered flash. */
1396157642Sps	if (sc->bce_flash_info->buffered) {
1397157642Sps		offset = ((offset / sc->bce_flash_info->page_size) <<
1398157642Sps			   sc->bce_flash_info->page_bits) +
1399157642Sps			  (offset % sc->bce_flash_info->page_size);
1400157642Sps	}
1401157642Sps
1402157642Sps	/*
1403157642Sps	 * Clear the DONE bit separately, set the address to read,
1404157642Sps	 * and issue the read.
1405157642Sps	 */
1406157642Sps	REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
1407157642Sps	REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE);
1408157642Sps	REG_WR(sc, BCE_NVM_COMMAND, cmd);
1409157642Sps
1410157642Sps	/* Wait for completion. */
1411157642Sps	for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) {
1412157642Sps		u32 val;
1413157642Sps
1414157642Sps		DELAY(5);
1415157642Sps
1416157642Sps		val = REG_RD(sc, BCE_NVM_COMMAND);
1417157642Sps		if (val & BCE_NVM_COMMAND_DONE) {
1418157642Sps			val = REG_RD(sc, BCE_NVM_READ);
1419157642Sps
1420157642Sps			val = bce_be32toh(val);
1421157642Sps			memcpy(ret_val, &val, 4);
1422157642Sps			break;
1423157642Sps		}
1424157642Sps	}
1425157642Sps
1426157642Sps	/* Check for errors. */
1427157642Sps	if (i >= NVRAM_TIMEOUT_COUNT) {
1428157642Sps		BCE_PRINTF(sc, "%s(%d): Timeout error reading NVRAM at offset 0x%08X!\n",
1429157642Sps			__FILE__, __LINE__, offset);
1430157642Sps		rc = EBUSY;
1431157642Sps	}
1432157642Sps
1433157642Sps	return(rc);
1434157642Sps}
1435157642Sps
1436157642Sps
1437157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT
1438157642Sps/****************************************************************************/
1439157642Sps/* Write a dword (32 bits) to NVRAM.                                        */
1440157642Sps/*                                                                          */
1441157642Sps/* Write a 32 bit word to NVRAM.  The caller is assumed to have already     */
1442157642Sps/* obtained the NVRAM lock, enabled the controller for NVRAM access, and    */
1443157642Sps/* enabled NVRAM write access.                                              */
1444157642Sps/*                                                                          */
1445157642Sps/* Returns:                                                                 */
1446157642Sps/*   0 on success, positive value on failure.                               */
1447157642Sps/****************************************************************************/
1448157642Spsstatic int
1449157642Spsbce_nvram_write_dword(struct bce_softc *sc, u32 offset, u8 *val,
1450157642Sps	u32 cmd_flags)
1451157642Sps{
1452157642Sps	u32 cmd, val32;
1453157642Sps	int j;
1454157642Sps
1455157642Sps	/* Build the command word. */
1456157642Sps	cmd = BCE_NVM_COMMAND_DOIT | BCE_NVM_COMMAND_WR | cmd_flags;
1457157642Sps
1458157642Sps	/* Calculate the offset for buffered flash. */
1459157642Sps	if (sc->bce_flash_info->buffered) {
1460157642Sps		offset = ((offset / sc->bce_flash_info->page_size) <<
1461157642Sps			  sc->bce_flash_info->page_bits) +
1462157642Sps			 (offset % sc->bce_flash_info->page_size);
1463157642Sps	}
1464157642Sps
1465157642Sps	/*
1466157642Sps	 * Clear the DONE bit separately, convert NVRAM data to big-endian,
1467157642Sps	 * set the NVRAM address to write, and issue the write command
1468157642Sps	 */
1469157642Sps	REG_WR(sc, BCE_NVM_COMMAND, BCE_NVM_COMMAND_DONE);
1470157642Sps	memcpy(&val32, val, 4);
1471157642Sps	val32 = htobe32(val32);
1472157642Sps	REG_WR(sc, BCE_NVM_WRITE, val32);
1473157642Sps	REG_WR(sc, BCE_NVM_ADDR, offset & BCE_NVM_ADDR_NVM_ADDR_VALUE);
1474157642Sps	REG_WR(sc, BCE_NVM_COMMAND, cmd);
1475157642Sps
1476157642Sps	/* Wait for completion. */
1477157642Sps	for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
1478157642Sps		DELAY(5);
1479157642Sps
1480157642Sps		if (REG_RD(sc, BCE_NVM_COMMAND) & BCE_NVM_COMMAND_DONE)
1481157642Sps			break;
1482157642Sps	}
1483157642Sps	if (j >= NVRAM_TIMEOUT_COUNT) {
1484157642Sps		BCE_PRINTF(sc, "%s(%d): Timeout error writing NVRAM at offset 0x%08X\n",
1485157642Sps			__FILE__, __LINE__, offset);
1486157642Sps		return EBUSY;
1487157642Sps	}
1488157642Sps
1489157642Sps	return 0;
1490157642Sps}
1491157642Sps#endif /* BCE_NVRAM_WRITE_SUPPORT */
1492157642Sps
1493157642Sps
1494157642Sps/****************************************************************************/
1495157642Sps/* Initialize NVRAM access.                                                 */
1496157642Sps/*                                                                          */
1497157642Sps/* Identify the NVRAM device in use and prepare the NVRAM interface to      */
1498157642Sps/* access that device.                                                      */
1499157642Sps/*                                                                          */
1500157642Sps/* Returns:                                                                 */
1501157642Sps/*   0 on success, positive value on failure.                               */
1502157642Sps/****************************************************************************/
1503157642Spsstatic int
1504157642Spsbce_init_nvram(struct bce_softc *sc)
1505157642Sps{
1506157642Sps	u32 val;
1507157642Sps	int j, entry_count, rc;
1508157642Sps	struct flash_spec *flash;
1509157642Sps
1510157642Sps	DBPRINT(sc,BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
1511157642Sps
1512157642Sps	/* Determine the selected interface. */
1513157642Sps	val = REG_RD(sc, BCE_NVM_CFG1);
1514157642Sps
1515157642Sps	entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
1516157642Sps
1517157642Sps	rc = 0;
1518157642Sps
1519157642Sps	/*
1520157642Sps	 * Flash reconfiguration is required to support additional
1521157642Sps	 * NVRAM devices not directly supported in hardware.
1522157642Sps	 * Check if the flash interface was reconfigured
1523157642Sps	 * by the bootcode.
1524157642Sps	 */
1525157642Sps
1526157642Sps	if (val & 0x40000000) {
1527157642Sps		/* Flash interface reconfigured by bootcode. */
1528157642Sps
1529157642Sps		DBPRINT(sc,BCE_INFO_LOAD,
1530157642Sps			"bce_init_nvram(): Flash WAS reconfigured.\n");
1531157642Sps
1532157642Sps		for (j = 0, flash = &flash_table[0]; j < entry_count;
1533157642Sps		     j++, flash++) {
1534157642Sps			if ((val & FLASH_BACKUP_STRAP_MASK) ==
1535157642Sps			    (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
1536157642Sps				sc->bce_flash_info = flash;
1537157642Sps				break;
1538157642Sps			}
1539157642Sps		}
1540157642Sps	} else {
1541157642Sps		/* Flash interface not yet reconfigured. */
1542157642Sps		u32 mask;
1543157642Sps
1544157642Sps		DBPRINT(sc,BCE_INFO_LOAD,
1545157642Sps			"bce_init_nvram(): Flash was NOT reconfigured.\n");
1546157642Sps
1547157642Sps		if (val & (1 << 23))
1548157642Sps			mask = FLASH_BACKUP_STRAP_MASK;
1549157642Sps		else
1550157642Sps			mask = FLASH_STRAP_MASK;
1551157642Sps
1552157642Sps		/* Look for the matching NVRAM device configuration data. */
1553157642Sps		for (j = 0, flash = &flash_table[0]; j < entry_count; j++, flash++) {
1554157642Sps
1555157642Sps			/* Check if the device matches any of the known devices. */
1556157642Sps			if ((val & mask) == (flash->strapping & mask)) {
1557157642Sps				/* Found a device match. */
1558157642Sps				sc->bce_flash_info = flash;
1559157642Sps
1560157642Sps				/* Request access to the flash interface. */
1561157642Sps				if ((rc = bce_acquire_nvram_lock(sc)) != 0)
1562157642Sps					return rc;
1563157642Sps
1564157642Sps				/* Reconfigure the flash interface. */
1565157642Sps				bce_enable_nvram_access(sc);
1566157642Sps				REG_WR(sc, BCE_NVM_CFG1, flash->config1);
1567157642Sps				REG_WR(sc, BCE_NVM_CFG2, flash->config2);
1568157642Sps				REG_WR(sc, BCE_NVM_CFG3, flash->config3);
1569157642Sps				REG_WR(sc, BCE_NVM_WRITE1, flash->write1);
1570157642Sps				bce_disable_nvram_access(sc);
1571157642Sps				bce_release_nvram_lock(sc);
1572157642Sps
1573157642Sps				break;
1574157642Sps			}
1575157642Sps		}
1576157642Sps	}
1577157642Sps
1578157642Sps	/* Check if a matching device was found. */
1579157642Sps	if (j == entry_count) {
1580157642Sps		sc->bce_flash_info = NULL;
1581157642Sps		BCE_PRINTF(sc, "%s(%d): Unknown Flash NVRAM found!\n",
1582157642Sps			__FILE__, __LINE__);
1583157642Sps		rc = ENODEV;
1584157642Sps	}
1585157642Sps
1586157642Sps	/* Write the flash config data to the shared memory interface. */
1587157642Sps	val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_SHARED_HW_CFG_CONFIG2);
1588157642Sps	val &= BCE_SHARED_HW_CFG2_NVM_SIZE_MASK;
1589157642Sps	if (val)
1590157642Sps		sc->bce_flash_size = val;
1591157642Sps	else
1592157642Sps		sc->bce_flash_size = sc->bce_flash_info->total_size;
1593157642Sps
1594157642Sps	DBPRINT(sc, BCE_INFO_LOAD, "bce_init_nvram() flash->total_size = 0x%08X\n",
1595157642Sps		sc->bce_flash_info->total_size);
1596157642Sps
1597157642Sps	DBPRINT(sc,BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
1598157642Sps
1599157642Sps	return rc;
1600157642Sps}
1601157642Sps
1602157642Sps
1603157642Sps/****************************************************************************/
1604157642Sps/* Read an arbitrary range of data from NVRAM.                              */
1605157642Sps/*                                                                          */
1606157642Sps/* Prepares the NVRAM interface for access and reads the requested data     */
1607157642Sps/* into the supplied buffer.                                                */
1608157642Sps/*                                                                          */
1609157642Sps/* Returns:                                                                 */
1610157642Sps/*   0 on success and the data read, positive value on failure.             */
1611157642Sps/****************************************************************************/
1612157642Spsstatic int
1613157642Spsbce_nvram_read(struct bce_softc *sc, u32 offset, u8 *ret_buf,
1614157642Sps	int buf_size)
1615157642Sps{
1616157642Sps	int rc = 0;
1617157642Sps	u32 cmd_flags, offset32, len32, extra;
1618157642Sps
1619157642Sps	if (buf_size == 0)
1620157642Sps		return 0;
1621157642Sps
1622157642Sps	/* Request access to the flash interface. */
1623157642Sps	if ((rc = bce_acquire_nvram_lock(sc)) != 0)
1624157642Sps		return rc;
1625157642Sps
1626157642Sps	/* Enable access to flash interface */
1627157642Sps	bce_enable_nvram_access(sc);
1628157642Sps
1629157642Sps	len32 = buf_size;
1630157642Sps	offset32 = offset;
1631157642Sps	extra = 0;
1632157642Sps
1633157642Sps	cmd_flags = 0;
1634157642Sps
1635157642Sps	if (offset32 & 3) {
1636157642Sps		u8 buf[4];
1637157642Sps		u32 pre_len;
1638157642Sps
1639157642Sps		offset32 &= ~3;
1640157642Sps		pre_len = 4 - (offset & 3);
1641157642Sps
1642157642Sps		if (pre_len >= len32) {
1643157642Sps			pre_len = len32;
1644157642Sps			cmd_flags = BCE_NVM_COMMAND_FIRST | BCE_NVM_COMMAND_LAST;
1645157642Sps		}
1646157642Sps		else {
1647157642Sps			cmd_flags = BCE_NVM_COMMAND_FIRST;
1648157642Sps		}
1649157642Sps
1650157642Sps		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
1651157642Sps
1652157642Sps		if (rc)
1653157642Sps			return rc;
1654157642Sps
1655157642Sps		memcpy(ret_buf, buf + (offset & 3), pre_len);
1656157642Sps
1657157642Sps		offset32 += 4;
1658157642Sps		ret_buf += pre_len;
1659157642Sps		len32 -= pre_len;
1660157642Sps	}
1661157642Sps
1662157642Sps	if (len32 & 3) {
1663157642Sps		extra = 4 - (len32 & 3);
1664157642Sps		len32 = (len32 + 4) & ~3;
1665157642Sps	}
1666157642Sps
1667157642Sps	if (len32 == 4) {
1668157642Sps		u8 buf[4];
1669157642Sps
1670157642Sps		if (cmd_flags)
1671157642Sps			cmd_flags = BCE_NVM_COMMAND_LAST;
1672157642Sps		else
1673157642Sps			cmd_flags = BCE_NVM_COMMAND_FIRST |
1674157642Sps				    BCE_NVM_COMMAND_LAST;
1675157642Sps
1676157642Sps		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
1677157642Sps
1678157642Sps		memcpy(ret_buf, buf, 4 - extra);
1679157642Sps	}
1680157642Sps	else if (len32 > 0) {
1681157642Sps		u8 buf[4];
1682157642Sps
1683157642Sps		/* Read the first word. */
1684157642Sps		if (cmd_flags)
1685157642Sps			cmd_flags = 0;
1686157642Sps		else
1687157642Sps			cmd_flags = BCE_NVM_COMMAND_FIRST;
1688157642Sps
1689157642Sps		rc = bce_nvram_read_dword(sc, offset32, ret_buf, cmd_flags);
1690157642Sps
1691157642Sps		/* Advance to the next dword. */
1692157642Sps		offset32 += 4;
1693157642Sps		ret_buf += 4;
1694157642Sps		len32 -= 4;
1695157642Sps
1696157642Sps		while (len32 > 4 && rc == 0) {
1697157642Sps			rc = bce_nvram_read_dword(sc, offset32, ret_buf, 0);
1698157642Sps
1699157642Sps			/* Advance to the next dword. */
1700157642Sps			offset32 += 4;
1701157642Sps			ret_buf += 4;
1702157642Sps			len32 -= 4;
1703157642Sps		}
1704157642Sps
1705157642Sps		if (rc)
1706157642Sps			return rc;
1707157642Sps
1708157642Sps		cmd_flags = BCE_NVM_COMMAND_LAST;
1709157642Sps		rc = bce_nvram_read_dword(sc, offset32, buf, cmd_flags);
1710157642Sps
1711157642Sps		memcpy(ret_buf, buf, 4 - extra);
1712157642Sps	}
1713157642Sps
1714157642Sps	/* Disable access to flash interface and release the lock. */
1715157642Sps	bce_disable_nvram_access(sc);
1716157642Sps	bce_release_nvram_lock(sc);
1717157642Sps
1718157642Sps	return rc;
1719157642Sps}
1720157642Sps
1721157642Sps
1722157642Sps#ifdef BCE_NVRAM_WRITE_SUPPORT
1723157642Sps/****************************************************************************/
1724157642Sps/* Write an arbitrary range of data from NVRAM.                             */
1725157642Sps/*                                                                          */
1726157642Sps/* Prepares the NVRAM interface for write access and writes the requested   */
1727157642Sps/* data from the supplied buffer.  The caller is responsible for            */
1728157642Sps/* calculating any appropriate CRCs.                                        */
1729157642Sps/*                                                                          */
1730157642Sps/* Returns:                                                                 */
1731157642Sps/*   0 on success, positive value on failure.                               */
1732157642Sps/****************************************************************************/
1733157642Spsstatic int
1734157642Spsbce_nvram_write(struct bce_softc *sc, u32 offset, u8 *data_buf,
1735157642Sps	int buf_size)
1736157642Sps{
1737157642Sps	u32 written, offset32, len32;
1738157642Sps	u8 *buf, start[4], end[4];
1739157642Sps	int rc = 0;
1740157642Sps	int align_start, align_end;
1741157642Sps
1742157642Sps	buf = data_buf;
1743157642Sps	offset32 = offset;
1744157642Sps	len32 = buf_size;
1745157642Sps	align_start = align_end = 0;
1746157642Sps
1747157642Sps	if ((align_start = (offset32 & 3))) {
1748157642Sps		offset32 &= ~3;
1749157642Sps		len32 += align_start;
1750157642Sps		if ((rc = bce_nvram_read(sc, offset32, start, 4)))
1751157642Sps			return rc;
1752157642Sps	}
1753157642Sps
1754157642Sps	if (len32 & 3) {
1755157642Sps	       	if ((len32 > 4) || !align_start) {
1756157642Sps			align_end = 4 - (len32 & 3);
1757157642Sps			len32 += align_end;
1758157642Sps			if ((rc = bce_nvram_read(sc, offset32 + len32 - 4,
1759157642Sps				end, 4))) {
1760157642Sps				return rc;
1761157642Sps			}
1762157642Sps		}
1763157642Sps	}
1764157642Sps
1765157642Sps	if (align_start || align_end) {
1766157642Sps		buf = malloc(len32, M_DEVBUF, M_NOWAIT);
1767157642Sps		if (buf == 0)
1768157642Sps			return ENOMEM;
1769157642Sps		if (align_start) {
1770157642Sps			memcpy(buf, start, 4);
1771157642Sps		}
1772157642Sps		if (align_end) {
1773157642Sps			memcpy(buf + len32 - 4, end, 4);
1774157642Sps		}
1775157642Sps		memcpy(buf + align_start, data_buf, buf_size);
1776157642Sps	}
1777157642Sps
1778157642Sps	written = 0;
1779157642Sps	while ((written < len32) && (rc == 0)) {
1780157642Sps		u32 page_start, page_end, data_start, data_end;
1781157642Sps		u32 addr, cmd_flags;
1782157642Sps		int i;
1783157642Sps		u8 flash_buffer[264];
1784157642Sps
1785157642Sps	    /* Find the page_start addr */
1786157642Sps		page_start = offset32 + written;
1787157642Sps		page_start -= (page_start % sc->bce_flash_info->page_size);
1788157642Sps		/* Find the page_end addr */
1789157642Sps		page_end = page_start + sc->bce_flash_info->page_size;
1790157642Sps		/* Find the data_start addr */
1791157642Sps		data_start = (written == 0) ? offset32 : page_start;
1792157642Sps		/* Find the data_end addr */
1793157642Sps		data_end = (page_end > offset32 + len32) ?
1794157642Sps			(offset32 + len32) : page_end;
1795157642Sps
1796157642Sps		/* Request access to the flash interface. */
1797157642Sps		if ((rc = bce_acquire_nvram_lock(sc)) != 0)
1798157642Sps			goto nvram_write_end;
1799157642Sps
1800157642Sps		/* Enable access to flash interface */
1801157642Sps		bce_enable_nvram_access(sc);
1802157642Sps
1803157642Sps		cmd_flags = BCE_NVM_COMMAND_FIRST;
1804157642Sps		if (sc->bce_flash_info->buffered == 0) {
1805157642Sps			int j;
1806157642Sps
1807157642Sps			/* Read the whole page into the buffer
1808157642Sps			 * (non-buffer flash only) */
1809157642Sps			for (j = 0; j < sc->bce_flash_info->page_size; j += 4) {
1810157642Sps				if (j == (sc->bce_flash_info->page_size - 4)) {
1811157642Sps					cmd_flags |= BCE_NVM_COMMAND_LAST;
1812157642Sps				}
1813157642Sps				rc = bce_nvram_read_dword(sc,
1814157642Sps					page_start + j,
1815157642Sps					&flash_buffer[j],
1816157642Sps					cmd_flags);
1817157642Sps
1818157642Sps				if (rc)
1819157642Sps					goto nvram_write_end;
1820157642Sps
1821157642Sps				cmd_flags = 0;
1822157642Sps			}
1823157642Sps		}
1824157642Sps
1825157642Sps		/* Enable writes to flash interface (unlock write-protect) */
1826157642Sps		if ((rc = bce_enable_nvram_write(sc)) != 0)
1827157642Sps			goto nvram_write_end;
1828157642Sps
1829157642Sps		/* Erase the page */
1830157642Sps		if ((rc = bce_nvram_erase_page(sc, page_start)) != 0)
1831157642Sps			goto nvram_write_end;
1832157642Sps
1833157642Sps		/* Re-enable the write again for the actual write */
1834157642Sps		bce_enable_nvram_write(sc);
1835157642Sps
1836157642Sps		/* Loop to write back the buffer data from page_start to
1837157642Sps		 * data_start */
1838157642Sps		i = 0;
1839157642Sps		if (sc->bce_flash_info->buffered == 0) {
1840157642Sps			for (addr = page_start; addr < data_start;
1841157642Sps				addr += 4, i += 4) {
1842157642Sps
1843157642Sps				rc = bce_nvram_write_dword(sc, addr,
1844157642Sps					&flash_buffer[i], cmd_flags);
1845157642Sps
1846157642Sps				if (rc != 0)
1847157642Sps					goto nvram_write_end;
1848157642Sps
1849157642Sps				cmd_flags = 0;
1850157642Sps			}
1851157642Sps		}
1852157642Sps
1853157642Sps		/* Loop to write the new data from data_start to data_end */
1854157642Sps		for (addr = data_start; addr < data_end; addr += 4, i++) {
1855157642Sps			if ((addr == page_end - 4) ||
1856157642Sps				((sc->bce_flash_info->buffered) &&
1857157642Sps				 (addr == data_end - 4))) {
1858157642Sps
1859157642Sps				cmd_flags |= BCE_NVM_COMMAND_LAST;
1860157642Sps			}
1861157642Sps			rc = bce_nvram_write_dword(sc, addr, buf,
1862157642Sps				cmd_flags);
1863157642Sps
1864157642Sps			if (rc != 0)
1865157642Sps				goto nvram_write_end;
1866157642Sps
1867157642Sps			cmd_flags = 0;
1868157642Sps			buf += 4;
1869157642Sps		}
1870157642Sps
1871157642Sps		/* Loop to write back the buffer data from data_end
1872157642Sps		 * to page_end */
1873157642Sps		if (sc->bce_flash_info->buffered == 0) {
1874157642Sps			for (addr = data_end; addr < page_end;
1875157642Sps				addr += 4, i += 4) {
1876157642Sps
1877157642Sps				if (addr == page_end-4) {
1878157642Sps					cmd_flags = BCE_NVM_COMMAND_LAST;
1879157642Sps                		}
1880157642Sps				rc = bce_nvram_write_dword(sc, addr,
1881157642Sps					&flash_buffer[i], cmd_flags);
1882157642Sps
1883157642Sps				if (rc != 0)
1884157642Sps					goto nvram_write_end;
1885157642Sps
1886157642Sps				cmd_flags = 0;
1887157642Sps			}
1888157642Sps		}
1889157642Sps
1890157642Sps		/* Disable writes to flash interface (lock write-protect) */
1891157642Sps		bce_disable_nvram_write(sc);
1892157642Sps
1893157642Sps		/* Disable access to flash interface */
1894157642Sps		bce_disable_nvram_access(sc);
1895157642Sps		bce_release_nvram_lock(sc);
1896157642Sps
1897157642Sps		/* Increment written */
1898157642Sps		written += data_end - data_start;
1899157642Sps	}
1900157642Sps
1901157642Spsnvram_write_end:
1902157642Sps	if (align_start || align_end)
1903157642Sps		free(buf, M_DEVBUF);
1904157642Sps
1905157642Sps	return rc;
1906157642Sps}
1907157642Sps#endif /* BCE_NVRAM_WRITE_SUPPORT */
1908157642Sps
1909157642Sps
1910157642Sps/****************************************************************************/
1911157642Sps/* Verifies that NVRAM is accessible and contains valid data.               */
1912157642Sps/*                                                                          */
1913157642Sps/* Reads the configuration data from NVRAM and verifies that the CRC is     */
1914157642Sps/* correct.                                                                 */
1915157642Sps/*                                                                          */
1916157642Sps/* Returns:                                                                 */
1917157642Sps/*   0 on success, positive value on failure.                               */
1918157642Sps/****************************************************************************/
1919157642Spsstatic int
1920157642Spsbce_nvram_test(struct bce_softc *sc)
1921157642Sps{
1922157642Sps	u32 buf[BCE_NVRAM_SIZE / 4];
1923157642Sps	u8 *data = (u8 *) buf;
1924157642Sps	int rc = 0;
1925157642Sps	u32 magic, csum;
1926157642Sps
1927157642Sps
1928157642Sps	/*
1929157642Sps	 * Check that the device NVRAM is valid by reading
1930157642Sps	 * the magic value at offset 0.
1931157642Sps	 */
1932157642Sps	if ((rc = bce_nvram_read(sc, 0, data, 4)) != 0)
1933157642Sps		goto bce_nvram_test_done;
1934157642Sps
1935157642Sps
1936157642Sps    magic = bce_be32toh(buf[0]);
1937157642Sps	if (magic != BCE_NVRAM_MAGIC) {
1938157642Sps		rc = ENODEV;
1939157642Sps		BCE_PRINTF(sc, "%s(%d): Invalid NVRAM magic value! Expected: 0x%08X, "
1940157642Sps			"Found: 0x%08X\n",
1941157642Sps			__FILE__, __LINE__, BCE_NVRAM_MAGIC, magic);
1942157642Sps		goto bce_nvram_test_done;
1943157642Sps	}
1944157642Sps
1945157642Sps	/*
1946157642Sps	 * Verify that the device NVRAM includes valid
1947157642Sps	 * configuration data.
1948157642Sps	 */
1949157642Sps	if ((rc = bce_nvram_read(sc, 0x100, data, BCE_NVRAM_SIZE)) != 0)
1950157642Sps		goto bce_nvram_test_done;
1951157642Sps
1952157642Sps	csum = ether_crc32_le(data, 0x100);
1953157642Sps	if (csum != BCE_CRC32_RESIDUAL) {
1954157642Sps		rc = ENODEV;
1955157642Sps		BCE_PRINTF(sc, "%s(%d): Invalid Manufacturing Information NVRAM CRC! "
1956157642Sps			"Expected: 0x%08X, Found: 0x%08X\n",
1957157642Sps			__FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum);
1958157642Sps		goto bce_nvram_test_done;
1959157642Sps	}
1960157642Sps
1961157642Sps	csum = ether_crc32_le(data + 0x100, 0x100);
1962157642Sps	if (csum != BCE_CRC32_RESIDUAL) {
1963157642Sps		BCE_PRINTF(sc, "%s(%d): Invalid Feature Configuration Information "
1964157642Sps			"NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n",
1965157642Sps			__FILE__, __LINE__, BCE_CRC32_RESIDUAL, csum);
1966157642Sps		rc = ENODEV;
1967157642Sps	}
1968157642Sps
1969157642Spsbce_nvram_test_done:
1970157642Sps	return rc;
1971157642Sps}
1972157642Sps
1973157642Sps
1974157642Sps/****************************************************************************/
1975157642Sps/* Free any DMA memory owned by the driver.                                 */
1976157642Sps/*                                                                          */
1977157642Sps/* Scans through each data structre that requires DMA memory and frees      */
1978157642Sps/* the memory if allocated.                                                 */
1979157642Sps/*                                                                          */
1980157642Sps/* Returns:                                                                 */
1981157642Sps/*   Nothing.                                                               */
1982157642Sps/****************************************************************************/
1983157642Spsstatic void
1984157642Spsbce_dma_free(struct bce_softc *sc)
1985157642Sps{
1986157642Sps	int i;
1987157642Sps
1988157642Sps	DBPRINT(sc,BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
1989157642Sps
1990157642Sps	/* Destroy the status block. */
1991157642Sps	if (sc->status_block != NULL)
1992157642Sps		bus_dmamem_free(
1993157642Sps			sc->status_tag,
1994157642Sps		    sc->status_block,
1995157642Sps		    sc->status_map);
1996157642Sps
1997157642Sps	if (sc->status_map != NULL) {
1998157642Sps		bus_dmamap_unload(
1999157642Sps			sc->status_tag,
2000157642Sps		    sc->status_map);
2001157642Sps		bus_dmamap_destroy(sc->status_tag,
2002157642Sps		    sc->status_map);
2003157642Sps	}
2004157642Sps
2005157642Sps	if (sc->status_tag != NULL)
2006157642Sps		bus_dma_tag_destroy(sc->status_tag);
2007157642Sps
2008157642Sps
2009157642Sps	/* Destroy the statistics block. */
2010157642Sps	if (sc->stats_block != NULL)
2011157642Sps		bus_dmamem_free(
2012157642Sps			sc->stats_tag,
2013157642Sps		    sc->stats_block,
2014157642Sps		    sc->stats_map);
2015157642Sps
2016157642Sps	if (sc->stats_map != NULL) {
2017157642Sps		bus_dmamap_unload(
2018157642Sps			sc->stats_tag,
2019157642Sps		    sc->stats_map);
2020157642Sps		bus_dmamap_destroy(sc->stats_tag,
2021157642Sps		    sc->stats_map);
2022157642Sps	}
2023157642Sps
2024157642Sps	if (sc->stats_tag != NULL)
2025157642Sps		bus_dma_tag_destroy(sc->stats_tag);
2026157642Sps
2027157642Sps
2028157642Sps	/* Free, unmap and destroy all TX buffer descriptor chain pages. */
2029157642Sps	for (i = 0; i < TX_PAGES; i++ ) {
2030157642Sps		if (sc->tx_bd_chain[i] != NULL)
2031157642Sps			bus_dmamem_free(
2032157642Sps				sc->tx_bd_chain_tag,
2033157642Sps			    sc->tx_bd_chain[i],
2034157642Sps			    sc->tx_bd_chain_map[i]);
2035157642Sps
2036157642Sps		if (sc->tx_bd_chain_map[i] != NULL) {
2037157642Sps			bus_dmamap_unload(
2038157642Sps				sc->tx_bd_chain_tag,
2039157642Sps		    	sc->tx_bd_chain_map[i]);
2040157642Sps			bus_dmamap_destroy(
2041157642Sps				sc->tx_bd_chain_tag,
2042157642Sps			    sc->tx_bd_chain_map[i]);
2043157642Sps		}
2044157642Sps
2045157642Sps	}
2046157642Sps
2047157642Sps	/* Destroy the TX buffer descriptor tag. */
2048157642Sps	if (sc->tx_bd_chain_tag != NULL)
2049157642Sps		bus_dma_tag_destroy(sc->tx_bd_chain_tag);
2050157642Sps
2051157642Sps
2052157642Sps	/* Free, unmap and destroy all RX buffer descriptor chain pages. */
2053157642Sps	for (i = 0; i < RX_PAGES; i++ ) {
2054157642Sps		if (sc->rx_bd_chain[i] != NULL)
2055157642Sps			bus_dmamem_free(
2056157642Sps				sc->rx_bd_chain_tag,
2057157642Sps			    sc->rx_bd_chain[i],
2058157642Sps			    sc->rx_bd_chain_map[i]);
2059157642Sps
2060157642Sps		if (sc->rx_bd_chain_map[i] != NULL) {
2061157642Sps			bus_dmamap_unload(
2062157642Sps				sc->rx_bd_chain_tag,
2063157642Sps		    	sc->rx_bd_chain_map[i]);
2064157642Sps			bus_dmamap_destroy(
2065157642Sps				sc->rx_bd_chain_tag,
2066157642Sps			    sc->rx_bd_chain_map[i]);
2067157642Sps		}
2068157642Sps	}
2069157642Sps
2070157642Sps	/* Destroy the RX buffer descriptor tag. */
2071157642Sps	if (sc->rx_bd_chain_tag != NULL)
2072157642Sps		bus_dma_tag_destroy(sc->rx_bd_chain_tag);
2073157642Sps
2074157642Sps
2075157642Sps	/* Unload and destroy the TX mbuf maps. */
2076157642Sps	for (i = 0; i < TOTAL_TX_BD; i++) {
2077157642Sps		if (sc->tx_mbuf_map[i] != NULL) {
2078157642Sps			bus_dmamap_unload(sc->tx_mbuf_tag,
2079157642Sps				sc->tx_mbuf_map[i]);
2080157642Sps			bus_dmamap_destroy(sc->tx_mbuf_tag,
2081157642Sps	 			sc->tx_mbuf_map[i]);
2082157642Sps		}
2083157642Sps	}
2084157642Sps
2085157642Sps	/* Destroy the TX mbuf tag. */
2086157642Sps	if (sc->tx_mbuf_tag != NULL)
2087157642Sps		bus_dma_tag_destroy(sc->tx_mbuf_tag);
2088157642Sps
2089157642Sps
2090157642Sps	/* Unload and destroy the RX mbuf maps. */
2091157642Sps	for (i = 0; i < TOTAL_RX_BD; i++) {
2092157642Sps		if (sc->rx_mbuf_map[i] != NULL) {
2093157642Sps			bus_dmamap_unload(sc->rx_mbuf_tag,
2094157642Sps				sc->rx_mbuf_map[i]);
2095157642Sps			bus_dmamap_destroy(sc->rx_mbuf_tag,
2096157642Sps	 			sc->rx_mbuf_map[i]);
2097157642Sps		}
2098157642Sps	}
2099157642Sps
2100157642Sps	/* Destroy the RX mbuf tag. */
2101157642Sps	if (sc->rx_mbuf_tag != NULL)
2102157642Sps		bus_dma_tag_destroy(sc->rx_mbuf_tag);
2103157642Sps
2104157642Sps
2105157642Sps	/* Destroy the parent tag */
2106157642Sps	if (sc->parent_tag != NULL)
2107157642Sps		bus_dma_tag_destroy(sc->parent_tag);
2108157642Sps
2109157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
2110157642Sps
2111157642Sps}
2112157642Sps
2113157642Sps
2114157642Sps/****************************************************************************/
2115157642Sps/* Get DMA memory from the OS.                                              */
2116157642Sps/*                                                                          */
2117157642Sps/* Validates that the OS has provided DMA buffers in response to a          */
2118157642Sps/* bus_dmamap_load() call and saves the physical address of those buffers.  */
2119157642Sps/* When the callback is used the OS will return 0 for the mapping function  */
2120157642Sps/* (bus_dmamap_load()) so we use the value of map_arg->maxsegs to pass any  */
2121157642Sps/* failures back to the caller.                                             */
2122157642Sps/*                                                                          */
2123157642Sps/* Returns:                                                                 */
2124157642Sps/*   Nothing.                                                               */
2125157642Sps/****************************************************************************/
2126157642Spsstatic void
2127157642Spsbce_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error)
2128157642Sps{
2129157642Sps	struct bce_dmamap_arg *map_arg = arg;
2130157642Sps	struct bce_softc *sc = map_arg->sc;
2131157642Sps
2132157642Sps	/* Simulate a mapping failure. */
2133157642Sps	DBRUNIF(DB_RANDOMTRUE(bce_debug_dma_map_addr_failure),
2134157642Sps		BCE_PRINTF(sc, "%s(%d): Simulating DMA mapping error.\n",
2135157642Sps			__FILE__, __LINE__);
2136157642Sps		error = ENOMEM);
2137157642Sps
2138157642Sps	/* Check for an error and signal the caller that an error occurred. */
2139157642Sps	if (error || (nseg > map_arg->maxsegs)) {
2140157642Sps		BCE_PRINTF(sc, "%s(%d): DMA mapping error! error = %d, "
2141157642Sps		"nseg = %d, maxsegs = %d\n",
2142157642Sps			__FILE__, __LINE__, error, nseg, map_arg->maxsegs);
2143157642Sps		map_arg->maxsegs = 0;
2144157642Sps		goto bce_dma_map_addr_exit;
2145157642Sps	}
2146157642Sps
2147157642Sps	map_arg->busaddr = segs->ds_addr;
2148157642Sps
2149157642Spsbce_dma_map_addr_exit:
2150157642Sps	return;
2151157642Sps}
2152157642Sps
2153157642Sps
2154157642Sps/****************************************************************************/
2155157642Sps/* Map TX buffers into TX buffer descriptors.                               */
2156157642Sps/*                                                                          */
2157157642Sps/* Given a series of DMA memory containting an outgoing frame, map the      */
2158157642Sps/* segments into the tx_bd structure used by the hardware.                  */
2159157642Sps/*                                                                          */
2160157642Sps/* Returns:                                                                 */
2161157642Sps/*   Nothing.                                                               */
2162157642Sps/****************************************************************************/
2163157642Spsstatic void
2164157642Spsbce_dma_map_tx_desc(void *arg, bus_dma_segment_t *segs,
2165157642Sps	int nseg, bus_size_t mapsize, int error)
2166157642Sps{
2167157642Sps	struct bce_dmamap_arg *map_arg;
2168157642Sps	struct bce_softc *sc;
2169157642Sps	struct tx_bd *txbd = NULL;
2170157642Sps	int i = 0;
2171157642Sps	u16 prod, chain_prod;
2172157642Sps	u32	prod_bseq;
2173157642Sps#ifdef BCE_DEBUG
2174157642Sps	u16 debug_prod;
2175157642Sps#endif
2176157642Sps
2177157642Sps	map_arg = arg;
2178157642Sps	sc = map_arg->sc;
2179157642Sps
2180157642Sps	if (error) {
2181157642Sps		DBPRINT(sc, BCE_WARN, "%s(): Called with error = %d\n",
2182157642Sps			__FUNCTION__, error);
2183157642Sps		return;
2184157642Sps	}
2185157642Sps
2186157642Sps	/* Signal error to caller if there's too many segments */
2187157642Sps	if (nseg > map_arg->maxsegs) {
2188157642Sps		DBPRINT(sc, BCE_WARN,
2189157642Sps			"%s(): Mapped TX descriptors: max segs = %d, "
2190157642Sps			"actual segs = %d\n",
2191157642Sps			__FUNCTION__, map_arg->maxsegs, nseg);
2192157642Sps
2193157642Sps		map_arg->maxsegs = 0;
2194157642Sps		return;
2195157642Sps	}
2196157642Sps
2197157642Sps	/* prod points to an empty tx_bd at this point. */
2198157642Sps	prod       = map_arg->prod;
2199157642Sps	chain_prod = map_arg->chain_prod;
2200157642Sps	prod_bseq  = map_arg->prod_bseq;
2201157642Sps
2202157642Sps#ifdef BCE_DEBUG
2203157642Sps	debug_prod = chain_prod;
2204157642Sps#endif
2205157642Sps
2206157642Sps	DBPRINT(sc, BCE_INFO_SEND,
2207157642Sps		"%s(): Start: prod = 0x%04X, chain_prod = %04X, "
2208157642Sps		"prod_bseq = 0x%08X\n",
2209157642Sps		__FUNCTION__, prod, chain_prod, prod_bseq);
2210157642Sps
2211157642Sps	/*
2212157642Sps	 * Cycle through each mbuf segment that makes up
2213157642Sps	 * the outgoing frame, gathering the mapping info
2214157642Sps	 * for that segment and creating a tx_bd to for
2215157642Sps	 * the mbuf.
2216157642Sps	 */
2217157642Sps
2218157642Sps	txbd = &map_arg->tx_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
2219157642Sps
2220157642Sps	/* Setup the first tx_bd for the first segment. */
2221157642Sps	txbd->tx_bd_haddr_lo       = htole32(BCE_ADDR_LO(segs[i].ds_addr));
2222157642Sps	txbd->tx_bd_haddr_hi       = htole32(BCE_ADDR_HI(segs[i].ds_addr));
2223157642Sps	txbd->tx_bd_mss_nbytes     = htole16(segs[i].ds_len);
2224157642Sps	txbd->tx_bd_vlan_tag_flags = htole16(map_arg->tx_flags |
2225157642Sps			TX_BD_FLAGS_START);
2226157642Sps	prod_bseq += segs[i].ds_len;
2227157642Sps
2228157642Sps	/* Setup any remaing segments. */
2229157642Sps	for (i = 1; i < nseg; i++) {
2230157642Sps		prod       = NEXT_TX_BD(prod);
2231157642Sps		chain_prod = TX_CHAIN_IDX(prod);
2232157642Sps
2233157642Sps		txbd = &map_arg->tx_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
2234157642Sps
2235157642Sps		txbd->tx_bd_haddr_lo       = htole32(BCE_ADDR_LO(segs[i].ds_addr));
2236157642Sps		txbd->tx_bd_haddr_hi       = htole32(BCE_ADDR_HI(segs[i].ds_addr));
2237157642Sps		txbd->tx_bd_mss_nbytes     = htole16(segs[i].ds_len);
2238157642Sps		txbd->tx_bd_vlan_tag_flags = htole16(map_arg->tx_flags);
2239157642Sps
2240157642Sps		prod_bseq += segs[i].ds_len;
2241157642Sps	}
2242157642Sps
2243157642Sps	/* Set the END flag on the last TX buffer descriptor. */
2244157642Sps	txbd->tx_bd_vlan_tag_flags |= htole16(TX_BD_FLAGS_END);
2245157642Sps
2246157642Sps	DBRUN(BCE_INFO_SEND, bce_dump_tx_chain(sc, debug_prod, nseg));
2247157642Sps
2248157642Sps	DBPRINT(sc, BCE_INFO_SEND,
2249157642Sps		"%s(): End: prod = 0x%04X, chain_prod = %04X, "
2250157642Sps		"prod_bseq = 0x%08X\n",
2251157642Sps		__FUNCTION__, prod, chain_prod, prod_bseq);
2252157642Sps
2253157642Sps	/* prod points to the last tx_bd at this point. */
2254157642Sps	map_arg->maxsegs    = nseg;
2255157642Sps	map_arg->prod       = prod;
2256157642Sps	map_arg->chain_prod = chain_prod;
2257157642Sps	map_arg->prod_bseq  = prod_bseq;
2258157642Sps}
2259157642Sps
2260157642Sps
2261157642Sps/****************************************************************************/
2262157642Sps/* Allocate any DMA memory needed by the driver.                            */
2263157642Sps/*                                                                          */
2264157642Sps/* Allocates DMA memory needed for the various global structures needed by  */
2265157642Sps/* hardware.                                                                */
2266157642Sps/*                                                                          */
2267157642Sps/* Returns:                                                                 */
2268157642Sps/*   0 for success, positive value for failure.                             */
2269157642Sps/****************************************************************************/
2270157642Spsstatic int
2271157642Spsbce_dma_alloc(device_t dev)
2272157642Sps{
2273157642Sps	struct bce_softc *sc;
2274157642Sps	int i, error, rc = 0;
2275157642Sps	struct bce_dmamap_arg map_arg;
2276157642Sps
2277157642Sps	sc = device_get_softc(dev);
2278157642Sps
2279157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
2280157642Sps
2281157642Sps	/*
2282157642Sps	 * Allocate the parent bus DMA tag appropriate for PCI.
2283157642Sps	 */
2284157642Sps	if (bus_dma_tag_create(NULL,		/* parent     */
2285157642Sps			BCE_DMA_ALIGN,				/* alignment  */
2286157642Sps			BCE_DMA_BOUNDARY,			/* boundary   */
2287157642Sps			sc->max_bus_addr,			/* lowaddr    */
2288157642Sps			BUS_SPACE_MAXADDR,			/* highaddr   */
2289157642Sps			NULL, 						/* filterfunc */
2290157642Sps			NULL,						/* filterarg  */
2291157642Sps			MAXBSIZE, 					/* maxsize    */
2292157642Sps			BUS_SPACE_UNRESTRICTED,		/* nsegments  */
2293157642Sps			BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
2294157642Sps			0,							/* flags      */
2295157642Sps			NULL, 						/* locfunc    */
2296157642Sps			NULL,						/* lockarg    */
2297157642Sps			&sc->parent_tag)) {
2298157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate parent DMA tag!\n",
2299157642Sps			__FILE__, __LINE__);
2300157642Sps		rc = ENOMEM;
2301157642Sps		goto bce_dma_alloc_exit;
2302157642Sps	}
2303157642Sps
2304157642Sps	/*
2305157642Sps	 * Create a DMA tag for the status block, allocate and clear the
2306157642Sps	 * memory, map the memory into DMA space, and fetch the physical
2307157642Sps	 * address of the block.
2308157642Sps	 */
2309157642Sps	if (bus_dma_tag_create(
2310157642Sps			sc->parent_tag,			/* parent      */
2311157642Sps	    	BCE_DMA_ALIGN,			/* alignment   */
2312157642Sps	    	BCE_DMA_BOUNDARY,		/* boundary    */
2313157642Sps	    	sc->max_bus_addr,		/* lowaddr     */
2314157642Sps	    	BUS_SPACE_MAXADDR,		/* highaddr    */
2315157642Sps	    	NULL, 					/* filterfunc  */
2316157642Sps	    	NULL, 					/* filterarg   */
2317157642Sps	    	BCE_STATUS_BLK_SZ, 		/* maxsize     */
2318157642Sps	    	1,						/* nsegments   */
2319157642Sps	    	BCE_STATUS_BLK_SZ, 		/* maxsegsize  */
2320157642Sps	    	0,						/* flags       */
2321157642Sps	    	NULL, 					/* lockfunc    */
2322157642Sps	    	NULL,					/* lockarg     */
2323157642Sps	    	&sc->status_tag)) {
2324157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate status block DMA tag!\n",
2325157642Sps			__FILE__, __LINE__);
2326157642Sps		rc = ENOMEM;
2327157642Sps		goto bce_dma_alloc_exit;
2328157642Sps	}
2329157642Sps
2330157642Sps	if(bus_dmamem_alloc(
2331157642Sps			sc->status_tag,				/* dmat        */
2332157642Sps	    	(void **)&sc->status_block,	/* vaddr       */
2333157642Sps	    	BUS_DMA_NOWAIT,					/* flags       */
2334157642Sps	    	&sc->status_map)) {
2335157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate status block DMA memory!\n",
2336157642Sps			__FILE__, __LINE__);
2337157642Sps		rc = ENOMEM;
2338157642Sps		goto bce_dma_alloc_exit;
2339157642Sps	}
2340157642Sps
2341157642Sps	bzero((char *)sc->status_block, BCE_STATUS_BLK_SZ);
2342157642Sps
2343157642Sps	map_arg.sc = sc;
2344157642Sps	map_arg.maxsegs = 1;
2345157642Sps
2346157642Sps	error = bus_dmamap_load(
2347157642Sps			sc->status_tag,	   		/* dmat        */
2348157642Sps	    	sc->status_map,	   		/* map         */
2349157642Sps	    	sc->status_block,	 	/* buf         */
2350157642Sps	    	BCE_STATUS_BLK_SZ,	 	/* buflen      */
2351157642Sps	    	bce_dma_map_addr, 	 	/* callback    */
2352157642Sps	    	&map_arg,			 	/* callbackarg */
2353157642Sps	    	BUS_DMA_NOWAIT);		/* flags       */
2354157642Sps
2355157642Sps	if(error || (map_arg.maxsegs == 0)) {
2356157642Sps		BCE_PRINTF(sc, "%s(%d): Could not map status block DMA memory!\n",
2357157642Sps			__FILE__, __LINE__);
2358157642Sps		rc = ENOMEM;
2359157642Sps		goto bce_dma_alloc_exit;
2360157642Sps	}
2361157642Sps
2362157642Sps	sc->status_block_paddr = map_arg.busaddr;
2363157642Sps	/* DRC - Fix for 64 bit addresses. */
2364157642Sps	DBPRINT(sc, BCE_INFO, "status_block_paddr = 0x%08X\n",
2365157642Sps		(u32) sc->status_block_paddr);
2366157642Sps
2367157642Sps	/*
2368157642Sps	 * Create a DMA tag for the statistics block, allocate and clear the
2369157642Sps	 * memory, map the memory into DMA space, and fetch the physical
2370157642Sps	 * address of the block.
2371157642Sps	 */
2372157642Sps	if (bus_dma_tag_create(
2373157642Sps			sc->parent_tag,			/* parent      */
2374157642Sps	    	BCE_DMA_ALIGN,	 		/* alignment   */
2375157642Sps	    	BCE_DMA_BOUNDARY, 		/* boundary    */
2376157642Sps	    	sc->max_bus_addr,		/* lowaddr     */
2377157642Sps	    	BUS_SPACE_MAXADDR,		/* highaddr    */
2378157642Sps	    	NULL,		 	  		/* filterfunc  */
2379157642Sps	    	NULL, 			  		/* filterarg   */
2380157642Sps	    	BCE_STATS_BLK_SZ, 		/* maxsize     */
2381157642Sps	    	1,				  		/* nsegments   */
2382157642Sps	    	BCE_STATS_BLK_SZ, 		/* maxsegsize  */
2383157642Sps	    	0, 				  		/* flags       */
2384157642Sps	    	NULL, 			  		/* lockfunc    */
2385157642Sps	    	NULL, 			  		/* lockarg     */
2386157642Sps	    	&sc->stats_tag)) {
2387157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate statistics block DMA tag!\n",
2388157642Sps			__FILE__, __LINE__);
2389157642Sps		rc = ENOMEM;
2390157642Sps		goto bce_dma_alloc_exit;
2391157642Sps	}
2392157642Sps
2393157642Sps	if (bus_dmamem_alloc(
2394157642Sps			sc->stats_tag,				/* dmat        */
2395157642Sps	    	(void **)&sc->stats_block,	/* vaddr       */
2396157642Sps	    	BUS_DMA_NOWAIT,	 			/* flags       */
2397157642Sps	    	&sc->stats_map)) {
2398157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate statistics block DMA memory!\n",
2399157642Sps			__FILE__, __LINE__);
2400157642Sps		rc = ENOMEM;
2401157642Sps		goto bce_dma_alloc_exit;
2402157642Sps	}
2403157642Sps
2404157642Sps	bzero((char *)sc->stats_block, BCE_STATS_BLK_SZ);
2405157642Sps
2406157642Sps	map_arg.sc = sc;
2407157642Sps	map_arg.maxsegs = 1;
2408157642Sps
2409157642Sps	error = bus_dmamap_load(
2410157642Sps			sc->stats_tag,	 	/* dmat        */
2411157642Sps	    	sc->stats_map,	 	/* map         */
2412157642Sps	    	sc->stats_block, 	/* buf         */
2413157642Sps	    	BCE_STATS_BLK_SZ,	/* buflen      */
2414157642Sps	    	bce_dma_map_addr,	/* callback    */
2415157642Sps	    	&map_arg, 		 	/* callbackarg */
2416157642Sps	    	BUS_DMA_NOWAIT);	/* flags       */
2417157642Sps
2418157642Sps	if(error || (map_arg.maxsegs == 0)) {
2419157642Sps		BCE_PRINTF(sc, "%s(%d): Could not map statistics block DMA memory!\n",
2420157642Sps			__FILE__, __LINE__);
2421157642Sps		rc = ENOMEM;
2422157642Sps		goto bce_dma_alloc_exit;
2423157642Sps	}
2424157642Sps
2425157642Sps	sc->stats_block_paddr = map_arg.busaddr;
2426157642Sps	/* DRC - Fix for 64 bit address. */
2427157642Sps	DBPRINT(sc,BCE_INFO, "stats_block_paddr = 0x%08X\n",
2428157642Sps		(u32) sc->stats_block_paddr);
2429157642Sps
2430157642Sps	/*
2431157642Sps	 * Create a DMA tag for the TX buffer descriptor chain,
2432157642Sps	 * allocate and clear the  memory, and fetch the
2433157642Sps	 * physical address of the block.
2434157642Sps	 */
2435157642Sps	if(bus_dma_tag_create(
2436157642Sps			sc->parent_tag,		  /* parent      */
2437157642Sps	    	BCM_PAGE_SIZE,		  /* alignment   */
2438157642Sps	    	BCE_DMA_BOUNDARY,	  /* boundary    */
2439157642Sps			sc->max_bus_addr,	  /* lowaddr     */
2440157642Sps			BUS_SPACE_MAXADDR, 	  /* highaddr    */
2441157642Sps			NULL, 				  /* filterfunc  */
2442157642Sps			NULL, 				  /* filterarg   */
2443157642Sps			BCE_TX_CHAIN_PAGE_SZ, /* maxsize     */
2444157642Sps			1,			  		  /* nsegments   */
2445157642Sps			BCE_TX_CHAIN_PAGE_SZ, /* maxsegsize  */
2446157642Sps			0,				 	  /* flags       */
2447157642Sps			NULL, 				  /* lockfunc    */
2448157642Sps			NULL,				  /* lockarg     */
2449157642Sps			&sc->tx_bd_chain_tag)) {
2450157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate TX descriptor chain DMA tag!\n",
2451157642Sps			__FILE__, __LINE__);
2452157642Sps		rc = ENOMEM;
2453157642Sps		goto bce_dma_alloc_exit;
2454157642Sps	}
2455157642Sps
2456157642Sps	for (i = 0; i < TX_PAGES; i++) {
2457157642Sps
2458157642Sps		if(bus_dmamem_alloc(
2459157642Sps				sc->tx_bd_chain_tag,			/* tag   */
2460157642Sps	    		(void **)&sc->tx_bd_chain[i],	/* vaddr */
2461157642Sps	    		BUS_DMA_NOWAIT,					/* flags */
2462157642Sps		    	&sc->tx_bd_chain_map[i])) {
2463157642Sps			BCE_PRINTF(sc, "%s(%d): Could not allocate TX descriptor "
2464157642Sps				"chain DMA memory!\n", __FILE__, __LINE__);
2465157642Sps			rc = ENOMEM;
2466157642Sps			goto bce_dma_alloc_exit;
2467157642Sps		}
2468157642Sps
2469157642Sps		map_arg.maxsegs = 1;
2470157642Sps		map_arg.sc = sc;
2471157642Sps
2472157642Sps		error = bus_dmamap_load(
2473157642Sps				sc->tx_bd_chain_tag,	 /* dmat        */
2474157642Sps	    		sc->tx_bd_chain_map[i],	 /* map         */
2475157642Sps	    		sc->tx_bd_chain[i],		 /* buf         */
2476157642Sps		    	BCE_TX_CHAIN_PAGE_SZ,  	 /* buflen      */
2477157642Sps		    	bce_dma_map_addr, 	   	 /* callback    */
2478157642Sps	    		&map_arg, 			   	 /* callbackarg */
2479157642Sps	    		BUS_DMA_NOWAIT);	   	 /* flags       */
2480157642Sps
2481157642Sps		if(error || (map_arg.maxsegs == 0)) {
2482157642Sps			BCE_PRINTF(sc, "%s(%d): Could not map TX descriptor chain DMA memory!\n",
2483157642Sps				__FILE__, __LINE__);
2484157642Sps			rc = ENOMEM;
2485157642Sps			goto bce_dma_alloc_exit;
2486157642Sps		}
2487157642Sps
2488157642Sps		sc->tx_bd_chain_paddr[i] = map_arg.busaddr;
2489157642Sps		/* DRC - Fix for 64 bit systems. */
2490157642Sps		DBPRINT(sc, BCE_INFO, "tx_bd_chain_paddr[%d] = 0x%08X\n",
2491157642Sps			i, (u32) sc->tx_bd_chain_paddr[i]);
2492157642Sps	}
2493157642Sps
2494157642Sps	/* Create a DMA tag for TX mbufs. */
2495157642Sps	if (bus_dma_tag_create(
2496157642Sps			sc->parent_tag,	 	 	/* parent      */
2497157642Sps	    	BCE_DMA_ALIGN,	 		/* alignment   */
2498157642Sps	    	BCE_DMA_BOUNDARY, 		/* boundary    */
2499157642Sps			sc->max_bus_addr,		/* lowaddr     */
2500157642Sps			BUS_SPACE_MAXADDR,		/* highaddr    */
2501157642Sps			NULL, 			  		/* filterfunc  */
2502157642Sps			NULL, 			  		/* filterarg   */
2503157642Sps			MCLBYTES * BCE_MAX_SEGMENTS,	/* maxsize     */
2504157642Sps			BCE_MAX_SEGMENTS,  		/* nsegments   */
2505157642Sps			MCLBYTES,				/* maxsegsize  */
2506157642Sps			0,				 		/* flags       */
2507157642Sps			NULL, 			  		/* lockfunc    */
2508157642Sps			NULL,			  		/* lockarg     */
2509157642Sps	    	&sc->tx_mbuf_tag)) {
2510157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate TX mbuf DMA tag!\n",
2511157642Sps			__FILE__, __LINE__);
2512157642Sps		rc = ENOMEM;
2513157642Sps		goto bce_dma_alloc_exit;
2514157642Sps	}
2515157642Sps
2516157642Sps	/* Create DMA maps for the TX mbufs clusters. */
2517157642Sps	for (i = 0; i < TOTAL_TX_BD; i++) {
2518157642Sps		if (bus_dmamap_create(sc->tx_mbuf_tag, BUS_DMA_NOWAIT,
2519157642Sps			&sc->tx_mbuf_map[i])) {
2520157642Sps			BCE_PRINTF(sc, "%s(%d): Unable to create TX mbuf DMA map!\n",
2521157642Sps				__FILE__, __LINE__);
2522157642Sps			rc = ENOMEM;
2523157642Sps			goto bce_dma_alloc_exit;
2524157642Sps		}
2525157642Sps	}
2526157642Sps
2527157642Sps	/*
2528157642Sps	 * Create a DMA tag for the RX buffer descriptor chain,
2529157642Sps	 * allocate and clear the  memory, and fetch the physical
2530157642Sps	 * address of the blocks.
2531157642Sps	 */
2532157642Sps	if (bus_dma_tag_create(
2533157642Sps			sc->parent_tag,			/* parent      */
2534157642Sps	    	BCM_PAGE_SIZE,			/* alignment   */
2535157642Sps	    	BCE_DMA_BOUNDARY,		/* boundary    */
2536157642Sps			BUS_SPACE_MAXADDR,		/* lowaddr     */
2537157642Sps			sc->max_bus_addr,		/* lowaddr     */
2538157642Sps			NULL,					/* filter      */
2539157642Sps			NULL, 					/* filterarg   */
2540157642Sps			BCE_RX_CHAIN_PAGE_SZ,	/* maxsize     */
2541157642Sps			1, 						/* nsegments   */
2542157642Sps			BCE_RX_CHAIN_PAGE_SZ,	/* maxsegsize  */
2543157642Sps			0,				 		/* flags       */
2544157642Sps			NULL,					/* lockfunc    */
2545157642Sps			NULL,					/* lockarg     */
2546157642Sps			&sc->rx_bd_chain_tag)) {
2547157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate RX descriptor chain DMA tag!\n",
2548157642Sps			__FILE__, __LINE__);
2549157642Sps		rc = ENOMEM;
2550157642Sps		goto bce_dma_alloc_exit;
2551157642Sps	}
2552157642Sps
2553157642Sps	for (i = 0; i < RX_PAGES; i++) {
2554157642Sps
2555157642Sps		if (bus_dmamem_alloc(
2556157642Sps				sc->rx_bd_chain_tag,			/* tag   */
2557157642Sps	    		(void **)&sc->rx_bd_chain[i], 	/* vaddr */
2558157642Sps	    		BUS_DMA_NOWAIT,				  	/* flags */
2559157642Sps		    	&sc->rx_bd_chain_map[i])) {
2560157642Sps			BCE_PRINTF(sc, "%s(%d): Could not allocate RX descriptor chain "
2561157642Sps				"DMA memory!\n", __FILE__, __LINE__);
2562157642Sps			rc = ENOMEM;
2563157642Sps			goto bce_dma_alloc_exit;
2564157642Sps		}
2565157642Sps
2566157642Sps		bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ);
2567157642Sps
2568157642Sps		map_arg.maxsegs = 1;
2569157642Sps		map_arg.sc = sc;
2570157642Sps
2571157642Sps		error = bus_dmamap_load(
2572157642Sps				sc->rx_bd_chain_tag,	/* dmat        */
2573157642Sps	    		sc->rx_bd_chain_map[i],	/* map         */
2574157642Sps	    		sc->rx_bd_chain[i],		/* buf         */
2575157642Sps		    	BCE_RX_CHAIN_PAGE_SZ,  	/* buflen      */
2576157642Sps		    	bce_dma_map_addr,	   	/* callback    */
2577157642Sps	    		&map_arg,			   	/* callbackarg */
2578157642Sps	    		BUS_DMA_NOWAIT);		/* flags       */
2579157642Sps
2580157642Sps		if(error || (map_arg.maxsegs == 0)) {
2581157642Sps			BCE_PRINTF(sc, "%s(%d): Could not map RX descriptor chain DMA memory!\n",
2582157642Sps				__FILE__, __LINE__);
2583157642Sps			rc = ENOMEM;
2584157642Sps			goto bce_dma_alloc_exit;
2585157642Sps		}
2586157642Sps
2587157642Sps		sc->rx_bd_chain_paddr[i] = map_arg.busaddr;
2588157642Sps		/* DRC - Fix for 64 bit systems. */
2589157642Sps		DBPRINT(sc, BCE_INFO, "rx_bd_chain_paddr[%d] = 0x%08X\n",
2590157642Sps			i, (u32) sc->rx_bd_chain_paddr[i]);
2591157642Sps	}
2592157642Sps
2593157642Sps	/*
2594157642Sps	 * Create a DMA tag for RX mbufs.
2595157642Sps	 */
2596157642Sps	if (bus_dma_tag_create(
2597157642Sps			sc->parent_tag,			/* parent      */
2598157642Sps	    	BCE_DMA_ALIGN,		  	/* alignment   */
2599157642Sps	    	BCE_DMA_BOUNDARY,	  	/* boundary    */
2600157642Sps			sc->max_bus_addr,	  	/* lowaddr     */
2601157642Sps			BUS_SPACE_MAXADDR, 	  	/* highaddr    */
2602157642Sps			NULL, 				  	/* filterfunc  */
2603157642Sps			NULL, 				  	/* filterarg   */
2604157642Sps			MJUM9BYTES,				/* maxsize     */
2605157642Sps			BCE_MAX_SEGMENTS,  		/* nsegments   */
2606157642Sps			MJUM9BYTES,				/* maxsegsize  */
2607157642Sps			0,				 	  	/* flags       */
2608157642Sps			NULL, 				  	/* lockfunc    */
2609157642Sps			NULL,				  	/* lockarg     */
2610157642Sps	    	&sc->rx_mbuf_tag)) {
2611157642Sps		BCE_PRINTF(sc, "%s(%d): Could not allocate RX mbuf DMA tag!\n",
2612157642Sps			__FILE__, __LINE__);
2613157642Sps		rc = ENOMEM;
2614157642Sps		goto bce_dma_alloc_exit;
2615157642Sps	}
2616157642Sps
2617157642Sps	/* Create DMA maps for the RX mbuf clusters. */
2618157642Sps	for (i = 0; i < TOTAL_RX_BD; i++) {
2619157642Sps		if (bus_dmamap_create(sc->rx_mbuf_tag, BUS_DMA_NOWAIT,
2620157642Sps				&sc->rx_mbuf_map[i])) {
2621157642Sps			BCE_PRINTF(sc, "%s(%d): Unable to create RX mbuf DMA map!\n",
2622157642Sps				__FILE__, __LINE__);
2623157642Sps			rc = ENOMEM;
2624157642Sps			goto bce_dma_alloc_exit;
2625157642Sps		}
2626157642Sps	}
2627157642Sps
2628157642Spsbce_dma_alloc_exit:
2629157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
2630157642Sps
2631157642Sps	return(rc);
2632157642Sps}
2633157642Sps
2634157642Sps
2635157642Sps/****************************************************************************/
2636157642Sps/* Release all resources used by the driver.                                */
2637157642Sps/*                                                                          */
2638157642Sps/* Releases all resources acquired by the driver including interrupts,      */
2639157642Sps/* interrupt handler, interfaces, mutexes, and DMA memory.                  */
2640157642Sps/*                                                                          */
2641157642Sps/* Returns:                                                                 */
2642157642Sps/*   Nothing.                                                               */
2643157642Sps/****************************************************************************/
2644157642Spsstatic void
2645157642Spsbce_release_resources(struct bce_softc *sc)
2646157642Sps{
2647157642Sps	device_t dev;
2648157642Sps
2649157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
2650157642Sps
2651157642Sps	dev = sc->bce_dev;
2652157642Sps
2653157642Sps	bce_dma_free(sc);
2654157642Sps
2655157642Sps	if (sc->bce_intrhand != NULL)
2656157642Sps		bus_teardown_intr(dev, sc->bce_irq, sc->bce_intrhand);
2657157642Sps
2658157642Sps	if (sc->bce_irq != NULL)
2659157642Sps		bus_release_resource(dev,
2660157642Sps			SYS_RES_IRQ,
2661157642Sps			0,
2662157642Sps			sc->bce_irq);
2663157642Sps
2664157642Sps	if (sc->bce_res != NULL)
2665157642Sps		bus_release_resource(dev,
2666157642Sps			SYS_RES_MEMORY,
2667157642Sps		    PCIR_BAR(0),
2668157642Sps		    sc->bce_res);
2669157642Sps
2670157642Sps	if (sc->bce_ifp != NULL)
2671157642Sps		if_free(sc->bce_ifp);
2672157642Sps
2673157642Sps
2674157642Sps	if (mtx_initialized(&sc->bce_mtx))
2675157642Sps		BCE_LOCK_DESTROY(sc);
2676157642Sps
2677157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
2678157642Sps
2679157642Sps}
2680157642Sps
2681157642Sps
2682157642Sps/****************************************************************************/
2683157642Sps/* Firmware synchronization.                                                */
2684157642Sps/*                                                                          */
2685157642Sps/* Before performing certain events such as a chip reset, synchronize with  */
2686157642Sps/* the firmware first.                                                      */
2687157642Sps/*                                                                          */
2688157642Sps/* Returns:                                                                 */
2689157642Sps/*   0 for success, positive value for failure.                             */
2690157642Sps/****************************************************************************/
2691157642Spsstatic int
2692157642Spsbce_fw_sync(struct bce_softc *sc, u32 msg_data)
2693157642Sps{
2694157642Sps	int i, rc = 0;
2695157642Sps	u32 val;
2696157642Sps
2697157642Sps	/* Don't waste any time if we've timed out before. */
2698157642Sps	if (sc->bce_fw_timed_out) {
2699157642Sps		rc = EBUSY;
2700157642Sps		goto bce_fw_sync_exit;
2701157642Sps	}
2702157642Sps
2703157642Sps	/* Increment the message sequence number. */
2704157642Sps	sc->bce_fw_wr_seq++;
2705157642Sps	msg_data |= sc->bce_fw_wr_seq;
2706157642Sps
2707157642Sps 	DBPRINT(sc, BCE_VERBOSE, "bce_fw_sync(): msg_data = 0x%08X\n", msg_data);
2708157642Sps
2709157642Sps	/* Send the message to the bootcode driver mailbox. */
2710157642Sps	REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_MB, msg_data);
2711157642Sps
2712157642Sps	/* Wait for the bootcode to acknowledge the message. */
2713157642Sps	for (i = 0; i < FW_ACK_TIME_OUT_MS; i++) {
2714157642Sps		/* Check for a response in the bootcode firmware mailbox. */
2715157642Sps		val = REG_RD_IND(sc, sc->bce_shmem_base + BCE_FW_MB);
2716157642Sps		if ((val & BCE_FW_MSG_ACK) == (msg_data & BCE_DRV_MSG_SEQ))
2717157642Sps			break;
2718157642Sps		DELAY(1000);
2719157642Sps	}
2720157642Sps
2721157642Sps	/* If we've timed out, tell the bootcode that we've stopped waiting. */
2722157642Sps	if (((val & BCE_FW_MSG_ACK) != (msg_data & BCE_DRV_MSG_SEQ)) &&
2723157642Sps		((msg_data & BCE_DRV_MSG_DATA) != BCE_DRV_MSG_DATA_WAIT0)) {
2724157642Sps
2725157642Sps		BCE_PRINTF(sc, "%s(%d): Firmware synchronization timeout! "
2726157642Sps			"msg_data = 0x%08X\n",
2727157642Sps			__FILE__, __LINE__, msg_data);
2728157642Sps
2729157642Sps		msg_data &= ~BCE_DRV_MSG_CODE;
2730157642Sps		msg_data |= BCE_DRV_MSG_CODE_FW_TIMEOUT;
2731157642Sps
2732157642Sps		REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_MB, msg_data);
2733157642Sps
2734157642Sps		sc->bce_fw_timed_out = 1;
2735157642Sps		rc = EBUSY;
2736157642Sps	}
2737157642Sps
2738157642Spsbce_fw_sync_exit:
2739157642Sps	return (rc);
2740157642Sps}
2741157642Sps
2742157642Sps
2743157642Sps/****************************************************************************/
2744157642Sps/* Load Receive Virtual 2 Physical (RV2P) processor firmware.               */
2745157642Sps/*                                                                          */
2746157642Sps/* Returns:                                                                 */
2747157642Sps/*   Nothing.                                                               */
2748157642Sps/****************************************************************************/
2749157642Spsstatic void
2750157642Spsbce_load_rv2p_fw(struct bce_softc *sc, u32 *rv2p_code,
2751157642Sps	u32 rv2p_code_len, u32 rv2p_proc)
2752157642Sps{
2753157642Sps	int i;
2754157642Sps	u32 val;
2755157642Sps
2756157642Sps	for (i = 0; i < rv2p_code_len; i += 8) {
2757157642Sps		REG_WR(sc, BCE_RV2P_INSTR_HIGH, *rv2p_code);
2758157642Sps		rv2p_code++;
2759157642Sps		REG_WR(sc, BCE_RV2P_INSTR_LOW, *rv2p_code);
2760157642Sps		rv2p_code++;
2761157642Sps
2762157642Sps		if (rv2p_proc == RV2P_PROC1) {
2763157642Sps			val = (i / 8) | BCE_RV2P_PROC1_ADDR_CMD_RDWR;
2764157642Sps			REG_WR(sc, BCE_RV2P_PROC1_ADDR_CMD, val);
2765157642Sps		}
2766157642Sps		else {
2767157642Sps			val = (i / 8) | BCE_RV2P_PROC2_ADDR_CMD_RDWR;
2768157642Sps			REG_WR(sc, BCE_RV2P_PROC2_ADDR_CMD, val);
2769157642Sps		}
2770157642Sps	}
2771157642Sps
2772157642Sps	/* Reset the processor, un-stall is done later. */
2773157642Sps	if (rv2p_proc == RV2P_PROC1) {
2774157642Sps		REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC1_RESET);
2775157642Sps	}
2776157642Sps	else {
2777157642Sps		REG_WR(sc, BCE_RV2P_COMMAND, BCE_RV2P_COMMAND_PROC2_RESET);
2778157642Sps	}
2779157642Sps}
2780157642Sps
2781157642Sps
2782157642Sps/****************************************************************************/
2783157642Sps/* Load RISC processor firmware.                                            */
2784157642Sps/*                                                                          */
2785157642Sps/* Loads firmware from the file if_bcefw.h into the scratchpad memory       */
2786157642Sps/* associated with a particular processor.                                  */
2787157642Sps/*                                                                          */
2788157642Sps/* Returns:                                                                 */
2789157642Sps/*   Nothing.                                                               */
2790157642Sps/****************************************************************************/
2791157642Spsstatic void
2792157642Spsbce_load_cpu_fw(struct bce_softc *sc, struct cpu_reg *cpu_reg,
2793157642Sps	struct fw_info *fw)
2794157642Sps{
2795157642Sps	u32 offset;
2796157642Sps	u32 val;
2797157642Sps
2798157642Sps	/* Halt the CPU. */
2799157642Sps	val = REG_RD_IND(sc, cpu_reg->mode);
2800157642Sps	val |= cpu_reg->mode_value_halt;
2801157642Sps	REG_WR_IND(sc, cpu_reg->mode, val);
2802157642Sps	REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
2803157642Sps
2804157642Sps	/* Load the Text area. */
2805157642Sps	offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
2806157642Sps	if (fw->text) {
2807157642Sps		int j;
2808157642Sps
2809157642Sps		for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
2810157642Sps			REG_WR_IND(sc, offset, fw->text[j]);
2811157642Sps	        }
2812157642Sps	}
2813157642Sps
2814157642Sps	/* Load the Data area. */
2815157642Sps	offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
2816157642Sps	if (fw->data) {
2817157642Sps		int j;
2818157642Sps
2819157642Sps		for (j = 0; j < (fw->data_len / 4); j++, offset += 4) {
2820157642Sps			REG_WR_IND(sc, offset, fw->data[j]);
2821157642Sps		}
2822157642Sps	}
2823157642Sps
2824157642Sps	/* Load the SBSS area. */
2825157642Sps	offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
2826157642Sps	if (fw->sbss) {
2827157642Sps		int j;
2828157642Sps
2829157642Sps		for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
2830157642Sps			REG_WR_IND(sc, offset, fw->sbss[j]);
2831157642Sps		}
2832157642Sps	}
2833157642Sps
2834157642Sps	/* Load the BSS area. */
2835157642Sps	offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
2836157642Sps	if (fw->bss) {
2837157642Sps		int j;
2838157642Sps
2839157642Sps		for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
2840157642Sps			REG_WR_IND(sc, offset, fw->bss[j]);
2841157642Sps		}
2842157642Sps	}
2843157642Sps
2844157642Sps	/* Load the Read-Only area. */
2845157642Sps	offset = cpu_reg->spad_base +
2846157642Sps		(fw->rodata_addr - cpu_reg->mips_view_base);
2847157642Sps	if (fw->rodata) {
2848157642Sps		int j;
2849157642Sps
2850157642Sps		for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) {
2851157642Sps			REG_WR_IND(sc, offset, fw->rodata[j]);
2852157642Sps		}
2853157642Sps	}
2854157642Sps
2855157642Sps	/* Clear the pre-fetch instruction. */
2856157642Sps	REG_WR_IND(sc, cpu_reg->inst, 0);
2857157642Sps	REG_WR_IND(sc, cpu_reg->pc, fw->start_addr);
2858157642Sps
2859157642Sps	/* Start the CPU. */
2860157642Sps	val = REG_RD_IND(sc, cpu_reg->mode);
2861157642Sps	val &= ~cpu_reg->mode_value_halt;
2862157642Sps	REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
2863157642Sps	REG_WR_IND(sc, cpu_reg->mode, val);
2864157642Sps}
2865157642Sps
2866157642Sps
2867157642Sps/****************************************************************************/
2868157642Sps/* Initialize the RV2P, RX, TX, TPAT, and COM CPUs.                         */
2869157642Sps/*                                                                          */
2870157642Sps/* Loads the firmware for each CPU and starts the CPU.                      */
2871157642Sps/*                                                                          */
2872157642Sps/* Returns:                                                                 */
2873157642Sps/*   Nothing.                                                               */
2874157642Sps/****************************************************************************/
2875157642Spsstatic void
2876157642Spsbce_init_cpus(struct bce_softc *sc)
2877157642Sps{
2878157642Sps	struct cpu_reg cpu_reg;
2879157642Sps	struct fw_info fw;
2880157642Sps
2881157642Sps	/* Initialize the RV2P processor. */
2882157642Sps	bce_load_rv2p_fw(sc, bce_rv2p_proc1, sizeof(bce_rv2p_proc1), RV2P_PROC1);
2883157642Sps	bce_load_rv2p_fw(sc, bce_rv2p_proc2, sizeof(bce_rv2p_proc2), RV2P_PROC2);
2884157642Sps
2885157642Sps	/* Initialize the RX Processor. */
2886157642Sps	cpu_reg.mode = BCE_RXP_CPU_MODE;
2887157642Sps	cpu_reg.mode_value_halt = BCE_RXP_CPU_MODE_SOFT_HALT;
2888157642Sps	cpu_reg.mode_value_sstep = BCE_RXP_CPU_MODE_STEP_ENA;
2889157642Sps	cpu_reg.state = BCE_RXP_CPU_STATE;
2890157642Sps	cpu_reg.state_value_clear = 0xffffff;
2891157642Sps	cpu_reg.gpr0 = BCE_RXP_CPU_REG_FILE;
2892157642Sps	cpu_reg.evmask = BCE_RXP_CPU_EVENT_MASK;
2893157642Sps	cpu_reg.pc = BCE_RXP_CPU_PROGRAM_COUNTER;
2894157642Sps	cpu_reg.inst = BCE_RXP_CPU_INSTRUCTION;
2895157642Sps	cpu_reg.bp = BCE_RXP_CPU_HW_BREAKPOINT;
2896157642Sps	cpu_reg.spad_base = BCE_RXP_SCRATCH;
2897157642Sps	cpu_reg.mips_view_base = 0x8000000;
2898157642Sps
2899157642Sps	fw.ver_major = bce_RXP_b06FwReleaseMajor;
2900157642Sps	fw.ver_minor = bce_RXP_b06FwReleaseMinor;
2901157642Sps	fw.ver_fix = bce_RXP_b06FwReleaseFix;
2902157642Sps	fw.start_addr = bce_RXP_b06FwStartAddr;
2903157642Sps
2904157642Sps	fw.text_addr = bce_RXP_b06FwTextAddr;
2905157642Sps	fw.text_len = bce_RXP_b06FwTextLen;
2906157642Sps	fw.text_index = 0;
2907157642Sps	fw.text = bce_RXP_b06FwText;
2908157642Sps
2909157642Sps	fw.data_addr = bce_RXP_b06FwDataAddr;
2910157642Sps	fw.data_len = bce_RXP_b06FwDataLen;
2911157642Sps	fw.data_index = 0;
2912157642Sps	fw.data = bce_RXP_b06FwData;
2913157642Sps
2914157642Sps	fw.sbss_addr = bce_RXP_b06FwSbssAddr;
2915157642Sps	fw.sbss_len = bce_RXP_b06FwSbssLen;
2916157642Sps	fw.sbss_index = 0;
2917157642Sps	fw.sbss = bce_RXP_b06FwSbss;
2918157642Sps
2919157642Sps	fw.bss_addr = bce_RXP_b06FwBssAddr;
2920157642Sps	fw.bss_len = bce_RXP_b06FwBssLen;
2921157642Sps	fw.bss_index = 0;
2922157642Sps	fw.bss = bce_RXP_b06FwBss;
2923157642Sps
2924157642Sps	fw.rodata_addr = bce_RXP_b06FwRodataAddr;
2925157642Sps	fw.rodata_len = bce_RXP_b06FwRodataLen;
2926157642Sps	fw.rodata_index = 0;
2927157642Sps	fw.rodata = bce_RXP_b06FwRodata;
2928157642Sps
2929157642Sps	DBPRINT(sc, BCE_INFO_RESET, "Loading RX firmware.\n");
2930157642Sps	bce_load_cpu_fw(sc, &cpu_reg, &fw);
2931157642Sps
2932157642Sps	/* Initialize the TX Processor. */
2933157642Sps	cpu_reg.mode = BCE_TXP_CPU_MODE;
2934157642Sps	cpu_reg.mode_value_halt = BCE_TXP_CPU_MODE_SOFT_HALT;
2935157642Sps	cpu_reg.mode_value_sstep = BCE_TXP_CPU_MODE_STEP_ENA;
2936157642Sps	cpu_reg.state = BCE_TXP_CPU_STATE;
2937157642Sps	cpu_reg.state_value_clear = 0xffffff;
2938157642Sps	cpu_reg.gpr0 = BCE_TXP_CPU_REG_FILE;
2939157642Sps	cpu_reg.evmask = BCE_TXP_CPU_EVENT_MASK;
2940157642Sps	cpu_reg.pc = BCE_TXP_CPU_PROGRAM_COUNTER;
2941157642Sps	cpu_reg.inst = BCE_TXP_CPU_INSTRUCTION;
2942157642Sps	cpu_reg.bp = BCE_TXP_CPU_HW_BREAKPOINT;
2943157642Sps	cpu_reg.spad_base = BCE_TXP_SCRATCH;
2944157642Sps	cpu_reg.mips_view_base = 0x8000000;
2945157642Sps
2946157642Sps	fw.ver_major = bce_TXP_b06FwReleaseMajor;
2947157642Sps	fw.ver_minor = bce_TXP_b06FwReleaseMinor;
2948157642Sps	fw.ver_fix = bce_TXP_b06FwReleaseFix;
2949157642Sps	fw.start_addr = bce_TXP_b06FwStartAddr;
2950157642Sps
2951157642Sps	fw.text_addr = bce_TXP_b06FwTextAddr;
2952157642Sps	fw.text_len = bce_TXP_b06FwTextLen;
2953157642Sps	fw.text_index = 0;
2954157642Sps	fw.text = bce_TXP_b06FwText;
2955157642Sps
2956157642Sps	fw.data_addr = bce_TXP_b06FwDataAddr;
2957157642Sps	fw.data_len = bce_TXP_b06FwDataLen;
2958157642Sps	fw.data_index = 0;
2959157642Sps	fw.data = bce_TXP_b06FwData;
2960157642Sps
2961157642Sps	fw.sbss_addr = bce_TXP_b06FwSbssAddr;
2962157642Sps	fw.sbss_len = bce_TXP_b06FwSbssLen;
2963157642Sps	fw.sbss_index = 0;
2964157642Sps	fw.sbss = bce_TXP_b06FwSbss;
2965157642Sps
2966157642Sps	fw.bss_addr = bce_TXP_b06FwBssAddr;
2967157642Sps	fw.bss_len = bce_TXP_b06FwBssLen;
2968157642Sps	fw.bss_index = 0;
2969157642Sps	fw.bss = bce_TXP_b06FwBss;
2970157642Sps
2971157642Sps	fw.rodata_addr = bce_TXP_b06FwRodataAddr;
2972157642Sps	fw.rodata_len = bce_TXP_b06FwRodataLen;
2973157642Sps	fw.rodata_index = 0;
2974157642Sps	fw.rodata = bce_TXP_b06FwRodata;
2975157642Sps
2976157642Sps	DBPRINT(sc, BCE_INFO_RESET, "Loading TX firmware.\n");
2977157642Sps	bce_load_cpu_fw(sc, &cpu_reg, &fw);
2978157642Sps
2979157642Sps	/* Initialize the TX Patch-up Processor. */
2980157642Sps	cpu_reg.mode = BCE_TPAT_CPU_MODE;
2981157642Sps	cpu_reg.mode_value_halt = BCE_TPAT_CPU_MODE_SOFT_HALT;
2982157642Sps	cpu_reg.mode_value_sstep = BCE_TPAT_CPU_MODE_STEP_ENA;
2983157642Sps	cpu_reg.state = BCE_TPAT_CPU_STATE;
2984157642Sps	cpu_reg.state_value_clear = 0xffffff;
2985157642Sps	cpu_reg.gpr0 = BCE_TPAT_CPU_REG_FILE;
2986157642Sps	cpu_reg.evmask = BCE_TPAT_CPU_EVENT_MASK;
2987157642Sps	cpu_reg.pc = BCE_TPAT_CPU_PROGRAM_COUNTER;
2988157642Sps	cpu_reg.inst = BCE_TPAT_CPU_INSTRUCTION;
2989157642Sps	cpu_reg.bp = BCE_TPAT_CPU_HW_BREAKPOINT;
2990157642Sps	cpu_reg.spad_base = BCE_TPAT_SCRATCH;
2991157642Sps	cpu_reg.mips_view_base = 0x8000000;
2992157642Sps
2993157642Sps	fw.ver_major = bce_TPAT_b06FwReleaseMajor;
2994157642Sps	fw.ver_minor = bce_TPAT_b06FwReleaseMinor;
2995157642Sps	fw.ver_fix = bce_TPAT_b06FwReleaseFix;
2996157642Sps	fw.start_addr = bce_TPAT_b06FwStartAddr;
2997157642Sps
2998157642Sps	fw.text_addr = bce_TPAT_b06FwTextAddr;
2999157642Sps	fw.text_len = bce_TPAT_b06FwTextLen;
3000157642Sps	fw.text_index = 0;
3001157642Sps	fw.text = bce_TPAT_b06FwText;
3002157642Sps
3003157642Sps	fw.data_addr = bce_TPAT_b06FwDataAddr;
3004157642Sps	fw.data_len = bce_TPAT_b06FwDataLen;
3005157642Sps	fw.data_index = 0;
3006157642Sps	fw.data = bce_TPAT_b06FwData;
3007157642Sps
3008157642Sps	fw.sbss_addr = bce_TPAT_b06FwSbssAddr;
3009157642Sps	fw.sbss_len = bce_TPAT_b06FwSbssLen;
3010157642Sps	fw.sbss_index = 0;
3011157642Sps	fw.sbss = bce_TPAT_b06FwSbss;
3012157642Sps
3013157642Sps	fw.bss_addr = bce_TPAT_b06FwBssAddr;
3014157642Sps	fw.bss_len = bce_TPAT_b06FwBssLen;
3015157642Sps	fw.bss_index = 0;
3016157642Sps	fw.bss = bce_TPAT_b06FwBss;
3017157642Sps
3018157642Sps	fw.rodata_addr = bce_TPAT_b06FwRodataAddr;
3019157642Sps	fw.rodata_len = bce_TPAT_b06FwRodataLen;
3020157642Sps	fw.rodata_index = 0;
3021157642Sps	fw.rodata = bce_TPAT_b06FwRodata;
3022157642Sps
3023157642Sps	DBPRINT(sc, BCE_INFO_RESET, "Loading TPAT firmware.\n");
3024157642Sps	bce_load_cpu_fw(sc, &cpu_reg, &fw);
3025157642Sps
3026157642Sps	/* Initialize the Completion Processor. */
3027157642Sps	cpu_reg.mode = BCE_COM_CPU_MODE;
3028157642Sps	cpu_reg.mode_value_halt = BCE_COM_CPU_MODE_SOFT_HALT;
3029157642Sps	cpu_reg.mode_value_sstep = BCE_COM_CPU_MODE_STEP_ENA;
3030157642Sps	cpu_reg.state = BCE_COM_CPU_STATE;
3031157642Sps	cpu_reg.state_value_clear = 0xffffff;
3032157642Sps	cpu_reg.gpr0 = BCE_COM_CPU_REG_FILE;
3033157642Sps	cpu_reg.evmask = BCE_COM_CPU_EVENT_MASK;
3034157642Sps	cpu_reg.pc = BCE_COM_CPU_PROGRAM_COUNTER;
3035157642Sps	cpu_reg.inst = BCE_COM_CPU_INSTRUCTION;
3036157642Sps	cpu_reg.bp = BCE_COM_CPU_HW_BREAKPOINT;
3037157642Sps	cpu_reg.spad_base = BCE_COM_SCRATCH;
3038157642Sps	cpu_reg.mips_view_base = 0x8000000;
3039157642Sps
3040157642Sps	fw.ver_major = bce_COM_b06FwReleaseMajor;
3041157642Sps	fw.ver_minor = bce_COM_b06FwReleaseMinor;
3042157642Sps	fw.ver_fix = bce_COM_b06FwReleaseFix;
3043157642Sps	fw.start_addr = bce_COM_b06FwStartAddr;
3044157642Sps
3045157642Sps	fw.text_addr = bce_COM_b06FwTextAddr;
3046157642Sps	fw.text_len = bce_COM_b06FwTextLen;
3047157642Sps	fw.text_index = 0;
3048157642Sps	fw.text = bce_COM_b06FwText;
3049157642Sps
3050157642Sps	fw.data_addr = bce_COM_b06FwDataAddr;
3051157642Sps	fw.data_len = bce_COM_b06FwDataLen;
3052157642Sps	fw.data_index = 0;
3053157642Sps	fw.data = bce_COM_b06FwData;
3054157642Sps
3055157642Sps	fw.sbss_addr = bce_COM_b06FwSbssAddr;
3056157642Sps	fw.sbss_len = bce_COM_b06FwSbssLen;
3057157642Sps	fw.sbss_index = 0;
3058157642Sps	fw.sbss = bce_COM_b06FwSbss;
3059157642Sps
3060157642Sps	fw.bss_addr = bce_COM_b06FwBssAddr;
3061157642Sps	fw.bss_len = bce_COM_b06FwBssLen;
3062157642Sps	fw.bss_index = 0;
3063157642Sps	fw.bss = bce_COM_b06FwBss;
3064157642Sps
3065157642Sps	fw.rodata_addr = bce_COM_b06FwRodataAddr;
3066157642Sps	fw.rodata_len = bce_COM_b06FwRodataLen;
3067157642Sps	fw.rodata_index = 0;
3068157642Sps	fw.rodata = bce_COM_b06FwRodata;
3069157642Sps
3070157642Sps	DBPRINT(sc, BCE_INFO_RESET, "Loading COM firmware.\n");
3071157642Sps	bce_load_cpu_fw(sc, &cpu_reg, &fw);
3072157642Sps}
3073157642Sps
3074157642Sps
3075157642Sps/****************************************************************************/
3076157642Sps/* Initialize context memory.                                               */
3077157642Sps/*                                                                          */
3078157642Sps/* Clears the memory associated with each Context ID (CID).                 */
3079157642Sps/*                                                                          */
3080157642Sps/* Returns:                                                                 */
3081157642Sps/*   Nothing.                                                               */
3082157642Sps/****************************************************************************/
3083157642Spsstatic void
3084157642Spsbce_init_context(struct bce_softc *sc)
3085157642Sps{
3086157642Sps	u32 vcid;
3087157642Sps
3088157642Sps	vcid = 96;
3089157642Sps	while (vcid) {
3090157642Sps		u32 vcid_addr, pcid_addr, offset;
3091157642Sps
3092157642Sps		vcid--;
3093157642Sps
3094157642Sps   		vcid_addr = GET_CID_ADDR(vcid);
3095157642Sps		pcid_addr = vcid_addr;
3096157642Sps
3097157642Sps		REG_WR(sc, BCE_CTX_VIRT_ADDR, 0x00);
3098157642Sps		REG_WR(sc, BCE_CTX_PAGE_TBL, pcid_addr);
3099157642Sps
3100157642Sps		/* Zero out the context. */
3101157642Sps		for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
3102157642Sps			CTX_WR(sc, 0x00, offset, 0);
3103157642Sps		}
3104157642Sps
3105157642Sps		REG_WR(sc, BCE_CTX_VIRT_ADDR, vcid_addr);
3106157642Sps		REG_WR(sc, BCE_CTX_PAGE_TBL, pcid_addr);
3107157642Sps	}
3108157642Sps}
3109157642Sps
3110157642Sps
3111157642Sps/****************************************************************************/
3112157642Sps/* Fetch the permanent MAC address of the controller.                       */
3113157642Sps/*                                                                          */
3114157642Sps/* Returns:                                                                 */
3115157642Sps/*   Nothing.                                                               */
3116157642Sps/****************************************************************************/
3117157642Spsstatic void
3118157642Spsbce_get_mac_addr(struct bce_softc *sc)
3119157642Sps{
3120157642Sps	u32 mac_lo = 0, mac_hi = 0;
3121157642Sps
3122157642Sps	/*
3123157642Sps	 * The NetXtreme II bootcode populates various NIC
3124157642Sps	 * power-on and runtime configuration items in a
3125157642Sps	 * shared memory area.  The factory configured MAC
3126157642Sps	 * address is available from both NVRAM and the
3127157642Sps	 * shared memory area so we'll read the value from
3128157642Sps	 * shared memory for speed.
3129157642Sps	 */
3130157642Sps
3131157642Sps	mac_hi = REG_RD_IND(sc, sc->bce_shmem_base +
3132157642Sps		BCE_PORT_HW_CFG_MAC_UPPER);
3133157642Sps	mac_lo = REG_RD_IND(sc, sc->bce_shmem_base +
3134157642Sps		BCE_PORT_HW_CFG_MAC_LOWER);
3135157642Sps
3136157642Sps	if ((mac_lo == 0) && (mac_hi == 0)) {
3137157642Sps		BCE_PRINTF(sc, "%s(%d): Invalid Ethernet address!\n",
3138157642Sps			__FILE__, __LINE__);
3139157642Sps	} else {
3140157642Sps		sc->eaddr[0] = (u_char)(mac_hi >> 8);
3141157642Sps		sc->eaddr[1] = (u_char)(mac_hi >> 0);
3142157642Sps		sc->eaddr[2] = (u_char)(mac_lo >> 24);
3143157642Sps		sc->eaddr[3] = (u_char)(mac_lo >> 16);
3144157642Sps		sc->eaddr[4] = (u_char)(mac_lo >> 8);
3145157642Sps		sc->eaddr[5] = (u_char)(mac_lo >> 0);
3146157642Sps	}
3147157642Sps
3148157642Sps	DBPRINT(sc, BCE_INFO, "Permanent Ethernet address = %6D\n", sc->eaddr, ":");
3149157642Sps}
3150157642Sps
3151157642Sps
3152157642Sps/****************************************************************************/
3153157642Sps/* Program the MAC address.                                                 */
3154157642Sps/*                                                                          */
3155157642Sps/* Returns:                                                                 */
3156157642Sps/*   Nothing.                                                               */
3157157642Sps/****************************************************************************/
3158157642Spsstatic void
3159157642Spsbce_set_mac_addr(struct bce_softc *sc)
3160157642Sps{
3161157642Sps	u32 val;
3162157642Sps	u8 *mac_addr = sc->eaddr;
3163157642Sps
3164157642Sps	DBPRINT(sc, BCE_INFO, "Setting Ethernet address = %6D\n", sc->eaddr, ":");
3165157642Sps
3166157642Sps	val = (mac_addr[0] << 8) | mac_addr[1];
3167157642Sps
3168157642Sps	REG_WR(sc, BCE_EMAC_MAC_MATCH0, val);
3169157642Sps
3170157642Sps	val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
3171157642Sps		(mac_addr[4] << 8) | mac_addr[5];
3172157642Sps
3173157642Sps	REG_WR(sc, BCE_EMAC_MAC_MATCH1, val);
3174157642Sps}
3175157642Sps
3176157642Sps
3177157642Sps/****************************************************************************/
3178157642Sps/* Stop the controller.                                                     */
3179157642Sps/*                                                                          */
3180157642Sps/* Returns:                                                                 */
3181157642Sps/*   Nothing.                                                               */
3182157642Sps/****************************************************************************/
3183157642Spsstatic void
3184157642Spsbce_stop(struct bce_softc *sc)
3185157642Sps{
3186157642Sps	struct ifnet *ifp;
3187157642Sps	struct ifmedia_entry *ifm;
3188157642Sps	struct mii_data *mii = NULL;
3189157642Sps	int mtmp, itmp;
3190157642Sps
3191157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3192157642Sps
3193157642Sps	BCE_LOCK_ASSERT(sc);
3194157642Sps
3195157642Sps	ifp = sc->bce_ifp;
3196157642Sps
3197157642Sps	mii = device_get_softc(sc->bce_miibus);
3198157642Sps
3199157642Sps	callout_stop(&sc->bce_stat_ch);
3200157642Sps
3201157642Sps	/* Disable the transmit/receive blocks. */
3202157642Sps	REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS, 0x5ffffff);
3203157642Sps	REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS);
3204157642Sps	DELAY(20);
3205157642Sps
3206157642Sps	bce_disable_intr(sc);
3207157642Sps
3208157642Sps	/* Tell firmware that the driver is going away. */
3209157642Sps	bce_reset(sc, BCE_DRV_MSG_CODE_SUSPEND_NO_WOL);
3210157642Sps
3211157642Sps	/* Free the RX lists. */
3212157642Sps	bce_free_rx_chain(sc);
3213157642Sps
3214157642Sps	/* Free TX buffers. */
3215157642Sps	bce_free_tx_chain(sc);
3216157642Sps
3217157642Sps	/*
3218157642Sps	 * Isolate/power down the PHY, but leave the media selection
3219157642Sps	 * unchanged so that things will be put back to normal when
3220157642Sps	 * we bring the interface back up.
3221157642Sps	 */
3222157642Sps
3223157642Sps	itmp = ifp->if_flags;
3224157642Sps	ifp->if_flags |= IFF_UP;
3225157642Sps	/*
3226157642Sps	 * If we are called from bce_detach(), mii is already NULL.
3227157642Sps	 */
3228157642Sps	if (mii != NULL) {
3229157642Sps		ifm = mii->mii_media.ifm_cur;
3230157642Sps		mtmp = ifm->ifm_media;
3231157642Sps		ifm->ifm_media = IFM_ETHER | IFM_NONE;
3232157642Sps		mii_mediachg(mii);
3233157642Sps		ifm->ifm_media = mtmp;
3234157642Sps	}
3235157642Sps
3236157642Sps	ifp->if_flags = itmp;
3237157642Sps	ifp->if_timer = 0;
3238157642Sps
3239157642Sps	sc->bce_link = 0;
3240157642Sps
3241157642Sps	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
3242157642Sps
3243157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3244157642Sps
3245157642Sps}
3246157642Sps
3247157642Sps
3248157642Spsstatic int
3249157642Spsbce_reset(struct bce_softc *sc, u32 reset_code)
3250157642Sps{
3251157642Sps	u32 val;
3252157642Sps	int i, rc = 0;
3253157642Sps
3254157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3255157642Sps
3256157642Sps	/* Wait for pending PCI transactions to complete. */
3257157642Sps	REG_WR(sc, BCE_MISC_ENABLE_CLR_BITS,
3258157642Sps	       BCE_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
3259157642Sps	       BCE_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
3260157642Sps	       BCE_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
3261157642Sps	       BCE_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
3262157642Sps	val = REG_RD(sc, BCE_MISC_ENABLE_CLR_BITS);
3263157642Sps	DELAY(5);
3264157642Sps
3265157642Sps	/* Assume bootcode is running. */
3266157642Sps	sc->bce_fw_timed_out = 0;
3267157642Sps
3268157642Sps	/* Give the firmware a chance to prepare for the reset. */
3269157642Sps	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT0 | reset_code);
3270157642Sps	if (rc)
3271157642Sps		goto bce_reset_exit;
3272157642Sps
3273157642Sps	/* Set a firmware reminder that this is a soft reset. */
3274157642Sps	REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_RESET_SIGNATURE,
3275157642Sps		   BCE_DRV_RESET_SIGNATURE_MAGIC);
3276157642Sps
3277157642Sps	/* Dummy read to force the chip to complete all current transactions. */
3278157642Sps	val = REG_RD(sc, BCE_MISC_ID);
3279157642Sps
3280157642Sps	/* Chip reset. */
3281157642Sps	val = BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
3282157642Sps	      BCE_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
3283157642Sps	      BCE_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
3284157642Sps	REG_WR(sc, BCE_PCICFG_MISC_CONFIG, val);
3285157642Sps
3286157642Sps	/* Allow up to 30us for reset to complete. */
3287157642Sps	for (i = 0; i < 10; i++) {
3288157642Sps		val = REG_RD(sc, BCE_PCICFG_MISC_CONFIG);
3289157642Sps		if ((val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
3290157642Sps			    BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
3291157642Sps			break;
3292157642Sps		}
3293157642Sps		DELAY(10);
3294157642Sps	}
3295157642Sps
3296157642Sps	/* Check that reset completed successfully. */
3297157642Sps	if (val & (BCE_PCICFG_MISC_CONFIG_CORE_RST_REQ |
3298157642Sps		   BCE_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
3299157642Sps		BCE_PRINTF(sc, "%s(%d): Reset failed!\n",
3300157642Sps			__FILE__, __LINE__);
3301157642Sps		rc = EBUSY;
3302157642Sps		goto bce_reset_exit;
3303157642Sps	}
3304157642Sps
3305157642Sps	/* Make sure byte swapping is properly configured. */
3306157642Sps	val = REG_RD(sc, BCE_PCI_SWAP_DIAG0);
3307157642Sps	if (val != 0x01020304) {
3308157642Sps		BCE_PRINTF(sc, "%s(%d): Byte swap is incorrect!\n",
3309157642Sps			__FILE__, __LINE__);
3310157642Sps		rc = ENODEV;
3311157642Sps		goto bce_reset_exit;
3312157642Sps	}
3313157642Sps
3314157642Sps	/* Just completed a reset, assume that firmware is running again. */
3315157642Sps	sc->bce_fw_timed_out = 0;
3316157642Sps
3317157642Sps	/* Wait for the firmware to finish its initialization. */
3318157642Sps	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT1 | reset_code);
3319157642Sps	if (rc)
3320157642Sps		BCE_PRINTF(sc, "%s(%d): Firmware did not complete initialization!\n",
3321157642Sps			__FILE__, __LINE__);
3322157642Sps
3323157642Spsbce_reset_exit:
3324157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3325157642Sps
3326157642Sps	return (rc);
3327157642Sps}
3328157642Sps
3329157642Sps
3330157642Spsstatic int
3331157642Spsbce_chipinit(struct bce_softc *sc)
3332157642Sps{
3333157642Sps	u32 val;
3334157642Sps	int rc = 0;
3335157642Sps
3336157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3337157642Sps
3338157642Sps	/* Make sure the interrupt is not active. */
3339157642Sps	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD, BCE_PCICFG_INT_ACK_CMD_MASK_INT);
3340157642Sps
3341157642Sps	/* Initialize DMA byte/word swapping, configure the number of DMA  */
3342157642Sps	/* channels and PCI clock compensation delay.                      */
3343157642Sps	val = BCE_DMA_CONFIG_DATA_BYTE_SWAP |
3344157642Sps	      BCE_DMA_CONFIG_DATA_WORD_SWAP |
3345157642Sps#if BYTE_ORDER == BIG_ENDIAN
3346157642Sps	      BCE_DMA_CONFIG_CNTL_BYTE_SWAP |
3347157642Sps#endif
3348157642Sps	      BCE_DMA_CONFIG_CNTL_WORD_SWAP |
3349157642Sps	      DMA_READ_CHANS << 12 |
3350157642Sps	      DMA_WRITE_CHANS << 16;
3351157642Sps
3352157642Sps	val |= (0x2 << 20) | BCE_DMA_CONFIG_CNTL_PCI_COMP_DLY;
3353157642Sps
3354157642Sps	if ((sc->bce_flags & BCE_PCIX_FLAG) && (sc->bus_speed_mhz == 133))
3355157642Sps		val |= BCE_DMA_CONFIG_PCI_FAST_CLK_CMP;
3356157642Sps
3357157642Sps	/*
3358157642Sps	 * This setting resolves a problem observed on certain Intel PCI
3359157642Sps	 * chipsets that cannot handle multiple outstanding DMA operations.
3360157642Sps	 * See errata E9_5706A1_65.
3361157642Sps	 */
3362157642Sps	if ((BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) &&
3363157642Sps	    (BCE_CHIP_ID(sc) != BCE_CHIP_ID_5706_A0) &&
3364157642Sps	    !(sc->bce_flags & BCE_PCIX_FLAG))
3365157642Sps		val |= BCE_DMA_CONFIG_CNTL_PING_PONG_DMA;
3366157642Sps
3367157642Sps	REG_WR(sc, BCE_DMA_CONFIG, val);
3368157642Sps
3369157642Sps	/* Clear the PCI-X relaxed ordering bit. See errata E3_5708CA0_570. */
3370157642Sps	if (sc->bce_flags & BCE_PCIX_FLAG) {
3371157642Sps		u16 val;
3372157642Sps
3373157642Sps		val = pci_read_config(sc->bce_dev, BCE_PCI_PCIX_CMD, 2);
3374157642Sps		pci_write_config(sc->bce_dev, BCE_PCI_PCIX_CMD, val & ~0x2, 2);
3375157642Sps	}
3376157642Sps
3377157642Sps	/* Enable the RX_V2P and Context state machines before access. */
3378157642Sps	REG_WR(sc, BCE_MISC_ENABLE_SET_BITS,
3379157642Sps	       BCE_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
3380157642Sps	       BCE_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
3381157642Sps	       BCE_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
3382157642Sps
3383157642Sps	/* Initialize context mapping and zero out the quick contexts. */
3384157642Sps	bce_init_context(sc);
3385157642Sps
3386157642Sps	/* Initialize the on-boards CPUs */
3387157642Sps	bce_init_cpus(sc);
3388157642Sps
3389157642Sps	/* Prepare NVRAM for access. */
3390157642Sps	if (bce_init_nvram(sc)) {
3391157642Sps		rc = ENODEV;
3392157642Sps		goto bce_chipinit_exit;
3393157642Sps	}
3394157642Sps
3395157642Sps	/* Set the kernel bypass block size */
3396157642Sps	val = REG_RD(sc, BCE_MQ_CONFIG);
3397157642Sps	val &= ~BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE;
3398157642Sps	val |= BCE_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
3399157642Sps	REG_WR(sc, BCE_MQ_CONFIG, val);
3400157642Sps
3401157642Sps	val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
3402157642Sps	REG_WR(sc, BCE_MQ_KNL_BYP_WIND_START, val);
3403157642Sps	REG_WR(sc, BCE_MQ_KNL_WIND_END, val);
3404157642Sps
3405157642Sps	val = (BCM_PAGE_BITS - 8) << 24;
3406157642Sps	REG_WR(sc, BCE_RV2P_CONFIG, val);
3407157642Sps
3408157642Sps	/* Configure page size. */
3409157642Sps	val = REG_RD(sc, BCE_TBDR_CONFIG);
3410157642Sps	val &= ~BCE_TBDR_CONFIG_PAGE_SIZE;
3411157642Sps	val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
3412157642Sps	REG_WR(sc, BCE_TBDR_CONFIG, val);
3413157642Sps
3414157642Spsbce_chipinit_exit:
3415157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3416157642Sps
3417157642Sps	return(rc);
3418157642Sps}
3419157642Sps
3420157642Sps
3421157642Sps/****************************************************************************/
3422157642Sps/* Initialize the controller in preparation to send/receive traffic.        */
3423157642Sps/*                                                                          */
3424157642Sps/* Returns:                                                                 */
3425157642Sps/*   0 for success, positive value for failure.                             */
3426157642Sps/****************************************************************************/
3427157642Spsstatic int
3428157642Spsbce_blockinit(struct bce_softc *sc)
3429157642Sps{
3430157642Sps	u32 reg, val;
3431157642Sps	int rc = 0;
3432157642Sps
3433157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3434157642Sps
3435157642Sps	/* Load the hardware default MAC address. */
3436157642Sps	bce_set_mac_addr(sc);
3437157642Sps
3438157642Sps	/* Set the Ethernet backoff seed value */
3439157642Sps	val = sc->eaddr[0]         + (sc->eaddr[1] << 8) +
3440157642Sps	      (sc->eaddr[2] << 16) + (sc->eaddr[3]     ) +
3441157642Sps	      (sc->eaddr[4] << 8)  + (sc->eaddr[5] << 16);
3442157642Sps	REG_WR(sc, BCE_EMAC_BACKOFF_SEED, val);
3443157642Sps
3444157642Sps	sc->last_status_idx = 0;
3445157642Sps	sc->rx_mode = BCE_EMAC_RX_MODE_SORT_MODE;
3446157642Sps
3447157642Sps	/* Set up link change interrupt generation. */
3448157642Sps	REG_WR(sc, BCE_EMAC_ATTENTION_ENA, BCE_EMAC_ATTENTION_ENA_LINK);
3449157642Sps
3450157642Sps	/* Program the physical address of the status block. */
3451157642Sps	REG_WR(sc, BCE_HC_STATUS_ADDR_L,
3452157642Sps		BCE_ADDR_LO(sc->status_block_paddr));
3453157642Sps	REG_WR(sc, BCE_HC_STATUS_ADDR_H,
3454157642Sps		BCE_ADDR_HI(sc->status_block_paddr));
3455157642Sps
3456157642Sps	/* Program the physical address of the statistics block. */
3457157642Sps	REG_WR(sc, BCE_HC_STATISTICS_ADDR_L,
3458157642Sps		BCE_ADDR_LO(sc->stats_block_paddr));
3459157642Sps	REG_WR(sc, BCE_HC_STATISTICS_ADDR_H,
3460157642Sps		BCE_ADDR_HI(sc->stats_block_paddr));
3461157642Sps
3462157642Sps	/* Program various host coalescing parameters. */
3463157642Sps	REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
3464157642Sps		(sc->bce_tx_quick_cons_trip_int << 16) | sc->bce_tx_quick_cons_trip);
3465157642Sps	REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
3466157642Sps		(sc->bce_rx_quick_cons_trip_int << 16) | sc->bce_rx_quick_cons_trip);
3467157642Sps	REG_WR(sc, BCE_HC_COMP_PROD_TRIP,
3468157642Sps		(sc->bce_comp_prod_trip_int << 16) | sc->bce_comp_prod_trip);
3469157642Sps	REG_WR(sc, BCE_HC_TX_TICKS,
3470157642Sps		(sc->bce_tx_ticks_int << 16) | sc->bce_tx_ticks);
3471157642Sps	REG_WR(sc, BCE_HC_RX_TICKS,
3472157642Sps		(sc->bce_rx_ticks_int << 16) | sc->bce_rx_ticks);
3473157642Sps	REG_WR(sc, BCE_HC_COM_TICKS,
3474157642Sps		(sc->bce_com_ticks_int << 16) | sc->bce_com_ticks);
3475157642Sps	REG_WR(sc, BCE_HC_CMD_TICKS,
3476157642Sps		(sc->bce_cmd_ticks_int << 16) | sc->bce_cmd_ticks);
3477157642Sps	REG_WR(sc, BCE_HC_STATS_TICKS,
3478157642Sps		(sc->bce_stats_ticks & 0xffff00));
3479157642Sps	REG_WR(sc, BCE_HC_STAT_COLLECT_TICKS,
3480157642Sps		0xbb8);  /* 3ms */
3481157642Sps	REG_WR(sc, BCE_HC_CONFIG,
3482157642Sps		(BCE_HC_CONFIG_RX_TMR_MODE | BCE_HC_CONFIG_TX_TMR_MODE |
3483157642Sps		BCE_HC_CONFIG_COLLECT_STATS));
3484157642Sps
3485157642Sps	/* Clear the internal statistics counters. */
3486157642Sps	REG_WR(sc, BCE_HC_COMMAND, BCE_HC_COMMAND_CLR_STAT_NOW);
3487157642Sps
3488157642Sps	/* Verify that bootcode is running. */
3489157642Sps	reg = REG_RD_IND(sc, sc->bce_shmem_base + BCE_DEV_INFO_SIGNATURE);
3490157642Sps
3491157642Sps	DBRUNIF(DB_RANDOMTRUE(bce_debug_bootcode_running_failure),
3492157642Sps		BCE_PRINTF(sc, "%s(%d): Simulating bootcode failure.\n",
3493157642Sps			__FILE__, __LINE__);
3494157642Sps		reg = 0);
3495157642Sps
3496157642Sps	if ((reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
3497157642Sps	    BCE_DEV_INFO_SIGNATURE_MAGIC) {
3498157642Sps		BCE_PRINTF(sc, "%s(%d): Bootcode not running! Found: 0x%08X, "
3499157642Sps			"Expected: 08%08X\n", __FILE__, __LINE__,
3500157642Sps			(reg & BCE_DEV_INFO_SIGNATURE_MAGIC_MASK),
3501157642Sps			BCE_DEV_INFO_SIGNATURE_MAGIC);
3502157642Sps		rc = ENODEV;
3503157642Sps		goto bce_blockinit_exit;
3504157642Sps	}
3505157642Sps
3506157642Sps	/* Check if any management firmware is running. */
3507157642Sps	reg = REG_RD_IND(sc, sc->bce_shmem_base + BCE_PORT_FEATURE);
3508157642Sps	if (reg & (BCE_PORT_FEATURE_ASF_ENABLED | BCE_PORT_FEATURE_IMD_ENABLED)) {
3509157642Sps		DBPRINT(sc, BCE_INFO, "Management F/W Enabled.\n");
3510157642Sps		sc->bce_flags |= BCE_MFW_ENABLE_FLAG;
3511157642Sps	}
3512157642Sps
3513157642Sps	sc->bce_fw_ver = REG_RD_IND(sc, sc->bce_shmem_base + BCE_DEV_INFO_BC_REV);
3514157642Sps	DBPRINT(sc, BCE_INFO, "bootcode rev = 0x%08X\n", sc->bce_fw_ver);
3515157642Sps
3516157642Sps	/* Allow bootcode to apply any additional fixes before enabling MAC. */
3517157642Sps	rc = bce_fw_sync(sc, BCE_DRV_MSG_DATA_WAIT2 | BCE_DRV_MSG_CODE_RESET);
3518157642Sps
3519157642Sps	/* Enable link state change interrupt generation. */
3520157642Sps	REG_WR(sc, BCE_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
3521157642Sps
3522157642Sps	/* Enable all remaining blocks in the MAC. */
3523157642Sps	REG_WR(sc, BCE_MISC_ENABLE_SET_BITS, 0x5ffffff);
3524157642Sps	REG_RD(sc, BCE_MISC_ENABLE_SET_BITS);
3525157642Sps	DELAY(20);
3526157642Sps
3527157642Spsbce_blockinit_exit:
3528157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3529157642Sps
3530157642Sps	return (rc);
3531157642Sps}
3532157642Sps
3533157642Sps
3534157642Sps/****************************************************************************/
3535157642Sps/* Encapsulate an mbuf cluster into the rx_bd chain.                        */
3536157642Sps/*                                                                          */
3537157642Sps/* The NetXtreme II can support Jumbo frames by using multiple rx_bd's.     */
3538157642Sps/* This routine will map an mbuf cluster into 1 or more rx_bd's as          */
3539157642Sps/* necessary.                                                               */
3540157642Sps/*                                                                          */
3541157642Sps/* Returns:                                                                 */
3542157642Sps/*   0 for success, positive value for failure.                             */
3543157642Sps/****************************************************************************/
3544157642Spsstatic int
3545157642Spsbce_get_buf(struct bce_softc *sc, struct mbuf *m, u16 *prod, u16 *chain_prod,
3546157642Sps	u32 *prod_bseq)
3547157642Sps{
3548157642Sps	bus_dmamap_t		map;
3549157642Sps	bus_dma_segment_t	segs[4];
3550157642Sps	struct mbuf *m_new = NULL;
3551157642Sps	struct rx_bd		*rxbd;
3552157642Sps	int i, nsegs, error, rc = 0;
3553157642Sps#ifdef BCE_DEBUG
3554157642Sps	u16 debug_chain_prod = *chain_prod;
3555157642Sps#endif
3556157642Sps
3557157642Sps	DBPRINT(sc, (BCE_VERBOSE_RESET | BCE_VERBOSE_RECV), "Entering %s()\n",
3558157642Sps		__FUNCTION__);
3559157642Sps
3560157642Sps	/* Make sure the inputs are valid. */
3561157642Sps	DBRUNIF((*chain_prod > MAX_RX_BD),
3562157642Sps		BCE_PRINTF(sc, "%s(%d): RX producer out of range: 0x%04X > 0x%04X\n",
3563157642Sps		__FILE__, __LINE__, *chain_prod, (u16) MAX_RX_BD));
3564157642Sps
3565157642Sps	DBPRINT(sc, BCE_VERBOSE_RECV, "%s(enter): prod = 0x%04X, chain_prod = 0x%04X, "
3566157642Sps		"prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod, *prod_bseq);
3567157642Sps
3568157642Sps	if (m == NULL) {
3569157642Sps
3570157642Sps		DBRUNIF(DB_RANDOMTRUE(bce_debug_mbuf_allocation_failure),
3571157642Sps			BCE_PRINTF(sc, "%s(%d): Simulating mbuf allocation failure.\n",
3572157642Sps				__FILE__, __LINE__);
3573157642Sps			sc->mbuf_alloc_failed++;
3574157642Sps			rc = ENOBUFS;
3575157642Sps			goto bce_get_buf_exit);
3576157642Sps
3577157642Sps		/* This is a new mbuf allocation. */
3578157642Sps		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
3579157642Sps		if (m_new == NULL) {
3580157642Sps
3581157642Sps			DBPRINT(sc, BCE_WARN, "%s(%d): RX mbuf header allocation failed!\n",
3582157642Sps				__FILE__, __LINE__);
3583157642Sps
3584157642Sps			DBRUNIF(1, sc->mbuf_alloc_failed++);
3585157642Sps
3586157642Sps			rc = ENOBUFS;
3587157642Sps			goto bce_get_buf_exit;
3588157642Sps		}
3589157642Sps
3590157642Sps		DBRUNIF(1, sc->rx_mbuf_alloc++);
3591157642Sps		m_cljget(m_new, M_DONTWAIT, sc->mbuf_alloc_size);
3592157642Sps		if (!(m_new->m_flags & M_EXT)) {
3593157642Sps
3594157642Sps			DBPRINT(sc, BCE_WARN, "%s(%d): RX mbuf chain allocation failed!\n",
3595157642Sps				__FILE__, __LINE__);
3596157642Sps
3597157642Sps			m_freem(m_new);
3598157642Sps
3599157642Sps			DBRUNIF(1, sc->rx_mbuf_alloc--);
3600157642Sps			DBRUNIF(1, sc->mbuf_alloc_failed++);
3601157642Sps
3602157642Sps			rc = ENOBUFS;
3603157642Sps			goto bce_get_buf_exit;
3604157642Sps		}
3605157642Sps
3606157642Sps		m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size;
3607157642Sps	} else {
3608157642Sps		m_new = m;
3609157642Sps		m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size;
3610157642Sps		m_new->m_data = m_new->m_ext.ext_buf;
3611157642Sps	}
3612157642Sps
3613157642Sps	/* Map the mbuf cluster into device memory. */
3614157642Sps	map = sc->rx_mbuf_map[*chain_prod];
3615157642Sps	error = bus_dmamap_load_mbuf_sg(sc->rx_mbuf_tag, map, m_new,
3616157642Sps	    segs, &nsegs, BUS_DMA_NOWAIT);
3617157642Sps
3618157642Sps	if (error) {
3619157642Sps		BCE_PRINTF(sc, "%s(%d): Error mapping mbuf into RX chain!\n",
3620157642Sps			__FILE__, __LINE__);
3621157642Sps
3622157642Sps		m_freem(m_new);
3623157642Sps
3624157642Sps		DBRUNIF(1, sc->rx_mbuf_alloc--);
3625157642Sps
3626157642Sps		rc = ENOBUFS;
3627157642Sps		goto bce_get_buf_exit;
3628157642Sps	}
3629157642Sps
3630157642Sps	/* Watch for overflow. */
3631157642Sps	DBRUNIF((sc->free_rx_bd > USABLE_RX_BD),
3632157642Sps		BCE_PRINTF(sc, "%s(%d): Too many free rx_bd (0x%04X > 0x%04X)!\n",
3633157642Sps			__FILE__, __LINE__, sc->free_rx_bd, (u16) USABLE_RX_BD));
3634157642Sps
3635157642Sps	DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
3636157642Sps		sc->rx_low_watermark = sc->free_rx_bd);
3637157642Sps
3638157642Sps	/* Setup the rx_bd for the first segment. */
3639157642Sps	rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
3640157642Sps
3641157642Sps	rxbd->rx_bd_haddr_lo  = htole32(BCE_ADDR_LO(segs[0].ds_addr));
3642157642Sps	rxbd->rx_bd_haddr_hi  = htole32(BCE_ADDR_HI(segs[0].ds_addr));
3643157642Sps	rxbd->rx_bd_len       = htole32(segs[0].ds_len);
3644157642Sps	rxbd->rx_bd_flags     = htole32(RX_BD_FLAGS_START);
3645157642Sps	*prod_bseq += segs[0].ds_len;
3646157642Sps
3647157642Sps	for (i = 1; i < nsegs; i++) {
3648157642Sps
3649157642Sps		*prod = NEXT_RX_BD(*prod);
3650157642Sps		*chain_prod = RX_CHAIN_IDX(*prod);
3651157642Sps
3652157642Sps		rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
3653157642Sps
3654157642Sps		rxbd->rx_bd_haddr_lo  = htole32(BCE_ADDR_LO(segs[i].ds_addr));
3655157642Sps		rxbd->rx_bd_haddr_hi  = htole32(BCE_ADDR_HI(segs[i].ds_addr));
3656157642Sps		rxbd->rx_bd_len       = htole32(segs[i].ds_len);
3657157642Sps		rxbd->rx_bd_flags     = 0;
3658157642Sps		*prod_bseq += segs[i].ds_len;
3659157642Sps	}
3660157642Sps
3661157642Sps	rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END);
3662157642Sps
3663157642Sps	/* Save the mbuf and update our counter. */
3664157642Sps	sc->rx_mbuf_ptr[*chain_prod] = m_new;
3665157642Sps	sc->free_rx_bd -= nsegs;
3666157642Sps
3667157642Sps	DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_mbuf_chain(sc, debug_chain_prod,
3668157642Sps		nsegs));
3669157642Sps
3670157642Sps	DBPRINT(sc, BCE_VERBOSE_RECV, "%s(exit): prod = 0x%04X, chain_prod = 0x%04X, "
3671157642Sps		"prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod, *prod_bseq);
3672157642Sps
3673157642Spsbce_get_buf_exit:
3674157642Sps	DBPRINT(sc, (BCE_VERBOSE_RESET | BCE_VERBOSE_RECV), "Exiting %s()\n",
3675157642Sps		__FUNCTION__);
3676157642Sps
3677157642Sps	return(rc);
3678157642Sps}
3679157642Sps
3680157642Sps
3681157642Sps/****************************************************************************/
3682157642Sps/* Allocate memory and initialize the TX data structures.                   */
3683157642Sps/*                                                                          */
3684157642Sps/* Returns:                                                                 */
3685157642Sps/*   0 for success, positive value for failure.                             */
3686157642Sps/****************************************************************************/
3687157642Spsstatic int
3688157642Spsbce_init_tx_chain(struct bce_softc *sc)
3689157642Sps{
3690157642Sps	struct tx_bd *txbd;
3691157642Sps	u32 val;
3692157642Sps	int i, rc = 0;
3693157642Sps
3694157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3695157642Sps
3696157642Sps	/* Set the initial TX producer/consumer indices. */
3697157642Sps	sc->tx_prod        = 0;
3698157642Sps	sc->tx_cons        = 0;
3699157642Sps	sc->tx_prod_bseq   = 0;
3700157642Sps	sc->used_tx_bd = 0;
3701157642Sps	DBRUNIF(1, sc->tx_hi_watermark = USABLE_TX_BD);
3702157642Sps
3703157642Sps	/*
3704157642Sps	 * The NetXtreme II supports a linked-list structre called
3705157642Sps	 * a Buffer Descriptor Chain (or BD chain).  A BD chain
3706157642Sps	 * consists of a series of 1 or more chain pages, each of which
3707157642Sps	 * consists of a fixed number of BD entries.
3708157642Sps	 * The last BD entry on each page is a pointer to the next page
3709157642Sps	 * in the chain, and the last pointer in the BD chain
3710157642Sps	 * points back to the beginning of the chain.
3711157642Sps	 */
3712157642Sps
3713157642Sps	/* Set the TX next pointer chain entries. */
3714157642Sps	for (i = 0; i < TX_PAGES; i++) {
3715157642Sps		int j;
3716157642Sps
3717157642Sps		txbd = &sc->tx_bd_chain[i][USABLE_TX_BD_PER_PAGE];
3718157642Sps
3719157642Sps		/* Check if we've reached the last page. */
3720157642Sps		if (i == (TX_PAGES - 1))
3721157642Sps			j = 0;
3722157642Sps		else
3723157642Sps			j = i + 1;
3724157642Sps
3725157642Sps		txbd->tx_bd_haddr_hi = htole32(BCE_ADDR_HI(sc->tx_bd_chain_paddr[j]));
3726157642Sps		txbd->tx_bd_haddr_lo = htole32(BCE_ADDR_LO(sc->tx_bd_chain_paddr[j]));
3727157642Sps	}
3728157642Sps
3729157642Sps	/*
3730157642Sps	 * Initialize the context ID for an L2 TX chain.
3731157642Sps	 */
3732157642Sps	val = BCE_L2CTX_TYPE_TYPE_L2;
3733157642Sps	val |= BCE_L2CTX_TYPE_SIZE_L2;
3734157642Sps	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TYPE, val);
3735157642Sps
3736157642Sps	val = BCE_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
3737157642Sps	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_CMD_TYPE, val);
3738157642Sps
3739157642Sps	/* Point the hardware to the first page in the chain. */
3740157642Sps	val = BCE_ADDR_HI(sc->tx_bd_chain_paddr[0]);
3741157642Sps	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TBDR_BHADDR_HI, val);
3742157642Sps	val = BCE_ADDR_LO(sc->tx_bd_chain_paddr[0]);
3743157642Sps	CTX_WR(sc, GET_CID_ADDR(TX_CID), BCE_L2CTX_TBDR_BHADDR_LO, val);
3744157642Sps
3745157642Sps	DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_chain(sc, 0, TOTAL_TX_BD));
3746157642Sps
3747157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3748157642Sps
3749157642Sps	return(rc);
3750157642Sps}
3751157642Sps
3752157642Sps
3753157642Sps/****************************************************************************/
3754157642Sps/* Free memory and clear the TX data structures.                            */
3755157642Sps/*                                                                          */
3756157642Sps/* Returns:                                                                 */
3757157642Sps/*   Nothing.                                                               */
3758157642Sps/****************************************************************************/
3759157642Spsstatic void
3760157642Spsbce_free_tx_chain(struct bce_softc *sc)
3761157642Sps{
3762157642Sps	int i;
3763157642Sps
3764157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3765157642Sps
3766157642Sps	/* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
3767157642Sps	for (i = 0; i < TOTAL_TX_BD; i++) {
3768157642Sps		if (sc->tx_mbuf_ptr[i] != NULL) {
3769157642Sps			if (sc->tx_mbuf_map != NULL)
3770157642Sps				bus_dmamap_sync(sc->tx_mbuf_tag, sc->tx_mbuf_map[i],
3771157642Sps					BUS_DMASYNC_POSTWRITE);
3772157642Sps			m_freem(sc->tx_mbuf_ptr[i]);
3773157642Sps			sc->tx_mbuf_ptr[i] = NULL;
3774157642Sps			DBRUNIF(1, sc->tx_mbuf_alloc--);
3775157642Sps		}
3776157642Sps	}
3777157642Sps
3778157642Sps	/* Clear each TX chain page. */
3779157642Sps	for (i = 0; i < TX_PAGES; i++)
3780157642Sps		bzero((char *)sc->tx_bd_chain[i], BCE_TX_CHAIN_PAGE_SZ);
3781157642Sps
3782157642Sps	/* Check if we lost any mbufs in the process. */
3783157642Sps	DBRUNIF((sc->tx_mbuf_alloc),
3784157642Sps		BCE_PRINTF(sc, "%s(%d): Memory leak! Lost %d mbufs "
3785157642Sps			"from tx chain!\n",
3786157642Sps			__FILE__, __LINE__, sc->tx_mbuf_alloc));
3787157642Sps
3788157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3789157642Sps}
3790157642Sps
3791157642Sps
3792157642Sps/****************************************************************************/
3793157642Sps/* Allocate memory and initialize the RX data structures.                   */
3794157642Sps/*                                                                          */
3795157642Sps/* Returns:                                                                 */
3796157642Sps/*   0 for success, positive value for failure.                             */
3797157642Sps/****************************************************************************/
3798157642Spsstatic int
3799157642Spsbce_init_rx_chain(struct bce_softc *sc)
3800157642Sps{
3801157642Sps	struct rx_bd *rxbd;
3802157642Sps	int i, rc = 0;
3803157642Sps	u16 prod, chain_prod;
3804157642Sps	u32 prod_bseq, val;
3805157642Sps
3806157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3807157642Sps
3808157642Sps	/* Initialize the RX producer and consumer indices. */
3809157642Sps	sc->rx_prod        = 0;
3810157642Sps	sc->rx_cons        = 0;
3811157642Sps	sc->rx_prod_bseq   = 0;
3812157642Sps	sc->free_rx_bd     = BCE_RX_SLACK_SPACE;
3813157642Sps	DBRUNIF(1, sc->rx_low_watermark = USABLE_RX_BD);
3814157642Sps
3815157642Sps	/* Initialize the RX next pointer chain entries. */
3816157642Sps	for (i = 0; i < RX_PAGES; i++) {
3817157642Sps		int j;
3818157642Sps
3819157642Sps		rxbd = &sc->rx_bd_chain[i][USABLE_RX_BD_PER_PAGE];
3820157642Sps
3821157642Sps		/* Check if we've reached the last page. */
3822157642Sps		if (i == (RX_PAGES - 1))
3823157642Sps			j = 0;
3824157642Sps		else
3825157642Sps			j = i + 1;
3826157642Sps
3827157642Sps		/* Setup the chain page pointers. */
3828157642Sps		rxbd->rx_bd_haddr_hi = htole32(BCE_ADDR_HI(sc->rx_bd_chain_paddr[j]));
3829157642Sps		rxbd->rx_bd_haddr_lo = htole32(BCE_ADDR_LO(sc->rx_bd_chain_paddr[j]));
3830157642Sps	}
3831157642Sps
3832157642Sps	/* Initialize the context ID for an L2 RX chain. */
3833157642Sps	val = BCE_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
3834157642Sps	val |= BCE_L2CTX_CTX_TYPE_SIZE_L2;
3835157642Sps	val |= 0x02 << 8;
3836157642Sps	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_CTX_TYPE, val);
3837157642Sps
3838157642Sps	/* Point the hardware to the first page in the chain. */
3839157642Sps	val = BCE_ADDR_HI(sc->rx_bd_chain_paddr[0]);
3840157642Sps	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_NX_BDHADDR_HI, val);
3841157642Sps	val = BCE_ADDR_LO(sc->rx_bd_chain_paddr[0]);
3842157642Sps	CTX_WR(sc, GET_CID_ADDR(RX_CID), BCE_L2CTX_NX_BDHADDR_LO, val);
3843157642Sps
3844157642Sps	/* Allocate mbuf clusters for the rx_bd chain. */
3845157642Sps	prod = prod_bseq = 0;
3846157642Sps	while (prod < BCE_RX_SLACK_SPACE) {
3847157642Sps		chain_prod = RX_CHAIN_IDX(prod);
3848157642Sps		if (bce_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq)) {
3849157642Sps			BCE_PRINTF(sc, "%s(%d): Error filling RX chain: rx_bd[0x%04X]!\n",
3850157642Sps				__FILE__, __LINE__, chain_prod);
3851157642Sps			rc = ENOBUFS;
3852157642Sps			break;
3853157642Sps		}
3854157642Sps		prod = NEXT_RX_BD(prod);
3855157642Sps	}
3856157642Sps
3857157642Sps	/* Save the RX chain producer index. */
3858157642Sps	sc->rx_prod      = prod;
3859157642Sps	sc->rx_prod_bseq = prod_bseq;
3860157642Sps
3861157642Sps	for (i = 0; i < RX_PAGES; i++) {
3862157642Sps		bus_dmamap_sync(
3863157642Sps			sc->rx_bd_chain_tag,
3864157642Sps	    	sc->rx_bd_chain_map[i],
3865157642Sps		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3866157642Sps	}
3867157642Sps
3868157642Sps	/* Tell the chip about the waiting rx_bd's. */
3869157642Sps	REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod);
3870157642Sps	REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq);
3871157642Sps
3872157642Sps	DBRUN(BCE_VERBOSE_RECV, bce_dump_rx_chain(sc, 0, TOTAL_RX_BD));
3873157642Sps
3874157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3875157642Sps
3876157642Sps	return(rc);
3877157642Sps}
3878157642Sps
3879157642Sps
3880157642Sps/****************************************************************************/
3881157642Sps/* Free memory and clear the RX data structures.                            */
3882157642Sps/*                                                                          */
3883157642Sps/* Returns:                                                                 */
3884157642Sps/*   Nothing.                                                               */
3885157642Sps/****************************************************************************/
3886157642Spsstatic void
3887157642Spsbce_free_rx_chain(struct bce_softc *sc)
3888157642Sps{
3889157642Sps	int i;
3890157642Sps
3891157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
3892157642Sps
3893157642Sps	/* Free any mbufs still in the RX mbuf chain. */
3894157642Sps	for (i = 0; i < TOTAL_RX_BD; i++) {
3895157642Sps		if (sc->rx_mbuf_ptr[i] != NULL) {
3896157642Sps			if (sc->rx_mbuf_map[i] != NULL)
3897157642Sps				bus_dmamap_sync(sc->rx_mbuf_tag, sc->rx_mbuf_map[i],
3898157642Sps					BUS_DMASYNC_POSTREAD);
3899157642Sps			m_freem(sc->rx_mbuf_ptr[i]);
3900157642Sps			sc->rx_mbuf_ptr[i] = NULL;
3901157642Sps			DBRUNIF(1, sc->rx_mbuf_alloc--);
3902157642Sps		}
3903157642Sps	}
3904157642Sps
3905157642Sps	/* Clear each RX chain page. */
3906157642Sps	for (i = 0; i < RX_PAGES; i++)
3907157642Sps		bzero((char *)sc->rx_bd_chain[i], BCE_RX_CHAIN_PAGE_SZ);
3908157642Sps
3909157642Sps	/* Check if we lost any mbufs in the process. */
3910157642Sps	DBRUNIF((sc->rx_mbuf_alloc),
3911157642Sps		BCE_PRINTF(sc, "%s(%d): Memory leak! Lost %d mbufs from rx chain!\n",
3912157642Sps			__FILE__, __LINE__, sc->rx_mbuf_alloc));
3913157642Sps
3914157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
3915157642Sps}
3916157642Sps
3917157642Sps
3918157642Sps/****************************************************************************/
3919157642Sps/* Set media options.                                                       */
3920157642Sps/*                                                                          */
3921157642Sps/* Returns:                                                                 */
3922157642Sps/*   0 for success, positive value for failure.                             */
3923157642Sps/****************************************************************************/
3924157642Spsstatic int
3925157642Spsbce_ifmedia_upd(struct ifnet *ifp)
3926157642Sps{
3927157642Sps	struct bce_softc *sc;
3928157642Sps	struct mii_data *mii;
3929157642Sps	struct ifmedia *ifm;
3930157642Sps	int rc = 0;
3931157642Sps
3932157642Sps	sc = ifp->if_softc;
3933157642Sps	ifm = &sc->bce_ifmedia;
3934157642Sps
3935157642Sps	/* DRC - ToDo: Add SerDes support. */
3936157642Sps
3937157642Sps	mii = device_get_softc(sc->bce_miibus);
3938157642Sps	sc->bce_link = 0;
3939157642Sps	if (mii->mii_instance) {
3940157642Sps		struct mii_softc *miisc;
3941157642Sps		for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
3942157642Sps		    miisc = LIST_NEXT(miisc, mii_list))
3943157642Sps			mii_phy_reset(miisc);
3944157642Sps	}
3945157642Sps	mii_mediachg(mii);
3946157642Sps
3947157642Sps	return(rc);
3948157642Sps}
3949157642Sps
3950157642Sps
3951157642Sps/****************************************************************************/
3952157642Sps/* Reports current media status.                                            */
3953157642Sps/*                                                                          */
3954157642Sps/* Returns:                                                                 */
3955157642Sps/*   Nothing.                                                               */
3956157642Sps/****************************************************************************/
3957157642Spsstatic void
3958157642Spsbce_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
3959157642Sps{
3960157642Sps	struct bce_softc *sc;
3961157642Sps	struct mii_data *mii;
3962157642Sps
3963157642Sps	sc = ifp->if_softc;
3964157642Sps
3965157642Sps	BCE_LOCK(sc);
3966157642Sps
3967157642Sps	mii = device_get_softc(sc->bce_miibus);
3968157642Sps
3969157642Sps	/* DRC - ToDo: Add SerDes support. */
3970157642Sps
3971157642Sps	mii_pollstat(mii);
3972157642Sps	ifmr->ifm_active = mii->mii_media_active;
3973157642Sps	ifmr->ifm_status = mii->mii_media_status;
3974157642Sps
3975157642Sps	BCE_UNLOCK(sc);
3976157642Sps}
3977157642Sps
3978157642Sps
3979157642Sps/****************************************************************************/
3980157642Sps/* Handles PHY generated interrupt events.                                  */
3981157642Sps/*                                                                          */
3982157642Sps/* Returns:                                                                 */
3983157642Sps/*   Nothing.                                                               */
3984157642Sps/****************************************************************************/
3985157642Spsstatic void
3986157642Spsbce_phy_intr(struct bce_softc *sc)
3987157642Sps{
3988157642Sps	u32 new_link_state, old_link_state;
3989157642Sps
3990157642Sps	new_link_state = sc->status_block->status_attn_bits &
3991157642Sps		STATUS_ATTN_BITS_LINK_STATE;
3992157642Sps	old_link_state = sc->status_block->status_attn_bits_ack &
3993157642Sps		STATUS_ATTN_BITS_LINK_STATE;
3994157642Sps
3995157642Sps	/* Handle any changes if the link state has changed. */
3996157642Sps	if (new_link_state != old_link_state) {
3997157642Sps
3998157642Sps		DBRUN(BCE_VERBOSE_INTR, bce_dump_status_block(sc));
3999157642Sps
4000157642Sps		sc->bce_link = 0;
4001157642Sps		callout_stop(&sc->bce_stat_ch);
4002157642Sps		bce_tick_locked(sc);
4003157642Sps
4004157642Sps		/* Update the status_attn_bits_ack field in the status block. */
4005157642Sps		if (new_link_state) {
4006157642Sps			REG_WR(sc, BCE_PCICFG_STATUS_BIT_SET_CMD,
4007157642Sps				STATUS_ATTN_BITS_LINK_STATE);
4008157642Sps			DBPRINT(sc, BCE_INFO, "Link is now UP.\n");
4009157642Sps		}
4010157642Sps		else {
4011157642Sps			REG_WR(sc, BCE_PCICFG_STATUS_BIT_CLEAR_CMD,
4012157642Sps				STATUS_ATTN_BITS_LINK_STATE);
4013157642Sps			DBPRINT(sc, BCE_INFO, "Link is now DOWN.\n");
4014157642Sps		}
4015157642Sps
4016157642Sps	}
4017157642Sps
4018157642Sps	/* Acknowledge the link change interrupt. */
4019157642Sps	REG_WR(sc, BCE_EMAC_STATUS, BCE_EMAC_STATUS_LINK_CHANGE);
4020157642Sps}
4021157642Sps
4022157642Sps
4023157642Sps/****************************************************************************/
4024157642Sps/* Handles received frame interrupt events.                                 */
4025157642Sps/*                                                                          */
4026157642Sps/* Returns:                                                                 */
4027157642Sps/*   Nothing.                                                               */
4028157642Sps/****************************************************************************/
4029157642Spsstatic void
4030157642Spsbce_rx_intr(struct bce_softc *sc)
4031157642Sps{
4032157642Sps	struct status_block *sblk = sc->status_block;
4033157642Sps	struct ifnet *ifp = sc->bce_ifp;
4034157642Sps	u16 hw_cons, sw_cons, sw_chain_cons, sw_prod, sw_chain_prod;
4035157642Sps	u32 sw_prod_bseq;
4036157642Sps	struct l2_fhdr *l2fhdr;
4037157642Sps
4038157642Sps	DBRUNIF(1, sc->rx_interrupts++);
4039157642Sps
4040157642Sps	/* Prepare the RX chain pages to be accessed by the host CPU. */
4041157642Sps	for (int i = 0; i < RX_PAGES; i++)
4042157642Sps		bus_dmamap_sync(sc->rx_bd_chain_tag,
4043157642Sps		    sc->rx_bd_chain_map[i], BUS_DMASYNC_POSTWRITE);
4044157642Sps
4045157642Sps	/* Get the hardware's view of the RX consumer index. */
4046157642Sps	hw_cons = sc->hw_rx_cons = sblk->status_rx_quick_consumer_index0;
4047157642Sps	if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
4048157642Sps		hw_cons++;
4049157642Sps
4050157642Sps	/* Get working copies of the driver's view of the RX indices. */
4051157642Sps	sw_cons = sc->rx_cons;
4052157642Sps	sw_prod = sc->rx_prod;
4053157642Sps	sw_prod_bseq = sc->rx_prod_bseq;
4054157642Sps
4055157642Sps	DBPRINT(sc, BCE_INFO_RECV, "%s(enter): sw_prod = 0x%04X, "
4056157642Sps		"sw_cons = 0x%04X, sw_prod_bseq = 0x%08X\n",
4057157642Sps		__FUNCTION__, sw_prod, sw_cons,
4058157642Sps		sw_prod_bseq);
4059157642Sps
4060157642Sps	/* Prevent speculative reads from getting ahead of the status block. */
4061157642Sps	bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
4062157642Sps		BUS_SPACE_BARRIER_READ);
4063157642Sps
4064157642Sps	DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
4065157642Sps		sc->rx_low_watermark = sc->free_rx_bd);
4066157642Sps
4067157642Sps	/*
4068157642Sps	 * Scan through the receive chain as long
4069157642Sps	 * as there is work to do.
4070157642Sps	 */
4071157642Sps	while (sw_cons != hw_cons) {
4072157642Sps		struct mbuf *m;
4073157642Sps		struct rx_bd *rxbd;
4074157642Sps		unsigned int len;
4075157642Sps		u32 status;
4076157642Sps
4077157642Sps		/* Convert the producer/consumer indices to an actual rx_bd index. */
4078157642Sps		sw_chain_cons = RX_CHAIN_IDX(sw_cons);
4079157642Sps		sw_chain_prod = RX_CHAIN_IDX(sw_prod);
4080157642Sps
4081157642Sps		/* Get the used rx_bd. */
4082157642Sps		rxbd = &sc->rx_bd_chain[RX_PAGE(sw_chain_cons)][RX_IDX(sw_chain_cons)];
4083157642Sps		sc->free_rx_bd++;
4084157642Sps
4085157642Sps		DBRUN(BCE_VERBOSE_RECV,
4086157642Sps			BCE_PRINTF(sc, "%s(): ", __FUNCTION__);
4087157642Sps			bce_dump_rxbd(sc, sw_chain_cons, rxbd));
4088157642Sps
4089157642Sps#ifdef DEVICE_POLLING
4090157642Sps		if (ifp->if_capenable & IFCAP_POLLING) {
4091157642Sps			if (sc->bce_rxcycles <= 0)
4092157642Sps				break;
4093157724Sru			sc->bce_rxcycles--;
4094157642Sps		}
4095157642Sps#endif
4096157642Sps
4097157642Sps		/* The mbuf is stored with the last rx_bd entry of a packet. */
4098157642Sps		if (sc->rx_mbuf_ptr[sw_chain_cons] != NULL) {
4099157642Sps
4100157642Sps			/* Validate that this is the last rx_bd. */
4101157642Sps			DBRUNIF((!(rxbd->rx_bd_flags & RX_BD_FLAGS_END)),
4102157642Sps				BCE_PRINTF(sc, "%s(%d): Unexpected mbuf found in rx_bd[0x%04X]!\n",
4103157642Sps				__FILE__, __LINE__, sw_chain_cons);
4104157642Sps				bce_breakpoint(sc));
4105157642Sps
4106157642Sps			/* DRC - ToDo: If the received packet is small, say less */
4107157642Sps			/*             than 128 bytes, allocate a new mbuf here, */
4108157642Sps			/*             copy the data to that mbuf, and recycle   */
4109157642Sps			/*             the mapped jumbo frame.                   */
4110157642Sps
4111157642Sps			/* Unmap the mbuf from DMA space. */
4112157642Sps			bus_dmamap_sync(sc->rx_mbuf_tag,
4113157642Sps			    sc->rx_mbuf_map[sw_chain_cons],
4114157642Sps		    	BUS_DMASYNC_POSTREAD);
4115157642Sps			bus_dmamap_unload(sc->rx_mbuf_tag,
4116157642Sps			    sc->rx_mbuf_map[sw_chain_cons]);
4117157642Sps
4118157642Sps			/* Remove the mbuf from the driver's chain. */
4119157642Sps			m = sc->rx_mbuf_ptr[sw_chain_cons];
4120157642Sps			sc->rx_mbuf_ptr[sw_chain_cons] = NULL;
4121157642Sps
4122157642Sps			/*
4123157642Sps			 * Frames received on the NetXteme II are prepended
4124157642Sps			 * with the l2_fhdr structure which provides status
4125157642Sps			 * information about the received frame (including
4126157642Sps			 * VLAN tags and checksum info) and are also
4127157642Sps			 * automatically adjusted to align the IP header
4128157642Sps			 * (i.e. two null bytes are inserted before the
4129157642Sps			 * Ethernet header).
4130157642Sps			 */
4131157642Sps			l2fhdr = mtod(m, struct l2_fhdr *);
4132157642Sps
4133157642Sps			len    = l2fhdr->l2_fhdr_pkt_len;
4134157642Sps			status = l2fhdr->l2_fhdr_status;
4135157642Sps
4136157642Sps			DBRUNIF(DB_RANDOMTRUE(bce_debug_l2fhdr_status_check),
4137157642Sps				BCE_PRINTF(sc, "Simulating l2_fhdr status error.\n");
4138157642Sps				status = status | L2_FHDR_ERRORS_PHY_DECODE);
4139157642Sps
4140157642Sps			/* Watch for unusual sized frames. */
4141157642Sps			DBRUNIF(((len < BCE_MIN_MTU) || (len > BCE_MAX_JUMBO_ETHER_MTU_VLAN)),
4142157642Sps				BCE_PRINTF(sc, "%s(%d): Unusual frame size found. "
4143157642Sps					"Min(%d), Actual(%d), Max(%d)\n",
4144157642Sps					__FILE__, __LINE__, (int) BCE_MIN_MTU,
4145157642Sps					len, (int) BCE_MAX_JUMBO_ETHER_MTU_VLAN);
4146157642Sps				bce_dump_mbuf(sc, m);
4147157642Sps		 		bce_breakpoint(sc));
4148157642Sps
4149157642Sps			len -= ETHER_CRC_LEN;
4150157642Sps
4151157642Sps			/* Check the received frame for errors. */
4152157642Sps			if (status &  (L2_FHDR_ERRORS_BAD_CRC |
4153157642Sps				L2_FHDR_ERRORS_PHY_DECODE | L2_FHDR_ERRORS_ALIGNMENT |
4154157642Sps				L2_FHDR_ERRORS_TOO_SHORT  | L2_FHDR_ERRORS_GIANT_FRAME)) {
4155157642Sps
4156157642Sps				ifp->if_ierrors++;
4157157642Sps				DBRUNIF(1, sc->l2fhdr_status_errors++);
4158157642Sps
4159157642Sps				/* Reuse the mbuf for a new frame. */
4160157642Sps				if (bce_get_buf(sc, m, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) {
4161157642Sps
4162157642Sps					DBRUNIF(1, bce_breakpoint(sc));
4163157642Sps					panic("bce%d: Can't reuse RX mbuf!\n", sc->bce_unit);
4164157642Sps
4165157642Sps				}
4166157642Sps				goto bce_rx_int_next_rx;
4167157642Sps			}
4168157642Sps
4169157642Sps			/*
4170157642Sps			 * Get a new mbuf for the rx_bd.   If no new
4171157642Sps			 * mbufs are available then reuse the current mbuf,
4172157642Sps			 * log an ierror on the interface, and generate
4173157642Sps			 * an error in the system log.
4174157642Sps			 */
4175157642Sps			if (bce_get_buf(sc, NULL, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) {
4176157642Sps
4177157642Sps				DBRUN(BCE_WARN,
4178157642Sps					BCE_PRINTF(sc, "%s(%d): Failed to allocate "
4179157642Sps					"new mbuf, incoming frame dropped!\n",
4180157642Sps					__FILE__, __LINE__));
4181157642Sps
4182157642Sps				ifp->if_ierrors++;
4183157642Sps
4184157642Sps				/* Try and reuse the exisitng mbuf. */
4185157642Sps				if (bce_get_buf(sc, m, &sw_prod, &sw_chain_prod, &sw_prod_bseq)) {
4186157642Sps
4187157642Sps					DBRUNIF(1, bce_breakpoint(sc));
4188157642Sps					panic("bce%d: Double mbuf allocation failure!", sc->bce_unit);
4189157642Sps
4190157642Sps				}
4191157642Sps				goto bce_rx_int_next_rx;
4192157642Sps			}
4193157642Sps
4194157642Sps			/* Skip over the l2_fhdr when passing the data up the stack. */
4195157642Sps			m_adj(m, sizeof(struct l2_fhdr) + ETHER_ALIGN);
4196157642Sps
4197157642Sps			/* Adjust the packet length to match the received data. */
4198157642Sps			m->m_pkthdr.len = m->m_len = len;
4199157642Sps
4200157642Sps			/* Send the packet to the appropriate interface. */
4201157642Sps			m->m_pkthdr.rcvif = ifp;
4202157642Sps
4203157642Sps			DBRUN(BCE_VERBOSE_RECV,
4204157642Sps				struct ether_header *eh;
4205157642Sps				eh = mtod(m, struct ether_header *);
4206157642Sps				BCE_PRINTF(sc, "%s(): to: %6D, from: %6D, type: 0x%04X\n",
4207157642Sps					__FUNCTION__, eh->ether_dhost, ":",
4208157642Sps					eh->ether_shost, ":", htons(eh->ether_type)));
4209157642Sps
4210157642Sps			/* Validate the checksum if offload enabled. */
4211157642Sps			if (ifp->if_capenable & IFCAP_RXCSUM) {
4212157642Sps
4213157642Sps				/* Check for an IP datagram. */
4214157642Sps				if (status & L2_FHDR_STATUS_IP_DATAGRAM) {
4215157642Sps					m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
4216157642Sps
4217157642Sps					/* Check if the IP checksum is valid. */
4218157642Sps					if ((l2fhdr->l2_fhdr_ip_xsum ^ 0xffff) == 0)
4219157642Sps						m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
4220157642Sps					else
4221157642Sps						DBPRINT(sc, BCE_WARN_SEND,
4222157642Sps							"%s(): Invalid IP checksum = 0x%04X!\n",
4223157642Sps							__FUNCTION__, l2fhdr->l2_fhdr_ip_xsum);
4224157642Sps				}
4225157642Sps
4226157642Sps				/* Check for a valid TCP/UDP frame. */
4227157642Sps				if (status & (L2_FHDR_STATUS_TCP_SEGMENT |
4228157642Sps					L2_FHDR_STATUS_UDP_DATAGRAM)) {
4229157642Sps
4230157642Sps					/* Check for a good TCP/UDP checksum. */
4231157642Sps					if ((status & (L2_FHDR_ERRORS_TCP_XSUM |
4232157642Sps						      L2_FHDR_ERRORS_UDP_XSUM)) == 0) {
4233157642Sps						m->m_pkthdr.csum_data =
4234157642Sps						    l2fhdr->l2_fhdr_tcp_udp_xsum;
4235157642Sps						m->m_pkthdr.csum_flags |= (CSUM_DATA_VALID
4236157642Sps							| CSUM_PSEUDO_HDR);
4237157642Sps					} else
4238157642Sps						DBPRINT(sc, BCE_WARN_SEND,
4239157642Sps							"%s(): Invalid TCP/UDP checksum = 0x%04X!\n",
4240157642Sps							__FUNCTION__, l2fhdr->l2_fhdr_tcp_udp_xsum);
4241157642Sps				}
4242157642Sps			}
4243157642Sps
4244157642Sps
4245157642Sps			/*
4246157642Sps			 * If we received a packet with a vlan tag,
4247157642Sps			 * attach that information to the packet.
4248157642Sps			 */
4249157642Sps			if (status & L2_FHDR_STATUS_L2_VLAN_TAG) {
4250157642Sps				DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): VLAN tag = 0x%04X\n",
4251157642Sps					__FUNCTION__, l2fhdr->l2_fhdr_vlan_tag);
4252157642Sps#if __FreeBSD_version < 700000
4253157642Sps				VLAN_INPUT_TAG(ifp, m, l2fhdr->l2_fhdr_vlan_tag, continue);
4254157642Sps#else
4255157642Sps				VLAN_INPUT_TAG(ifp, m, l2fhdr->l2_fhdr_vlan_tag);
4256157642Sps				if (m == NULL)
4257157642Sps					continue;
4258157642Sps#endif
4259157642Sps			}
4260157642Sps
4261157642Sps			/* Pass the mbuf off to the upper layers. */
4262157642Sps			ifp->if_ipackets++;
4263157642Sps			DBPRINT(sc, BCE_VERBOSE_RECV, "%s(): Passing received frame up.\n",
4264157642Sps				__FUNCTION__);
4265157642Sps			BCE_UNLOCK(sc);
4266157642Sps			(*ifp->if_input)(ifp, m);
4267157642Sps			DBRUNIF(1, sc->rx_mbuf_alloc--);
4268157642Sps			BCE_LOCK(sc);
4269157642Sps
4270157642Spsbce_rx_int_next_rx:
4271157642Sps			sw_prod = NEXT_RX_BD(sw_prod);
4272157642Sps		}
4273157642Sps
4274157642Sps		sw_cons = NEXT_RX_BD(sw_cons);
4275157642Sps
4276157642Sps		/* Refresh hw_cons to see if there's new work */
4277157642Sps		if (sw_cons == hw_cons) {
4278157642Sps			hw_cons = sc->hw_rx_cons = sblk->status_rx_quick_consumer_index0;
4279157642Sps			if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
4280157642Sps				hw_cons++;
4281157642Sps		}
4282157642Sps
4283157642Sps		/* Prevent speculative reads from getting ahead of the status block. */
4284157642Sps		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
4285157642Sps			BUS_SPACE_BARRIER_READ);
4286157642Sps	}
4287157642Sps
4288157642Sps	for (int i = 0; i < RX_PAGES; i++)
4289157642Sps		bus_dmamap_sync(sc->rx_bd_chain_tag,
4290157642Sps		    sc->rx_bd_chain_map[i], BUS_DMASYNC_PREWRITE);
4291157642Sps
4292157642Sps	sc->rx_cons = sw_cons;
4293157642Sps	sc->rx_prod = sw_prod;
4294157642Sps	sc->rx_prod_bseq = sw_prod_bseq;
4295157642Sps
4296157642Sps	REG_WR16(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BDIDX, sc->rx_prod);
4297157642Sps	REG_WR(sc, MB_RX_CID_ADDR + BCE_L2CTX_HOST_BSEQ, sc->rx_prod_bseq);
4298157642Sps
4299157642Sps	DBPRINT(sc, BCE_INFO_RECV, "%s(exit): rx_prod = 0x%04X, "
4300157642Sps		"rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n",
4301157642Sps		__FUNCTION__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq);
4302157642Sps}
4303157642Sps
4304157642Sps
4305157642Sps/****************************************************************************/
4306157642Sps/* Handles transmit completion interrupt events.                            */
4307157642Sps/*                                                                          */
4308157642Sps/* Returns:                                                                 */
4309157642Sps/*   Nothing.                                                               */
4310157642Sps/****************************************************************************/
4311157642Spsstatic void
4312157642Spsbce_tx_intr(struct bce_softc *sc)
4313157642Sps{
4314157642Sps	struct status_block *sblk = sc->status_block;
4315157642Sps	struct ifnet *ifp = sc->bce_ifp;
4316157642Sps	u16 hw_tx_cons, sw_tx_cons, sw_tx_chain_cons;
4317157642Sps
4318157642Sps	BCE_LOCK_ASSERT(sc);
4319157642Sps
4320157642Sps	DBRUNIF(1, sc->tx_interrupts++);
4321157642Sps
4322157642Sps	/* Get the hardware's view of the TX consumer index. */
4323157642Sps	hw_tx_cons = sc->hw_tx_cons = sblk->status_tx_quick_consumer_index0;
4324157642Sps
4325157642Sps	/* Skip to the next entry if this is a chain page pointer. */
4326157642Sps	if ((hw_tx_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
4327157642Sps		hw_tx_cons++;
4328157642Sps
4329157642Sps	sw_tx_cons = sc->tx_cons;
4330157642Sps
4331157642Sps	/* Prevent speculative reads from getting ahead of the status block. */
4332157642Sps	bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
4333157642Sps		BUS_SPACE_BARRIER_READ);
4334157642Sps
4335157642Sps	/* Cycle through any completed TX chain page entries. */
4336157642Sps	while (sw_tx_cons != hw_tx_cons) {
4337157642Sps#ifdef BCE_DEBUG
4338157642Sps		struct tx_bd *txbd = NULL;
4339157642Sps#endif
4340157642Sps		sw_tx_chain_cons = TX_CHAIN_IDX(sw_tx_cons);
4341157642Sps
4342157642Sps		DBPRINT(sc, BCE_INFO_SEND,
4343157642Sps			"%s(): hw_tx_cons = 0x%04X, sw_tx_cons = 0x%04X, "
4344157642Sps			"sw_tx_chain_cons = 0x%04X\n",
4345157642Sps			__FUNCTION__, hw_tx_cons, sw_tx_cons, sw_tx_chain_cons);
4346157642Sps
4347157642Sps		DBRUNIF((sw_tx_chain_cons > MAX_TX_BD),
4348157642Sps			BCE_PRINTF(sc, "%s(%d): TX chain consumer out of range! "
4349157642Sps				" 0x%04X > 0x%04X\n",
4350157642Sps				__FILE__, __LINE__, sw_tx_chain_cons,
4351157642Sps				(int) MAX_TX_BD);
4352157642Sps			bce_breakpoint(sc));
4353157642Sps
4354157642Sps		DBRUNIF(1,
4355157642Sps			txbd = &sc->tx_bd_chain[TX_PAGE(sw_tx_chain_cons)]
4356157642Sps				[TX_IDX(sw_tx_chain_cons)]);
4357157642Sps
4358157642Sps		DBRUNIF((txbd == NULL),
4359157642Sps			BCE_PRINTF(sc, "%s(%d): Unexpected NULL tx_bd[0x%04X]!\n",
4360157642Sps				__FILE__, __LINE__, sw_tx_chain_cons);
4361157642Sps			bce_breakpoint(sc));
4362157642Sps
4363157642Sps		DBRUN(BCE_INFO_SEND,
4364157642Sps			BCE_PRINTF(sc, "%s(): ", __FUNCTION__);
4365157642Sps			bce_dump_txbd(sc, sw_tx_chain_cons, txbd));
4366157642Sps
4367157642Sps		/*
4368157642Sps		 * Free the associated mbuf. Remember
4369157642Sps		 * that only the last tx_bd of a packet
4370157642Sps		 * has an mbuf pointer and DMA map.
4371157642Sps		 */
4372157642Sps		if (sc->tx_mbuf_ptr[sw_tx_chain_cons] != NULL) {
4373157642Sps
4374157642Sps			/* Validate that this is the last tx_bd. */
4375157642Sps			DBRUNIF((!(txbd->tx_bd_vlan_tag_flags & TX_BD_FLAGS_END)),
4376157642Sps				BCE_PRINTF(sc, "%s(%d): tx_bd END flag not set but "
4377157642Sps				"txmbuf == NULL!\n", __FILE__, __LINE__);
4378157642Sps				bce_breakpoint(sc));
4379157642Sps
4380157642Sps			DBRUN(BCE_INFO_SEND,
4381157642Sps				BCE_PRINTF(sc, "%s(): Unloading map/freeing mbuf "
4382157642Sps					"from tx_bd[0x%04X]\n", __FUNCTION__, sw_tx_chain_cons));
4383157642Sps
4384157642Sps			/* Unmap the mbuf. */
4385157642Sps			bus_dmamap_unload(sc->tx_mbuf_tag,
4386157642Sps			    sc->tx_mbuf_map[sw_tx_chain_cons]);
4387157642Sps
4388157642Sps			/* Free the mbuf. */
4389157642Sps			m_freem(sc->tx_mbuf_ptr[sw_tx_chain_cons]);
4390157642Sps			sc->tx_mbuf_ptr[sw_tx_chain_cons] = NULL;
4391157642Sps			DBRUNIF(1, sc->tx_mbuf_alloc--);
4392157642Sps
4393157642Sps			ifp->if_opackets++;
4394157642Sps		}
4395157642Sps
4396157642Sps		sc->used_tx_bd--;
4397157642Sps		sw_tx_cons = NEXT_TX_BD(sw_tx_cons);
4398157642Sps
4399157642Sps		/* Refresh hw_cons to see if there's new work. */
4400157642Sps		hw_tx_cons = sc->hw_tx_cons = sblk->status_tx_quick_consumer_index0;
4401157642Sps		if ((hw_tx_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
4402157642Sps			hw_tx_cons++;
4403157642Sps
4404157642Sps		/* Prevent speculative reads from getting ahead of the status block. */
4405157642Sps		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
4406157642Sps			BUS_SPACE_BARRIER_READ);
4407157642Sps	}
4408157642Sps
4409157642Sps	/* Clear the TX timeout timer. */
4410157642Sps	ifp->if_timer = 0;
4411157642Sps
4412157642Sps	/* Clear the tx hardware queue full flag. */
4413157642Sps	if ((sc->used_tx_bd + BCE_TX_SLACK_SPACE) < USABLE_TX_BD) {
4414157642Sps		DBRUNIF((ifp->if_drv_flags & IFF_DRV_OACTIVE),
4415157642Sps			BCE_PRINTF(sc, "%s(): TX chain is open for business! Used tx_bd = %d\n",
4416157642Sps				__FUNCTION__, sc->used_tx_bd));
4417157642Sps		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
4418157642Sps	}
4419157642Sps
4420157642Sps	sc->tx_cons = sw_tx_cons;
4421157642Sps}
4422157642Sps
4423157642Sps
4424157642Sps/****************************************************************************/
4425157642Sps/* Disables interrupt generation.                                           */
4426157642Sps/*                                                                          */
4427157642Sps/* Returns:                                                                 */
4428157642Sps/*   Nothing.                                                               */
4429157642Sps/****************************************************************************/
4430157642Spsstatic void
4431157642Spsbce_disable_intr(struct bce_softc *sc)
4432157642Sps{
4433157642Sps	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
4434157642Sps	       BCE_PCICFG_INT_ACK_CMD_MASK_INT);
4435157642Sps	REG_RD(sc, BCE_PCICFG_INT_ACK_CMD);
4436157642Sps}
4437157642Sps
4438157642Sps
4439157642Sps/****************************************************************************/
4440157642Sps/* Enables interrupt generation.                                            */
4441157642Sps/*                                                                          */
4442157642Sps/* Returns:                                                                 */
4443157642Sps/*   Nothing.                                                               */
4444157642Sps/****************************************************************************/
4445157642Spsstatic void
4446157642Spsbce_enable_intr(struct bce_softc *sc)
4447157642Sps{
4448157642Sps	u32 val;
4449157642Sps
4450157642Sps	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
4451157642Sps	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID |
4452157642Sps	       BCE_PCICFG_INT_ACK_CMD_MASK_INT | sc->last_status_idx);
4453157642Sps
4454157642Sps	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
4455157642Sps	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx);
4456157642Sps
4457157642Sps	val = REG_RD(sc, BCE_HC_COMMAND);
4458157642Sps	REG_WR(sc, BCE_HC_COMMAND, val | BCE_HC_COMMAND_COAL_NOW);
4459157642Sps}
4460157642Sps
4461157642Sps
4462157642Sps/****************************************************************************/
4463157642Sps/* Handles controller initialization.                                       */
4464157642Sps/*                                                                          */
4465157642Sps/* Must be called from a locked routine.                                    */
4466157642Sps/*                                                                          */
4467157642Sps/* Returns:                                                                 */
4468157642Sps/*   Nothing.                                                               */
4469157642Sps/****************************************************************************/
4470157642Spsstatic void
4471157642Spsbce_init_locked(struct bce_softc *sc)
4472157642Sps{
4473157642Sps	struct ifnet *ifp;
4474157642Sps	u32 ether_mtu;
4475157642Sps
4476157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
4477157642Sps
4478157642Sps	BCE_LOCK_ASSERT(sc);
4479157642Sps
4480157642Sps	ifp = sc->bce_ifp;
4481157642Sps
4482157642Sps	/* Check if the driver is still running and bail out if it is. */
4483157642Sps	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
4484157642Sps		goto bce_init_locked_exit;
4485157642Sps
4486157642Sps	bce_stop(sc);
4487157642Sps
4488157642Sps	if (bce_reset(sc, BCE_DRV_MSG_CODE_RESET)) {
4489157642Sps		BCE_PRINTF(sc, "%s(%d): Controller reset failed!\n",
4490157642Sps			__FILE__, __LINE__);
4491157642Sps		goto bce_init_locked_exit;
4492157642Sps	}
4493157642Sps
4494157642Sps	if (bce_chipinit(sc)) {
4495157642Sps		BCE_PRINTF(sc, "%s(%d): Controller initialization failed!\n",
4496157642Sps			__FILE__, __LINE__);
4497157642Sps		goto bce_init_locked_exit;
4498157642Sps	}
4499157642Sps
4500157642Sps	if (bce_blockinit(sc)) {
4501157642Sps		BCE_PRINTF(sc, "%s(%d): Block initialization failed!\n",
4502157642Sps			__FILE__, __LINE__);
4503157642Sps		goto bce_init_locked_exit;
4504157642Sps	}
4505157642Sps
4506157642Sps	/* Load our MAC address. */
4507157642Sps	bcopy(IF_LLADDR(sc->bce_ifp), sc->eaddr, ETHER_ADDR_LEN);
4508157642Sps	bce_set_mac_addr(sc);
4509157642Sps
4510157642Sps	/* Calculate and program the Ethernet MTU size. */
4511157642Sps	ether_mtu = ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN + ifp->if_mtu +
4512157642Sps		ETHER_CRC_LEN;
4513157642Sps
4514157642Sps	DBPRINT(sc, BCE_INFO, "%s(): setting mtu = %d\n",__FUNCTION__, ether_mtu);
4515157642Sps
4516157642Sps	/*
4517157642Sps	 * Program the mtu, enabling jumbo frame
4518157642Sps	 * support if necessary.  Also set the mbuf
4519157642Sps	 * allocation count for RX frames.
4520157642Sps	 */
4521157642Sps	if (ether_mtu > ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) {
4522157642Sps		REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu |
4523157642Sps			BCE_EMAC_RX_MTU_SIZE_JUMBO_ENA);
4524157642Sps		sc->mbuf_alloc_size = MJUM9BYTES;
4525157642Sps	} else {
4526157642Sps		REG_WR(sc, BCE_EMAC_RX_MTU_SIZE, ether_mtu);
4527157642Sps		sc->mbuf_alloc_size = MCLBYTES;
4528157642Sps	}
4529157642Sps
4530157642Sps	/* Calculate the RX Ethernet frame size for rx_bd's. */
4531157642Sps	sc->max_frame_size = sizeof(struct l2_fhdr) + 2 + ether_mtu + 8;
4532157642Sps
4533157642Sps	DBPRINT(sc, BCE_INFO,
4534157642Sps		"%s(): mclbytes = %d, mbuf_alloc_size = %d, "
4535157642Sps		"max_frame_size = %d\n",
4536157642Sps		__FUNCTION__, (int) MCLBYTES, sc->mbuf_alloc_size, sc->max_frame_size);
4537157642Sps
4538157642Sps	/* Program appropriate promiscuous/multicast filtering. */
4539157642Sps	bce_set_rx_mode(sc);
4540157642Sps
4541157642Sps	/* Init RX buffer descriptor chain. */
4542157642Sps	bce_init_rx_chain(sc);
4543157642Sps
4544157642Sps	/* Init TX buffer descriptor chain. */
4545157642Sps	bce_init_tx_chain(sc);
4546157642Sps
4547157642Sps#ifdef DEVICE_POLLING
4548157642Sps	/* Disable interrupts if we are polling. */
4549157642Sps	if (ifp->if_capenable & IFCAP_POLLING) {
4550157642Sps		bce_disable_intr(sc);
4551157642Sps
4552157642Sps		REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
4553157642Sps			(1 << 16) | sc->bce_rx_quick_cons_trip);
4554157642Sps		REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
4555157642Sps			(1 << 16) | sc->bce_tx_quick_cons_trip);
4556157642Sps	} else
4557157642Sps#endif
4558157642Sps	/* Enable host interrupts. */
4559157642Sps	bce_enable_intr(sc);
4560157642Sps
4561157642Sps	bce_ifmedia_upd(ifp);
4562157642Sps
4563157642Sps	ifp->if_drv_flags |= IFF_DRV_RUNNING;
4564157642Sps	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
4565157642Sps
4566157642Sps	callout_reset(&sc->bce_stat_ch, hz, bce_tick, sc);
4567157642Sps
4568157642Spsbce_init_locked_exit:
4569157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
4570157642Sps
4571157642Sps	return;
4572157642Sps}
4573157642Sps
4574157642Sps
4575157642Sps/****************************************************************************/
4576157642Sps/* Handles controller initialization when called from an unlocked routine.  */
4577157642Sps/*                                                                          */
4578157642Sps/* Returns:                                                                 */
4579157642Sps/*   Nothing.                                                               */
4580157642Sps/****************************************************************************/
4581157642Spsstatic void
4582157642Spsbce_init(void *xsc)
4583157642Sps{
4584157642Sps	struct bce_softc *sc = xsc;
4585157642Sps
4586157642Sps	BCE_LOCK(sc);
4587157642Sps	bce_init_locked(sc);
4588157642Sps	BCE_UNLOCK(sc);
4589157642Sps}
4590157642Sps
4591157642Sps
4592157642Sps/****************************************************************************/
4593157642Sps/* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */
4594157642Sps/* memory visible to the controller.                                        */
4595157642Sps/*                                                                          */
4596157642Sps/* Returns:                                                                 */
4597157642Sps/*   0 for success, positive value for failure.                             */
4598157642Sps/****************************************************************************/
4599157642Spsstatic int
4600157642Spsbce_tx_encap(struct bce_softc *sc, struct mbuf *m_head, u16 *prod,
4601157642Sps	u16 *chain_prod, u32 *prod_bseq)
4602157642Sps{
4603157642Sps	u32 vlan_tag_flags = 0;
4604157642Sps	struct m_tag *mtag;
4605157642Sps	struct bce_dmamap_arg map_arg;
4606157642Sps	bus_dmamap_t map;
4607157642Sps	int i, error, rc = 0;
4608157642Sps
4609157642Sps	/* Transfer any checksum offload flags to the bd. */
4610157642Sps	if (m_head->m_pkthdr.csum_flags) {
4611157642Sps		if (m_head->m_pkthdr.csum_flags & CSUM_IP)
4612157642Sps			vlan_tag_flags |= TX_BD_FLAGS_IP_CKSUM;
4613157642Sps		if (m_head->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP))
4614157642Sps			vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
4615157642Sps	}
4616157642Sps
4617157642Sps	/* Transfer any VLAN tags to the bd. */
4618157642Sps	mtag = VLAN_OUTPUT_TAG(sc->bce_ifp, m_head);
4619157642Sps	if (mtag != NULL)
4620157642Sps		vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG |
4621157642Sps			(VLAN_TAG_VALUE(mtag) << 16));
4622157642Sps
4623157642Sps	/* Map the mbuf into DMAable memory. */
4624157642Sps	map = sc->tx_mbuf_map[*chain_prod];
4625157642Sps	map_arg.sc         = sc;
4626157642Sps	map_arg.prod       = *prod;
4627157642Sps	map_arg.chain_prod = *chain_prod;
4628157642Sps	map_arg.prod_bseq  = *prod_bseq;
4629157642Sps	map_arg.tx_flags   = vlan_tag_flags;
4630157642Sps	map_arg.maxsegs    = USABLE_TX_BD - sc->used_tx_bd -
4631157642Sps		BCE_TX_SLACK_SPACE;
4632157642Sps
4633157642Sps	KASSERT(map_arg.maxsegs > 0, ("Invalid TX maxsegs value!"));
4634157642Sps
4635157642Sps	for (i = 0; i < TX_PAGES; i++)
4636157642Sps		map_arg.tx_chain[i] = sc->tx_bd_chain[i];
4637157642Sps
4638157642Sps	/* Map the mbuf into our DMA address space. */
4639157642Sps	error = bus_dmamap_load_mbuf(sc->tx_mbuf_tag, map, m_head,
4640157642Sps	    bce_dma_map_tx_desc, &map_arg, BUS_DMA_NOWAIT);
4641157642Sps
4642157642Sps	if (error || map_arg.maxsegs == 0) {
4643157642Sps		BCE_PRINTF(sc, "%s(%d): Error mapping mbuf into TX chain!\n",
4644157642Sps			__FILE__, __LINE__);
4645157642Sps		rc = ENOBUFS;
4646157642Sps		goto bce_tx_encap_exit;
4647157642Sps	}
4648157642Sps
4649157642Sps	/*
4650157642Sps	 * Ensure that the map for this transmission
4651157642Sps	 * is placed at the array index of the last
4652157642Sps	 * descriptor in this chain.  This is done
4653157642Sps	 * because a single map is used for all
4654157642Sps	 * segments of the mbuf and we don't want to
4655157642Sps	 * delete the map before all of the segments
4656157642Sps	 * have been freed.
4657157642Sps	 */
4658157642Sps	sc->tx_mbuf_map[*chain_prod] =
4659157642Sps		sc->tx_mbuf_map[map_arg.chain_prod];
4660157642Sps	sc->tx_mbuf_map[map_arg.chain_prod] = map;
4661157642Sps	sc->tx_mbuf_ptr[map_arg.chain_prod] = m_head;
4662157642Sps	sc->used_tx_bd += map_arg.maxsegs;
4663157642Sps
4664157642Sps	DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark),
4665157642Sps		sc->tx_hi_watermark = sc->used_tx_bd);
4666157642Sps
4667157642Sps	DBRUNIF(1, sc->tx_mbuf_alloc++);
4668157642Sps
4669157642Sps	DBRUN(BCE_VERBOSE_SEND, bce_dump_tx_mbuf_chain(sc, *chain_prod,
4670157642Sps		map_arg.maxsegs));
4671157642Sps
4672157642Sps	/* prod still points the last used tx_bd at this point. */
4673157642Sps	*prod       = map_arg.prod;
4674157642Sps	*chain_prod = map_arg.chain_prod;
4675157642Sps	*prod_bseq  = map_arg.prod_bseq;
4676157642Sps
4677157642Spsbce_tx_encap_exit:
4678157642Sps
4679157642Sps	return(rc);
4680157642Sps}
4681157642Sps
4682157642Sps
4683157642Sps/****************************************************************************/
4684157642Sps/* Main transmit routine when called from another routine with a lock.      */
4685157642Sps/*                                                                          */
4686157642Sps/* Returns:                                                                 */
4687157642Sps/*   Nothing.                                                               */
4688157642Sps/****************************************************************************/
4689157642Spsstatic void
4690157642Spsbce_start_locked(struct ifnet *ifp)
4691157642Sps{
4692157642Sps	struct bce_softc *sc = ifp->if_softc;
4693157642Sps	struct mbuf *m_head = NULL;
4694157642Sps	int count = 0;
4695157642Sps	u16 tx_prod, tx_chain_prod;
4696157642Sps	u32	tx_prod_bseq;
4697157642Sps
4698157642Sps	/* If there's no link or the transmit queue is empty then just exit. */
4699157642Sps	if (!sc->bce_link || IFQ_DRV_IS_EMPTY(&ifp->if_snd)) {
4700157642Sps		DBPRINT(sc, BCE_INFO_SEND, "%s(): No link or transmit queue empty.\n",
4701157642Sps			__FUNCTION__);
4702157642Sps		goto bce_start_locked_exit;
4703157642Sps	}
4704157642Sps
4705157642Sps	/* prod points to the next free tx_bd. */
4706157642Sps	tx_prod = sc->tx_prod;
4707157642Sps	tx_chain_prod = TX_CHAIN_IDX(tx_prod);
4708157642Sps	tx_prod_bseq = sc->tx_prod_bseq;
4709157642Sps
4710157642Sps	DBPRINT(sc, BCE_INFO_SEND,
4711157642Sps		"%s(): Start: tx_prod = 0x%04X, tx_chain_prod = %04X, "
4712157642Sps		"tx_prod_bseq = 0x%08X\n",
4713157642Sps		__FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq);
4714157642Sps
4715157642Sps	/* Keep adding entries while there is space in the ring. */
4716157642Sps	while(sc->tx_mbuf_ptr[tx_chain_prod] == NULL) {
4717157642Sps
4718157642Sps		/* Check for any frames to send. */
4719157642Sps		IFQ_DRV_DEQUEUE(&ifp->if_snd, m_head);
4720157642Sps		if (m_head == NULL)
4721157642Sps			break;
4722157642Sps
4723157642Sps		/*
4724157642Sps		 * Pack the data into the transmit ring. If we
4725157642Sps		 * don't have room, place the mbuf back at the
4726157642Sps		 * head of the queue and set the OACTIVE flag
4727157642Sps		 * to wait for the NIC to drain the chain.
4728157642Sps		 */
4729157642Sps		if (bce_tx_encap(sc, m_head, &tx_prod, &tx_chain_prod, &tx_prod_bseq)) {
4730157642Sps			IFQ_DRV_PREPEND(&ifp->if_snd, m_head);
4731157642Sps			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
4732157642Sps			DBPRINT(sc, BCE_INFO_SEND,
4733157642Sps				"TX chain is closed for business! Total tx_bd used = %d\n",
4734157642Sps				sc->used_tx_bd);
4735157642Sps			break;
4736157642Sps		}
4737157642Sps
4738157642Sps		count++;
4739157642Sps
4740157642Sps		/* Send a copy of the frame to any BPF listeners. */
4741157642Sps		BPF_MTAP(ifp, m_head);
4742157642Sps
4743157642Sps		tx_prod = NEXT_TX_BD(tx_prod);
4744157642Sps		tx_chain_prod = TX_CHAIN_IDX(tx_prod);
4745157642Sps	}
4746157642Sps
4747157642Sps	if (count == 0) {
4748157642Sps		/* no packets were dequeued */
4749157642Sps		DBPRINT(sc, BCE_VERBOSE_SEND, "%s(): No packets were dequeued\n",
4750157642Sps			__FUNCTION__);
4751157642Sps		goto bce_start_locked_exit;
4752157642Sps	}
4753157642Sps
4754157642Sps	/* Update the driver's counters. */
4755157642Sps	sc->tx_prod      = tx_prod;
4756157642Sps	sc->tx_prod_bseq = tx_prod_bseq;
4757157642Sps
4758157642Sps	DBPRINT(sc, BCE_INFO_SEND,
4759157642Sps		"%s(): End: tx_prod = 0x%04X, tx_chain_prod = 0x%04X, "
4760157642Sps		"tx_prod_bseq = 0x%08X\n",
4761157642Sps		__FUNCTION__, tx_prod, tx_chain_prod, tx_prod_bseq);
4762157642Sps
4763157642Sps	/* Start the transmit. */
4764157642Sps	REG_WR16(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BIDX, sc->tx_prod);
4765157642Sps	REG_WR(sc, MB_TX_CID_ADDR + BCE_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq);
4766157642Sps
4767157642Sps	/* Set the tx timeout. */
4768157642Sps	ifp->if_timer = BCE_TX_TIMEOUT;
4769157642Sps
4770157642Spsbce_start_locked_exit:
4771157642Sps	return;
4772157642Sps}
4773157642Sps
4774157642Sps
4775157642Sps/****************************************************************************/
4776157642Sps/* Main transmit routine when called from another routine without a lock.   */
4777157642Sps/*                                                                          */
4778157642Sps/* Returns:                                                                 */
4779157642Sps/*   Nothing.                                                               */
4780157642Sps/****************************************************************************/
4781157642Spsstatic void
4782157642Spsbce_start(struct ifnet *ifp)
4783157642Sps{
4784157642Sps	struct bce_softc *sc = ifp->if_softc;
4785157642Sps
4786157642Sps	BCE_LOCK(sc);
4787157642Sps	bce_start_locked(ifp);
4788157642Sps	BCE_UNLOCK(sc);
4789157642Sps}
4790157642Sps
4791157642Sps
4792157642Sps/****************************************************************************/
4793157642Sps/* Handles any IOCTL calls from the operating system.                       */
4794157642Sps/*                                                                          */
4795157642Sps/* Returns:                                                                 */
4796157642Sps/*   0 for success, positive value for failure.                             */
4797157642Sps/****************************************************************************/
4798157642Spsstatic int
4799157642Spsbce_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
4800157642Sps{
4801157642Sps	struct bce_softc *sc = ifp->if_softc;
4802157642Sps	struct ifreq *ifr = (struct ifreq *) data;
4803157642Sps	struct mii_data *mii;
4804157642Sps	int mask, error = 0;
4805157642Sps
4806157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
4807157642Sps
4808157642Sps	switch(command) {
4809157642Sps
4810157642Sps		/* Set the MTU. */
4811157642Sps		case SIOCSIFMTU:
4812157642Sps			/* Check that the MTU setting is supported. */
4813157642Sps			if ((ifr->ifr_mtu < BCE_MIN_MTU) ||
4814157642Sps				(ifr->ifr_mtu > BCE_MAX_JUMBO_MTU)) {
4815157642Sps				error = EINVAL;
4816157642Sps				break;
4817157642Sps			}
4818157642Sps
4819157642Sps			DBPRINT(sc, BCE_INFO, "Setting new MTU of %d\n", ifr->ifr_mtu);
4820157642Sps
4821157642Sps			ifp->if_mtu = ifr->ifr_mtu;
4822157642Sps			ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
4823157642Sps			bce_init(sc);
4824157642Sps			break;
4825157642Sps
4826157642Sps		/* Set interface. */
4827157642Sps		case SIOCSIFFLAGS:
4828157642Sps			DBPRINT(sc, BCE_VERBOSE, "Received SIOCSIFFLAGS\n");
4829157642Sps
4830157642Sps			BCE_LOCK(sc);
4831157642Sps
4832157642Sps			/* Check if the interface is up. */
4833157642Sps			if (ifp->if_flags & IFF_UP) {
4834157642Sps				/* Change the promiscuous/multicast flags as necessary. */
4835157642Sps				bce_set_rx_mode(sc);
4836157642Sps			} else {
4837157642Sps				/* The interface is down.  Check if the driver is running. */
4838157642Sps				if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
4839157642Sps					bce_stop(sc);
4840157642Sps				}
4841157642Sps			}
4842157642Sps
4843157642Sps			BCE_UNLOCK(sc);
4844157642Sps			error = 0;
4845157642Sps
4846157642Sps			break;
4847157642Sps
4848157642Sps		/* Add/Delete multicast address */
4849157642Sps		case SIOCADDMULTI:
4850157642Sps		case SIOCDELMULTI:
4851157642Sps			DBPRINT(sc, BCE_VERBOSE, "Received SIOCADDMULTI/SIOCDELMULTI\n");
4852157642Sps
4853157642Sps			if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
4854157642Sps				BCE_LOCK(sc);
4855157642Sps				bce_set_rx_mode(sc);
4856157642Sps				BCE_UNLOCK(sc);
4857157642Sps				error = 0;
4858157642Sps			}
4859157642Sps
4860157642Sps			break;
4861157642Sps
4862157642Sps		/* Set/Get Interface media */
4863157642Sps		case SIOCSIFMEDIA:
4864157642Sps		case SIOCGIFMEDIA:
4865157642Sps			DBPRINT(sc, BCE_VERBOSE, "Received SIOCSIFMEDIA/SIOCGIFMEDIA\n");
4866157642Sps
4867157642Sps			DBPRINT(sc, BCE_VERBOSE, "bce_phy_flags = 0x%08X\n",
4868157642Sps				sc->bce_phy_flags);
4869157642Sps
4870157642Sps			if (sc->bce_phy_flags & BCE_PHY_SERDES_FLAG) {
4871157642Sps				DBPRINT(sc, BCE_VERBOSE, "SerDes media set/get\n");
4872157642Sps
4873157642Sps				error = ifmedia_ioctl(ifp, ifr,
4874157642Sps				    &sc->bce_ifmedia, command);
4875157642Sps			} else {
4876157642Sps				DBPRINT(sc, BCE_VERBOSE, "Copper media set/get\n");
4877157642Sps				mii = device_get_softc(sc->bce_miibus);
4878157642Sps				error = ifmedia_ioctl(ifp, ifr,
4879157642Sps				    &mii->mii_media, command);
4880157642Sps			}
4881157642Sps			break;
4882157642Sps
4883157642Sps		/* Set interface capability */
4884157642Sps		case SIOCSIFCAP:
4885157642Sps			mask = ifr->ifr_reqcap ^ ifp->if_capenable;
4886157642Sps			DBPRINT(sc, BCE_INFO, "Received SIOCSIFCAP = 0x%08X\n", (u32) mask);
4887157642Sps
4888157642Sps#ifdef DEVICE_POLLING
4889157642Sps			if (mask & IFCAP_POLLING) {
4890157642Sps				if (ifr->ifr_reqcap & IFCAP_POLLING) {
4891157642Sps
4892157642Sps					/* Setup the poll routine to call. */
4893157642Sps					error = ether_poll_register(bce_poll, ifp);
4894157642Sps					if (error) {
4895157642Sps						BCE_PRINTF(sc, "%s(%d): Error registering poll function!\n",
4896157642Sps							__FILE__, __LINE__);
4897157642Sps						goto bce_ioctl_exit;
4898157642Sps					}
4899157642Sps
4900157642Sps					/* Clear the interrupt. */
4901157642Sps					BCE_LOCK(sc);
4902157642Sps					bce_disable_intr(sc);
4903157642Sps
4904157642Sps					REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
4905157642Sps						(1 << 16) | sc->bce_rx_quick_cons_trip);
4906157642Sps					REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
4907157642Sps						(1 << 16) | sc->bce_tx_quick_cons_trip);
4908157642Sps
4909157642Sps					ifp->if_capenable |= IFCAP_POLLING;
4910157642Sps					BCE_UNLOCK(sc);
4911157642Sps				} else {
4912157642Sps					/* Clear the poll routine. */
4913157642Sps					error = ether_poll_deregister(ifp);
4914157642Sps
4915157642Sps					/* Enable interrupt even in error case */
4916157642Sps					BCE_LOCK(sc);
4917157642Sps					bce_enable_intr(sc);
4918157642Sps
4919157642Sps					REG_WR(sc, BCE_HC_TX_QUICK_CONS_TRIP,
4920157642Sps						(sc->bce_tx_quick_cons_trip_int << 16) |
4921157642Sps						sc->bce_tx_quick_cons_trip);
4922157642Sps					REG_WR(sc, BCE_HC_RX_QUICK_CONS_TRIP,
4923157642Sps						(sc->bce_rx_quick_cons_trip_int << 16) |
4924157642Sps						sc->bce_rx_quick_cons_trip);
4925157642Sps
4926157642Sps					ifp->if_capenable &= ~IFCAP_POLLING;
4927157642Sps					BCE_UNLOCK(sc);
4928157642Sps				}
4929157642Sps			}
4930157642Sps#endif /*DEVICE_POLLING */
4931157642Sps
4932157642Sps			/* Toggle the TX checksum capabilites enable flag. */
4933157642Sps			if (mask & IFCAP_TXCSUM) {
4934157642Sps				ifp->if_capenable ^= IFCAP_TXCSUM;
4935157642Sps				if (IFCAP_TXCSUM & ifp->if_capenable)
4936157642Sps					ifp->if_hwassist = BCE_IF_HWASSIST;
4937157642Sps				else
4938157642Sps					ifp->if_hwassist = 0;
4939157642Sps			}
4940157642Sps
4941157642Sps			/* Toggle the RX checksum capabilities enable flag. */
4942157642Sps			if (mask & IFCAP_RXCSUM) {
4943157642Sps				ifp->if_capenable ^= IFCAP_RXCSUM;
4944157642Sps				if (IFCAP_RXCSUM & ifp->if_capenable)
4945157642Sps					ifp->if_hwassist = BCE_IF_HWASSIST;
4946157642Sps				else
4947157642Sps					ifp->if_hwassist = 0;
4948157642Sps			}
4949157642Sps
4950157642Sps			/* Toggle VLAN_MTU capabilities enable flag. */
4951157642Sps			if (mask & IFCAP_VLAN_MTU) {
4952157642Sps				BCE_PRINTF(sc, "%s(%d): Changing VLAN_MTU not supported.\n",
4953157642Sps					__FILE__, __LINE__);
4954157642Sps			}
4955157642Sps
4956157642Sps			/* Toggle VLANHWTAG capabilities enabled flag. */
4957157642Sps			if (mask & IFCAP_VLAN_HWTAGGING) {
4958157642Sps				if (sc->bce_flags & BCE_MFW_ENABLE_FLAG)
4959157642Sps					BCE_PRINTF(sc, "%s(%d): Cannot change VLAN_HWTAGGING while "
4960157642Sps						"management firmware (ASF/IPMI/UMP) is running!\n",
4961157642Sps						__FILE__, __LINE__);
4962157642Sps				else
4963157642Sps					BCE_PRINTF(sc, "%s(%d): Changing VLAN_HWTAGGING not supported!\n",
4964157642Sps						__FILE__, __LINE__);
4965157642Sps			}
4966157642Sps
4967157642Sps			break;
4968157642Sps		default:
4969157642Sps			DBPRINT(sc, BCE_INFO, "Received unsupported IOCTL: 0x%08X\n",
4970157642Sps				(u32) command);
4971157642Sps
4972157642Sps			/* We don't know how to handle the IOCTL, pass it on. */
4973157642Sps			error = ether_ioctl(ifp, command, data);
4974157642Sps			break;
4975157642Sps	}
4976157642Sps
4977157724Sru#ifdef DEVICE_POLLING
4978157724Srubce_ioctl_exit:
4979157724Sru#endif
4980157724Sru
4981157642Sps	DBPRINT(sc, BCE_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
4982157642Sps
4983157642Sps	return(error);
4984157642Sps}
4985157642Sps
4986157642Sps
4987157642Sps/****************************************************************************/
4988157642Sps/* Transmit timeout handler.                                                */
4989157642Sps/*                                                                          */
4990157642Sps/* Returns:                                                                 */
4991157642Sps/*   Nothing.                                                               */
4992157642Sps/****************************************************************************/
4993157642Spsstatic void
4994157642Spsbce_watchdog(struct ifnet *ifp)
4995157642Sps{
4996157642Sps	struct bce_softc *sc = ifp->if_softc;
4997157642Sps
4998157642Sps	DBRUN(BCE_WARN_SEND,
4999157642Sps		bce_dump_driver_state(sc);
5000157642Sps		bce_dump_status_block(sc));
5001157642Sps
5002157642Sps	BCE_PRINTF(sc, "%s(%d): Watchdog timeout occurred, resetting!\n",
5003157642Sps		__FILE__, __LINE__);
5004157642Sps
5005157642Sps	/* DBRUN(BCE_FATAL, bce_breakpoint(sc)); */
5006157642Sps
5007157642Sps	ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
5008157642Sps
5009157642Sps	bce_init(sc);
5010157642Sps	ifp->if_oerrors++;
5011157642Sps
5012157642Sps}
5013157642Sps
5014157642Sps
5015157642Sps#ifdef DEVICE_POLLING
5016157642Spsstatic void
5017157642Spsbce_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
5018157642Sps{
5019157642Sps	struct bce_softc *sc = ifp->if_softc;
5020157642Sps
5021157642Sps	BCE_LOCK_ASSERT(sc);
5022157642Sps
5023157642Sps	sc->bce_rxcycles = count;
5024157642Sps
5025157642Sps	bus_dmamap_sync(sc->status_tag, sc->status_map,
5026157642Sps	    BUS_DMASYNC_POSTWRITE);
5027157642Sps
5028157642Sps	/* Check for any completed RX frames. */
5029157642Sps	if (sc->status_block->status_rx_quick_consumer_index0 !=
5030157642Sps		sc->hw_rx_cons)
5031157642Sps		bce_rx_intr(sc);
5032157642Sps
5033157642Sps	/* Check for any completed TX frames. */
5034157642Sps	if (sc->status_block->status_tx_quick_consumer_index0 !=
5035157642Sps		sc->hw_tx_cons)
5036157642Sps		bce_tx_intr(sc);
5037157642Sps
5038157642Sps	/* Check for new frames to transmit. */
5039157642Sps	if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
5040157642Sps		bce_start_locked(ifp);
5041157642Sps
5042157642Sps}
5043157642Sps
5044157642Sps
5045157642Spsstatic void
5046157642Spsbce_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
5047157642Sps{
5048157642Sps	struct bce_softc *sc = ifp->if_softc;
5049157642Sps
5050157642Sps	BCE_LOCK(sc);
5051157642Sps	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
5052157642Sps		bce_poll_locked(ifp, cmd, count);
5053157642Sps	BCE_UNLOCK(sc);
5054157642Sps}
5055157642Sps#endif /* DEVICE_POLLING */
5056157642Sps
5057157642Sps
5058157642Sps#if 0
5059157642Spsstatic inline int
5060157642Spsbce_has_work(struct bce_softc *sc)
5061157642Sps{
5062157642Sps	struct status_block *stat = sc->status_block;
5063157642Sps
5064157642Sps	if ((stat->status_rx_quick_consumer_index0 != sc->hw_rx_cons) ||
5065157642Sps	    (stat->status_tx_quick_consumer_index0 != sc->hw_tx_cons))
5066157642Sps		return 1;
5067157642Sps
5068157642Sps	if (((stat->status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) != 0) !=
5069157642Sps	    bp->link_up)
5070157642Sps		return 1;
5071157642Sps
5072157642Sps	return 0;
5073157642Sps}
5074157642Sps#endif
5075157642Sps
5076157642Sps
5077157642Sps/*
5078157642Sps * Interrupt handler.
5079157642Sps */
5080157642Sps/****************************************************************************/
5081157642Sps/* Main interrupt entry point.  Verifies that the controller generated the  */
5082157642Sps/* interrupt and then calls a separate routine for handle the various       */
5083157642Sps/* interrupt causes (PHY, TX, RX).                                          */
5084157642Sps/*                                                                          */
5085157642Sps/* Returns:                                                                 */
5086157642Sps/*   0 for success, positive value for failure.                             */
5087157642Sps/****************************************************************************/
5088157642Spsstatic void
5089157642Spsbce_intr(void *xsc)
5090157642Sps{
5091157642Sps	struct bce_softc *sc;
5092157642Sps	struct ifnet *ifp;
5093157642Sps	u32 status_attn_bits;
5094157642Sps
5095157642Sps	sc = xsc;
5096157642Sps	ifp = sc->bce_ifp;
5097157642Sps
5098157642Sps	BCE_LOCK(sc);
5099157642Sps
5100157642Sps	DBRUNIF(1, sc->interrupts_generated++);
5101157642Sps
5102157642Sps#ifdef DEVICE_POLLING
5103157642Sps	if (ifp->if_capenable & IFCAP_POLLING) {
5104157642Sps		DBPRINT(sc, BCE_INFO, "Polling enabled!\n");
5105157642Sps		goto bce_intr_exit;
5106157642Sps	}
5107157642Sps#endif
5108157642Sps
5109157642Sps	bus_dmamap_sync(sc->status_tag, sc->status_map,
5110157642Sps	    BUS_DMASYNC_POSTWRITE);
5111157642Sps
5112157642Sps	/*
5113157642Sps	 * If the hardware status block index
5114157642Sps	 * matches the last value read by the
5115157642Sps	 * driver and we haven't asserted our
5116157642Sps	 * interrupt then there's nothing to do.
5117157642Sps	 */
5118157642Sps	if ((sc->status_block->status_idx == sc->last_status_idx) &&
5119157642Sps		(REG_RD(sc, BCE_PCICFG_MISC_STATUS) & BCE_PCICFG_MISC_STATUS_INTA_VALUE))
5120157642Sps		goto bce_intr_exit;
5121157642Sps
5122157642Sps	/* Ack the interrupt and stop others from occuring. */
5123157642Sps	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
5124157642Sps		BCE_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
5125157642Sps		BCE_PCICFG_INT_ACK_CMD_MASK_INT);
5126157642Sps
5127157642Sps	/* Keep processing data as long as there is work to do. */
5128157642Sps	for (;;) {
5129157642Sps
5130157642Sps		status_attn_bits = sc->status_block->status_attn_bits;
5131157642Sps
5132157642Sps		DBRUNIF(DB_RANDOMTRUE(bce_debug_unexpected_attention),
5133157642Sps			BCE_PRINTF(sc, "Simulating unexpected status attention bit set.");
5134157642Sps			status_attn_bits = status_attn_bits | STATUS_ATTN_BITS_PARITY_ERROR);
5135157642Sps
5136157642Sps		/* Was it a link change interrupt? */
5137157642Sps		if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
5138157642Sps			(sc->status_block->status_attn_bits_ack & STATUS_ATTN_BITS_LINK_STATE))
5139157642Sps			bce_phy_intr(sc);
5140157642Sps
5141157642Sps		/* If any other attention is asserted then the chip is toast. */
5142157642Sps		if (((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) !=
5143157642Sps			(sc->status_block->status_attn_bits_ack &
5144157642Sps			~STATUS_ATTN_BITS_LINK_STATE))) {
5145157642Sps
5146157642Sps			DBRUN(1, sc->unexpected_attentions++);
5147157642Sps
5148157642Sps			BCE_PRINTF(sc, "%s(%d): Fatal attention detected: 0x%08X\n",
5149157642Sps				__FILE__, __LINE__, sc->status_block->status_attn_bits);
5150157642Sps
5151157642Sps			DBRUN(BCE_FATAL,
5152157642Sps				if (bce_debug_unexpected_attention == 0)
5153157642Sps					bce_breakpoint(sc));
5154157642Sps
5155157642Sps			bce_init_locked(sc);
5156157642Sps			goto bce_intr_exit;
5157157642Sps		}
5158157642Sps
5159157642Sps		/* Check for any completed RX frames. */
5160157642Sps		if (sc->status_block->status_rx_quick_consumer_index0 != sc->hw_rx_cons)
5161157642Sps			bce_rx_intr(sc);
5162157642Sps
5163157642Sps		/* Check for any completed TX frames. */
5164157642Sps		if (sc->status_block->status_tx_quick_consumer_index0 != sc->hw_tx_cons)
5165157642Sps			bce_tx_intr(sc);
5166157642Sps
5167157642Sps		/* Save the status block index value for use during the next interrupt. */
5168157642Sps		sc->last_status_idx = sc->status_block->status_idx;
5169157642Sps
5170157642Sps		/* Prevent speculative reads from getting ahead of the status block. */
5171157642Sps		bus_space_barrier(sc->bce_btag, sc->bce_bhandle, 0, 0,
5172157642Sps			BUS_SPACE_BARRIER_READ);
5173157642Sps
5174157642Sps		/* If there's no work left then exit the interrupt service routine. */
5175157642Sps		if ((sc->status_block->status_rx_quick_consumer_index0 == sc->hw_rx_cons) &&
5176157642Sps	    	(sc->status_block->status_tx_quick_consumer_index0 == sc->hw_tx_cons))
5177157642Sps			break;
5178157642Sps
5179157642Sps	}
5180157642Sps
5181157642Sps	bus_dmamap_sync(sc->status_tag,	sc->status_map,
5182157642Sps	    BUS_DMASYNC_PREWRITE);
5183157642Sps
5184157642Sps	/* Re-enable interrupts. */
5185157642Sps	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
5186157642Sps	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx |
5187157642Sps	       BCE_PCICFG_INT_ACK_CMD_MASK_INT);
5188157642Sps	REG_WR(sc, BCE_PCICFG_INT_ACK_CMD,
5189157642Sps	       BCE_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx);
5190157642Sps
5191157642Sps	/* Handle any frames that arrived while handling the interrupt. */
5192157642Sps	if (ifp->if_drv_flags & IFF_DRV_RUNNING && !IFQ_DRV_IS_EMPTY(&ifp->if_snd))
5193157642Sps		bce_start_locked(ifp);
5194157642Sps
5195157642Spsbce_intr_exit:
5196157642Sps	BCE_UNLOCK(sc);
5197157642Sps}
5198157642Sps
5199157642Sps
5200157642Sps/****************************************************************************/
5201157642Sps/* Programs the various packet receive modes (broadcast and multicast).     */
5202157642Sps/*                                                                          */
5203157642Sps/* Returns:                                                                 */
5204157642Sps/*   Nothing.                                                               */
5205157642Sps/****************************************************************************/
5206157642Spsstatic void
5207157642Spsbce_set_rx_mode(struct bce_softc *sc)
5208157642Sps{
5209157642Sps	struct ifnet *ifp;
5210157642Sps	struct ifmultiaddr *ifma;
5211157642Sps	u32 hashes[4] = { 0, 0, 0, 0 };
5212157642Sps	u32 rx_mode, sort_mode;
5213157642Sps	int h, i;
5214157642Sps
5215157642Sps	BCE_LOCK_ASSERT(sc);
5216157642Sps
5217157642Sps	ifp = sc->bce_ifp;
5218157642Sps
5219157642Sps	/* Initialize receive mode default settings. */
5220157642Sps	rx_mode   = sc->rx_mode & ~(BCE_EMAC_RX_MODE_PROMISCUOUS |
5221157642Sps			    BCE_EMAC_RX_MODE_KEEP_VLAN_TAG);
5222157642Sps	sort_mode = 1 | BCE_RPM_SORT_USER0_BC_EN;
5223157642Sps
5224157642Sps	/*
5225157642Sps	 * ASF/IPMI/UMP firmware requires that VLAN tag stripping
5226157642Sps	 * be enbled.
5227157642Sps	 */
5228157642Sps	if (!(BCE_IF_CAPABILITIES & IFCAP_VLAN_HWTAGGING) &&
5229157642Sps		(!(sc->bce_flags & BCE_MFW_ENABLE_FLAG)))
5230157642Sps		rx_mode |= BCE_EMAC_RX_MODE_KEEP_VLAN_TAG;
5231157642Sps
5232157642Sps	/*
5233157642Sps	 * Check for promiscuous, all multicast, or selected
5234157642Sps	 * multicast address filtering.
5235157642Sps	 */
5236157642Sps	if (ifp->if_flags & IFF_PROMISC) {
5237157642Sps		DBPRINT(sc, BCE_INFO, "Enabling promiscuous mode.\n");
5238157642Sps
5239157642Sps		/* Enable promiscuous mode. */
5240157642Sps		rx_mode |= BCE_EMAC_RX_MODE_PROMISCUOUS;
5241157642Sps		sort_mode |= BCE_RPM_SORT_USER0_PROM_EN;
5242157642Sps	} else if (ifp->if_flags & IFF_ALLMULTI) {
5243157642Sps		DBPRINT(sc, BCE_INFO, "Enabling all multicast mode.\n");
5244157642Sps
5245157642Sps		/* Enable all multicast addresses. */
5246157642Sps		for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
5247157642Sps			REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), 0xffffffff);
5248157642Sps       	}
5249157642Sps		sort_mode |= BCE_RPM_SORT_USER0_MC_EN;
5250157642Sps	} else {
5251157642Sps		/* Accept one or more multicast(s). */
5252157642Sps		DBPRINT(sc, BCE_INFO, "Enabling selective multicast mode.\n");
5253157642Sps
5254157642Sps		IF_ADDR_LOCK(ifp);
5255157642Sps		TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
5256157642Sps			if (ifma->ifma_addr->sa_family != AF_LINK)
5257157642Sps				continue;
5258157642Sps			h = ether_crc32_le(LLADDR((struct sockaddr_dl *)
5259157642Sps		    	ifma->ifma_addr), ETHER_ADDR_LEN) & 0x7F;
5260157642Sps			hashes[(h & 0x60) >> 5] |= 1 << (h & 0x1F);
5261157642Sps		}
5262157642Sps		IF_ADDR_UNLOCK(ifp);
5263157642Sps
5264157642Sps		for (i = 0; i < 4; i++)
5265157642Sps			REG_WR(sc, BCE_EMAC_MULTICAST_HASH0 + (i * 4), hashes[i]);
5266157642Sps
5267157642Sps		sort_mode |= BCE_RPM_SORT_USER0_MC_HSH_EN;
5268157642Sps	}
5269157642Sps
5270157642Sps	/* Only make changes if the recive mode has actually changed. */
5271157642Sps	if (rx_mode != sc->rx_mode) {
5272157642Sps		DBPRINT(sc, BCE_VERBOSE, "Enabling new receive mode: 0x%08X\n",
5273157642Sps			rx_mode);
5274157642Sps
5275157642Sps		sc->rx_mode = rx_mode;
5276157642Sps		REG_WR(sc, BCE_EMAC_RX_MODE, rx_mode);
5277157642Sps	}
5278157642Sps
5279157642Sps	/* Disable and clear the exisitng sort before enabling a new sort. */
5280157642Sps	REG_WR(sc, BCE_RPM_SORT_USER0, 0x0);
5281157642Sps	REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode);
5282157642Sps	REG_WR(sc, BCE_RPM_SORT_USER0, sort_mode | BCE_RPM_SORT_USER0_ENA);
5283157642Sps}
5284157642Sps
5285157642Sps
5286157642Sps/****************************************************************************/
5287157642Sps/* Called periodically to updates statistics from the controllers           */
5288157642Sps/* statistics block.                                                        */
5289157642Sps/*                                                                          */
5290157642Sps/* Returns:                                                                 */
5291157642Sps/*   Nothing.                                                               */
5292157642Sps/****************************************************************************/
5293157642Spsstatic void
5294157642Spsbce_stats_update(struct bce_softc *sc)
5295157642Sps{
5296157642Sps	struct ifnet *ifp;
5297157642Sps	struct statistics_block *stats;
5298157642Sps
5299157642Sps	DBPRINT(sc, BCE_EXCESSIVE, "Entering %s()\n", __FUNCTION__);
5300157642Sps
5301157642Sps	ifp = sc->bce_ifp;
5302157642Sps
5303157642Sps	stats = (struct statistics_block *) sc->stats_block;
5304157642Sps
5305157642Sps	/*
5306157642Sps	 * Update the interface statistics from the
5307157642Sps	 * hardware statistics.
5308157642Sps	 */
5309157642Sps	ifp->if_collisions = (u_long) stats->stat_EtherStatsCollisions;
5310157642Sps
5311157642Sps	ifp->if_ibytes  = BCE_STATS(IfHCInOctets);
5312157642Sps
5313157642Sps	ifp->if_obytes  = BCE_STATS(IfHCOutOctets);
5314157642Sps
5315157642Sps	ifp->if_imcasts = BCE_STATS(IfHCInMulticastPkts);
5316157642Sps
5317157642Sps	ifp->if_omcasts = BCE_STATS(IfHCOutMulticastPkts);
5318157642Sps
5319157642Sps	ifp->if_ierrors = (u_long) stats->stat_EtherStatsUndersizePkts +
5320157642Sps				      (u_long) stats->stat_EtherStatsOverrsizePkts +
5321157642Sps					  (u_long) stats->stat_IfInMBUFDiscards +
5322157642Sps					  (u_long) stats->stat_Dot3StatsAlignmentErrors +
5323157642Sps					  (u_long) stats->stat_Dot3StatsFCSErrors;
5324157642Sps
5325157642Sps	ifp->if_oerrors = (u_long) stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors +
5326157642Sps					  (u_long) stats->stat_Dot3StatsExcessiveCollisions +
5327157642Sps					  (u_long) stats->stat_Dot3StatsLateCollisions;
5328157642Sps
5329157642Sps	/*
5330157642Sps	 * Certain controllers don't report
5331157642Sps	 * carrier sense errors correctly.
5332157642Sps	 * See errata E11_5708CA0_1165.
5333157642Sps	 */
5334157642Sps	if (!(BCE_CHIP_NUM(sc) == BCE_CHIP_NUM_5706) &&
5335157642Sps	    !(BCE_CHIP_ID(sc) == BCE_CHIP_ID_5708_A0))
5336157642Sps		ifp->if_oerrors += (u_long) stats->stat_Dot3StatsCarrierSenseErrors;
5337157642Sps
5338157642Sps	/*
5339157642Sps	 * Update the sysctl statistics from the
5340157642Sps	 * hardware statistics.
5341157642Sps	 */
5342157642Sps	sc->stat_IfHCInOctets =
5343157642Sps		((u64) stats->stat_IfHCInOctets_hi << 32) +
5344157642Sps		 (u64) stats->stat_IfHCInOctets_lo;
5345157642Sps
5346157642Sps	sc->stat_IfHCInBadOctets =
5347157642Sps		((u64) stats->stat_IfHCInBadOctets_hi << 32) +
5348157642Sps		 (u64) stats->stat_IfHCInBadOctets_lo;
5349157642Sps
5350157642Sps	sc->stat_IfHCOutOctets =
5351157642Sps		((u64) stats->stat_IfHCOutOctets_hi << 32) +
5352157642Sps		 (u64) stats->stat_IfHCOutOctets_lo;
5353157642Sps
5354157642Sps	sc->stat_IfHCOutBadOctets =
5355157642Sps		((u64) stats->stat_IfHCOutBadOctets_hi << 32) +
5356157642Sps		 (u64) stats->stat_IfHCOutBadOctets_lo;
5357157642Sps
5358157642Sps	sc->stat_IfHCInUcastPkts =
5359157642Sps		((u64) stats->stat_IfHCInUcastPkts_hi << 32) +
5360157642Sps		 (u64) stats->stat_IfHCInUcastPkts_lo;
5361157642Sps
5362157642Sps	sc->stat_IfHCInMulticastPkts =
5363157642Sps		((u64) stats->stat_IfHCInMulticastPkts_hi << 32) +
5364157642Sps		 (u64) stats->stat_IfHCInMulticastPkts_lo;
5365157642Sps
5366157642Sps	sc->stat_IfHCInBroadcastPkts =
5367157642Sps		((u64) stats->stat_IfHCInBroadcastPkts_hi << 32) +
5368157642Sps		 (u64) stats->stat_IfHCInBroadcastPkts_lo;
5369157642Sps
5370157642Sps	sc->stat_IfHCOutUcastPkts =
5371157642Sps		((u64) stats->stat_IfHCOutUcastPkts_hi << 32) +
5372157642Sps		 (u64) stats->stat_IfHCOutUcastPkts_lo;
5373157642Sps
5374157642Sps	sc->stat_IfHCOutMulticastPkts =
5375157642Sps		((u64) stats->stat_IfHCOutMulticastPkts_hi << 32) +
5376157642Sps		 (u64) stats->stat_IfHCOutMulticastPkts_lo;
5377157642Sps
5378157642Sps	sc->stat_IfHCOutBroadcastPkts =
5379157642Sps		((u64) stats->stat_IfHCOutBroadcastPkts_hi << 32) +
5380157642Sps		 (u64) stats->stat_IfHCOutBroadcastPkts_lo;
5381157642Sps
5382157642Sps	sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors =
5383157642Sps		stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
5384157642Sps
5385157642Sps	sc->stat_Dot3StatsCarrierSenseErrors =
5386157642Sps		stats->stat_Dot3StatsCarrierSenseErrors;
5387157642Sps
5388157642Sps	sc->stat_Dot3StatsFCSErrors =
5389157642Sps		stats->stat_Dot3StatsFCSErrors;
5390157642Sps
5391157642Sps	sc->stat_Dot3StatsAlignmentErrors =
5392157642Sps		stats->stat_Dot3StatsAlignmentErrors;
5393157642Sps
5394157642Sps	sc->stat_Dot3StatsSingleCollisionFrames =
5395157642Sps		stats->stat_Dot3StatsSingleCollisionFrames;
5396157642Sps
5397157642Sps	sc->stat_Dot3StatsMultipleCollisionFrames =
5398157642Sps		stats->stat_Dot3StatsMultipleCollisionFrames;
5399157642Sps
5400157642Sps	sc->stat_Dot3StatsDeferredTransmissions =
5401157642Sps		stats->stat_Dot3StatsDeferredTransmissions;
5402157642Sps
5403157642Sps	sc->stat_Dot3StatsExcessiveCollisions =
5404157642Sps		stats->stat_Dot3StatsExcessiveCollisions;
5405157642Sps
5406157642Sps	sc->stat_Dot3StatsLateCollisions =
5407157642Sps		stats->stat_Dot3StatsLateCollisions;
5408157642Sps
5409157642Sps	sc->stat_EtherStatsCollisions =
5410157642Sps		stats->stat_EtherStatsCollisions;
5411157642Sps
5412157642Sps	sc->stat_EtherStatsFragments =
5413157642Sps		stats->stat_EtherStatsFragments;
5414157642Sps
5415157642Sps	sc->stat_EtherStatsJabbers =
5416157642Sps		stats->stat_EtherStatsJabbers;
5417157642Sps
5418157642Sps	sc->stat_EtherStatsUndersizePkts =
5419157642Sps		stats->stat_EtherStatsUndersizePkts;
5420157642Sps
5421157642Sps	sc->stat_EtherStatsOverrsizePkts =
5422157642Sps		stats->stat_EtherStatsOverrsizePkts;
5423157642Sps
5424157642Sps	sc->stat_EtherStatsPktsRx64Octets =
5425157642Sps		stats->stat_EtherStatsPktsRx64Octets;
5426157642Sps
5427157642Sps	sc->stat_EtherStatsPktsRx65Octetsto127Octets =
5428157642Sps		stats->stat_EtherStatsPktsRx65Octetsto127Octets;
5429157642Sps
5430157642Sps	sc->stat_EtherStatsPktsRx128Octetsto255Octets =
5431157642Sps		stats->stat_EtherStatsPktsRx128Octetsto255Octets;
5432157642Sps
5433157642Sps	sc->stat_EtherStatsPktsRx256Octetsto511Octets =
5434157642Sps		stats->stat_EtherStatsPktsRx256Octetsto511Octets;
5435157642Sps
5436157642Sps	sc->stat_EtherStatsPktsRx512Octetsto1023Octets =
5437157642Sps		stats->stat_EtherStatsPktsRx512Octetsto1023Octets;
5438157642Sps
5439157642Sps	sc->stat_EtherStatsPktsRx1024Octetsto1522Octets =
5440157642Sps		stats->stat_EtherStatsPktsRx1024Octetsto1522Octets;
5441157642Sps
5442157642Sps	sc->stat_EtherStatsPktsRx1523Octetsto9022Octets =
5443157642Sps		stats->stat_EtherStatsPktsRx1523Octetsto9022Octets;
5444157642Sps
5445157642Sps	sc->stat_EtherStatsPktsTx64Octets =
5446157642Sps		stats->stat_EtherStatsPktsTx64Octets;
5447157642Sps
5448157642Sps	sc->stat_EtherStatsPktsTx65Octetsto127Octets =
5449157642Sps		stats->stat_EtherStatsPktsTx65Octetsto127Octets;
5450157642Sps
5451157642Sps	sc->stat_EtherStatsPktsTx128Octetsto255Octets =
5452157642Sps		stats->stat_EtherStatsPktsTx128Octetsto255Octets;
5453157642Sps
5454157642Sps	sc->stat_EtherStatsPktsTx256Octetsto511Octets =
5455157642Sps		stats->stat_EtherStatsPktsTx256Octetsto511Octets;
5456157642Sps
5457157642Sps	sc->stat_EtherStatsPktsTx512Octetsto1023Octets =
5458157642Sps		stats->stat_EtherStatsPktsTx512Octetsto1023Octets;
5459157642Sps
5460157642Sps	sc->stat_EtherStatsPktsTx1024Octetsto1522Octets =
5461157642Sps		stats->stat_EtherStatsPktsTx1024Octetsto1522Octets;
5462157642Sps
5463157642Sps	sc->stat_EtherStatsPktsTx1523Octetsto9022Octets =
5464157642Sps		stats->stat_EtherStatsPktsTx1523Octetsto9022Octets;
5465157642Sps
5466157642Sps	sc->stat_XonPauseFramesReceived =
5467157642Sps		stats->stat_XonPauseFramesReceived;
5468157642Sps
5469157642Sps	sc->stat_XoffPauseFramesReceived =
5470157642Sps		stats->stat_XoffPauseFramesReceived;
5471157642Sps
5472157642Sps	sc->stat_OutXonSent =
5473157642Sps		stats->stat_OutXonSent;
5474157642Sps
5475157642Sps	sc->stat_OutXoffSent =
5476157642Sps		stats->stat_OutXoffSent;
5477157642Sps
5478157642Sps	sc->stat_FlowControlDone =
5479157642Sps		stats->stat_FlowControlDone;
5480157642Sps
5481157642Sps	sc->stat_MacControlFramesReceived =
5482157642Sps		stats->stat_MacControlFramesReceived;
5483157642Sps
5484157642Sps	sc->stat_XoffStateEntered =
5485157642Sps		stats->stat_XoffStateEntered;
5486157642Sps
5487157642Sps	sc->stat_IfInFramesL2FilterDiscards =
5488157642Sps		stats->stat_IfInFramesL2FilterDiscards;
5489157642Sps
5490157642Sps	sc->stat_IfInRuleCheckerDiscards =
5491157642Sps		stats->stat_IfInRuleCheckerDiscards;
5492157642Sps
5493157642Sps	sc->stat_IfInFTQDiscards =
5494157642Sps		stats->stat_IfInFTQDiscards;
5495157642Sps
5496157642Sps	sc->stat_IfInMBUFDiscards =
5497157642Sps		stats->stat_IfInMBUFDiscards;
5498157642Sps
5499157642Sps	sc->stat_IfInRuleCheckerP4Hit =
5500157642Sps		stats->stat_IfInRuleCheckerP4Hit;
5501157642Sps
5502157642Sps	sc->stat_CatchupInRuleCheckerDiscards =
5503157642Sps		stats->stat_CatchupInRuleCheckerDiscards;
5504157642Sps
5505157642Sps	sc->stat_CatchupInFTQDiscards =
5506157642Sps		stats->stat_CatchupInFTQDiscards;
5507157642Sps
5508157642Sps	sc->stat_CatchupInMBUFDiscards =
5509157642Sps		stats->stat_CatchupInMBUFDiscards;
5510157642Sps
5511157642Sps	sc->stat_CatchupInRuleCheckerP4Hit =
5512157642Sps		stats->stat_CatchupInRuleCheckerP4Hit;
5513157642Sps
5514157642Sps	DBPRINT(sc, BCE_EXCESSIVE, "Exiting %s()\n", __FUNCTION__);
5515157642Sps}
5516157642Sps
5517157642Sps
5518157642Spsstatic void
5519157642Spsbce_tick_locked(struct bce_softc *sc)
5520157642Sps{
5521157642Sps	struct mii_data *mii = NULL;
5522157642Sps	struct ifnet *ifp;
5523157642Sps	u32 msg;
5524157642Sps
5525157642Sps	ifp = sc->bce_ifp;
5526157642Sps
5527157642Sps	BCE_LOCK_ASSERT(sc);
5528157642Sps
5529157642Sps	/* Tell the firmware that the driver is still running. */
5530157642Sps#ifdef BCE_DEBUG
5531157642Sps	msg = (u32) BCE_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE;
5532157642Sps#else
5533157642Sps	msg = (u32) ++sc->bce_fw_drv_pulse_wr_seq;
5534157642Sps#endif
5535157642Sps	REG_WR_IND(sc, sc->bce_shmem_base + BCE_DRV_PULSE_MB, msg);
5536157642Sps
5537157642Sps	/* Update the statistics from the hardware statistics block. */
5538157642Sps	bce_stats_update(sc);
5539157642Sps
5540157642Sps	/* Schedule the next tick. */
5541157642Sps	callout_reset(
5542157642Sps		&sc->bce_stat_ch,		/* callout */
5543157642Sps		hz, 					/* ticks */
5544157642Sps		bce_tick, 				/* function */
5545157642Sps		sc);					/* function argument */
5546157642Sps
5547157642Sps	/* If link is up already up then we're done. */
5548157642Sps	if (sc->bce_link)
5549157642Sps		goto bce_tick_locked_exit;
5550157642Sps
5551157642Sps	/* DRC - ToDo: Add SerDes support and check SerDes link here. */
5552157642Sps
5553157642Sps	mii = device_get_softc(sc->bce_miibus);
5554157642Sps	mii_tick(mii);
5555157642Sps
5556157642Sps	/* Check if the link has come up. */
5557157642Sps	if (!sc->bce_link && mii->mii_media_status & IFM_ACTIVE &&
5558157642Sps	    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
5559157642Sps		sc->bce_link++;
5560157642Sps		if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T ||
5561157642Sps		    IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_SX) &&
5562157642Sps		    bootverbose)
5563157642Sps			BCE_PRINTF(sc, "Gigabit link up\n");
5564157642Sps		/* Now that link is up, handle any outstanding TX traffic. */
5565157642Sps		if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
5566157642Sps			bce_start_locked(ifp);
5567157642Sps	}
5568157642Sps
5569157642Spsbce_tick_locked_exit:
5570157642Sps	return;
5571157642Sps}
5572157642Sps
5573157642Sps
5574157642Spsstatic void
5575157642Spsbce_tick(void *xsc)
5576157642Sps{
5577157642Sps	struct bce_softc *sc;
5578157642Sps
5579157642Sps	sc = xsc;
5580157642Sps
5581157642Sps	BCE_LOCK(sc);
5582157642Sps	bce_tick_locked(sc);
5583157642Sps	BCE_UNLOCK(sc);
5584157642Sps}
5585157642Sps
5586157642Sps
5587157642Sps#ifdef BCE_DEBUG
5588157642Sps/****************************************************************************/
5589157642Sps/* Allows the driver state to be dumped through the sysctl interface.       */
5590157642Sps/*                                                                          */
5591157642Sps/* Returns:                                                                 */
5592157642Sps/*   0 for success, positive value for failure.                             */
5593157642Sps/****************************************************************************/
5594157642Spsstatic int
5595157642Spsbce_sysctl_driver_state(SYSCTL_HANDLER_ARGS)
5596157642Sps{
5597157642Sps        int error;
5598157642Sps        int result;
5599157642Sps        struct bce_softc *sc;
5600157642Sps
5601157642Sps        result = -1;
5602157642Sps        error = sysctl_handle_int(oidp, &result, 0, req);
5603157642Sps
5604157642Sps        if (error || !req->newptr)
5605157642Sps                return (error);
5606157642Sps
5607157642Sps        if (result == 1) {
5608157642Sps                sc = (struct bce_softc *)arg1;
5609157642Sps                bce_dump_driver_state(sc);
5610157642Sps        }
5611157642Sps
5612157642Sps        return error;
5613157642Sps}
5614157642Sps
5615157642Sps
5616157642Sps/****************************************************************************/
5617157642Sps/* Allows the hardware state to be dumped through the sysctl interface.     */
5618157642Sps/*                                                                          */
5619157642Sps/* Returns:                                                                 */
5620157642Sps/*   0 for success, positive value for failure.                             */
5621157642Sps/****************************************************************************/
5622157642Spsstatic int
5623157642Spsbce_sysctl_hw_state(SYSCTL_HANDLER_ARGS)
5624157642Sps{
5625157642Sps        int error;
5626157642Sps        int result;
5627157642Sps        struct bce_softc *sc;
5628157642Sps
5629157642Sps        result = -1;
5630157642Sps        error = sysctl_handle_int(oidp, &result, 0, req);
5631157642Sps
5632157642Sps        if (error || !req->newptr)
5633157642Sps                return (error);
5634157642Sps
5635157642Sps        if (result == 1) {
5636157642Sps                sc = (struct bce_softc *)arg1;
5637157642Sps                bce_dump_hw_state(sc);
5638157642Sps        }
5639157642Sps
5640157642Sps        return error;
5641157642Sps}
5642157642Sps
5643157642Sps
5644157642Sps/****************************************************************************/
5645157642Sps/*                                                                          */
5646157642Sps/*                                                                          */
5647157642Sps/* Returns:                                                                 */
5648157642Sps/*   0 for success, positive value for failure.                             */
5649157642Sps/****************************************************************************/
5650157642Spsstatic int
5651157642Spsbce_sysctl_dump_rx_chain(SYSCTL_HANDLER_ARGS)
5652157642Sps{
5653157642Sps        int error;
5654157642Sps        int result;
5655157642Sps        struct bce_softc *sc;
5656157642Sps
5657157642Sps        result = -1;
5658157642Sps        error = sysctl_handle_int(oidp, &result, 0, req);
5659157642Sps
5660157642Sps        if (error || !req->newptr)
5661157642Sps                return (error);
5662157642Sps
5663157642Sps        if (result == 1) {
5664157642Sps                sc = (struct bce_softc *)arg1;
5665157642Sps                bce_dump_rx_chain(sc, 0, USABLE_RX_BD);
5666157642Sps        }
5667157642Sps
5668157642Sps        return error;
5669157642Sps}
5670157642Sps
5671157642Sps
5672157642Sps/****************************************************************************/
5673157642Sps/*                                                                          */
5674157642Sps/*                                                                          */
5675157642Sps/* Returns:                                                                 */
5676157642Sps/*   0 for success, positive value for failure.                             */
5677157642Sps/****************************************************************************/
5678157642Spsstatic int
5679157642Spsbce_sysctl_breakpoint(SYSCTL_HANDLER_ARGS)
5680157642Sps{
5681157642Sps        int error;
5682157642Sps        int result;
5683157642Sps        struct bce_softc *sc;
5684157642Sps
5685157642Sps        result = -1;
5686157642Sps        error = sysctl_handle_int(oidp, &result, 0, req);
5687157642Sps
5688157642Sps        if (error || !req->newptr)
5689157642Sps                return (error);
5690157642Sps
5691157642Sps        if (result == 1) {
5692157642Sps                sc = (struct bce_softc *)arg1;
5693157642Sps                bce_breakpoint(sc);
5694157642Sps        }
5695157642Sps
5696157642Sps        return error;
5697157642Sps}
5698157642Sps#endif
5699157642Sps
5700157642Sps
5701157642Sps/****************************************************************************/
5702157642Sps/* Adds any sysctl parameters for tuning or debugging purposes.             */
5703157642Sps/*                                                                          */
5704157642Sps/* Returns:                                                                 */
5705157642Sps/*   0 for success, positive value for failure.                             */
5706157642Sps/****************************************************************************/
5707157642Spsstatic void
5708157642Spsbce_add_sysctls(struct bce_softc *sc)
5709157642Sps{
5710157642Sps	struct sysctl_ctx_list *ctx;
5711157642Sps	struct sysctl_oid_list *children;
5712157642Sps
5713157642Sps	ctx = device_get_sysctl_ctx(sc->bce_dev);
5714157642Sps	children = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->bce_dev));
5715157642Sps
5716157642Sps	SYSCTL_ADD_STRING(ctx, children, OID_AUTO,
5717157642Sps		"driver_version",
5718157642Sps		CTLFLAG_RD, &bce_driver_version,
5719157642Sps		0, "bce driver version");
5720157642Sps
5721157642Sps#ifdef BCE_DEBUG
5722157642Sps	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
5723157642Sps		"rx_low_watermark",
5724157642Sps		CTLFLAG_RD, &sc->rx_low_watermark,
5725157642Sps		0, "Lowest level of free rx_bd's");
5726157642Sps
5727157642Sps	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
5728157642Sps		"tx_hi_watermark",
5729157642Sps		CTLFLAG_RD, &sc->tx_hi_watermark,
5730157642Sps		0, "Highest level of used tx_bd's");
5731157642Sps
5732157642Sps	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
5733157642Sps		"l2fhdr_status_errors",
5734157642Sps		CTLFLAG_RD, &sc->l2fhdr_status_errors,
5735157642Sps		0, "l2_fhdr status errors");
5736157642Sps
5737157642Sps	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
5738157642Sps		"unexpected_attentions",
5739157642Sps		CTLFLAG_RD, &sc->unexpected_attentions,
5740157642Sps		0, "unexpected attentions");
5741157642Sps
5742157642Sps	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
5743157642Sps		"lost_status_block_updates",
5744157642Sps		CTLFLAG_RD, &sc->lost_status_block_updates,
5745157642Sps		0, "lost status block updates");
5746157642Sps
5747157642Sps	SYSCTL_ADD_INT(ctx, children, OID_AUTO,
5748157642Sps		"mbuf_alloc_failed",
5749157642Sps		CTLFLAG_RD, &sc->mbuf_alloc_failed,
5750157642Sps		0, "mbuf cluster allocation failures");
5751157642Sps#endif
5752157642Sps
5753157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5754157642Sps		"stat_IfHcInOctets",
5755157642Sps		CTLFLAG_RD, &sc->stat_IfHCInOctets,
5756157642Sps		"Bytes received");
5757157642Sps
5758157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5759157642Sps		"stat_IfHCInBadOctets",
5760157642Sps		CTLFLAG_RD, &sc->stat_IfHCInBadOctets,
5761157642Sps		"Bad bytes received");
5762157642Sps
5763157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5764157642Sps		"stat_IfHCOutOctets",
5765157642Sps		CTLFLAG_RD, &sc->stat_IfHCOutOctets,
5766157642Sps		"Bytes sent");
5767157642Sps
5768157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5769157642Sps		"stat_IfHCOutBadOctets",
5770157642Sps		CTLFLAG_RD, &sc->stat_IfHCOutBadOctets,
5771157642Sps		"Bad bytes sent");
5772157642Sps
5773157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5774157642Sps		"stat_IfHCInUcastPkts",
5775157642Sps		CTLFLAG_RD, &sc->stat_IfHCInUcastPkts,
5776157642Sps		"Unicast packets received");
5777157642Sps
5778157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5779157642Sps		"stat_IfHCInMulticastPkts",
5780157642Sps		CTLFLAG_RD, &sc->stat_IfHCInMulticastPkts,
5781157642Sps		"Multicast packets received");
5782157642Sps
5783157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5784157642Sps		"stat_IfHCInBroadcastPkts",
5785157642Sps		CTLFLAG_RD, &sc->stat_IfHCInBroadcastPkts,
5786157642Sps		"Broadcast packets received");
5787157642Sps
5788157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5789157642Sps		"stat_IfHCOutUcastPkts",
5790157642Sps		CTLFLAG_RD, &sc->stat_IfHCOutUcastPkts,
5791157642Sps		"Unicast packets sent");
5792157642Sps
5793157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5794157642Sps		"stat_IfHCOutMulticastPkts",
5795157642Sps		CTLFLAG_RD, &sc->stat_IfHCOutMulticastPkts,
5796157642Sps		"Multicast packets sent");
5797157642Sps
5798157642Sps	SYSCTL_ADD_ULONG(ctx, children, OID_AUTO,
5799157642Sps		"stat_IfHCOutBroadcastPkts",
5800157642Sps		CTLFLAG_RD, &sc->stat_IfHCOutBroadcastPkts,
5801157642Sps		"Broadcast packets sent");
5802157642Sps
5803157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5804157642Sps		"stat_emac_tx_stat_dot3statsinternalmactransmiterrors",
5805157642Sps		CTLFLAG_RD, &sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors,
5806157642Sps		0, "Internal MAC transmit errors");
5807157642Sps
5808157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5809157642Sps		"stat_Dot3StatsCarrierSenseErrors",
5810157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsCarrierSenseErrors,
5811157642Sps		0, "Carrier sense errors");
5812157642Sps
5813157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5814157642Sps		"stat_Dot3StatsFCSErrors",
5815157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsFCSErrors,
5816157642Sps		0, "Frame check sequence errors");
5817157642Sps
5818157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5819157642Sps		"stat_Dot3StatsAlignmentErrors",
5820157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsAlignmentErrors,
5821157642Sps		0, "Alignment errors");
5822157642Sps
5823157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5824157642Sps		"stat_Dot3StatsSingleCollisionFrames",
5825157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsSingleCollisionFrames,
5826157642Sps		0, "Single Collision Frames");
5827157642Sps
5828157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5829157642Sps		"stat_Dot3StatsMultipleCollisionFrames",
5830157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsMultipleCollisionFrames,
5831157642Sps		0, "Multiple Collision Frames");
5832157642Sps
5833157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5834157642Sps		"stat_Dot3StatsDeferredTransmissions",
5835157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsDeferredTransmissions,
5836157642Sps		0, "Deferred Transmissions");
5837157642Sps
5838157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5839157642Sps		"stat_Dot3StatsExcessiveCollisions",
5840157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsExcessiveCollisions,
5841157642Sps		0, "Excessive Collisions");
5842157642Sps
5843157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5844157642Sps		"stat_Dot3StatsLateCollisions",
5845157642Sps		CTLFLAG_RD, &sc->stat_Dot3StatsLateCollisions,
5846157642Sps		0, "Late Collisions");
5847157642Sps
5848157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5849157642Sps		"stat_EtherStatsCollisions",
5850157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsCollisions,
5851157642Sps		0, "Collisions");
5852157642Sps
5853157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5854157642Sps		"stat_EtherStatsFragments",
5855157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsFragments,
5856157642Sps		0, "Fragments");
5857157642Sps
5858157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5859157642Sps		"stat_EtherStatsJabbers",
5860157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsJabbers,
5861157642Sps		0, "Jabbers");
5862157642Sps
5863157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5864157642Sps		"stat_EtherStatsUndersizePkts",
5865157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsUndersizePkts,
5866157642Sps		0, "Undersize packets");
5867157642Sps
5868157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5869157642Sps		"stat_EtherStatsOverrsizePkts",
5870157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsOverrsizePkts,
5871157642Sps		0, "stat_EtherStatsOverrsizePkts");
5872157642Sps
5873157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5874157642Sps		"stat_EtherStatsPktsRx64Octets",
5875157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx64Octets,
5876157642Sps		0, "Bytes received in 64 byte packets");
5877157642Sps
5878157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5879157642Sps		"stat_EtherStatsPktsRx65Octetsto127Octets",
5880157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx65Octetsto127Octets,
5881157642Sps		0, "Bytes received in 65 to 127 byte packets");
5882157642Sps
5883157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5884157642Sps		"stat_EtherStatsPktsRx128Octetsto255Octets",
5885157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx128Octetsto255Octets,
5886157642Sps		0, "Bytes received in 128 to 255 byte packets");
5887157642Sps
5888157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5889157642Sps		"stat_EtherStatsPktsRx256Octetsto511Octets",
5890157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx256Octetsto511Octets,
5891157642Sps		0, "Bytes received in 256 to 511 byte packets");
5892157642Sps
5893157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5894157642Sps		"stat_EtherStatsPktsRx512Octetsto1023Octets",
5895157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx512Octetsto1023Octets,
5896157642Sps		0, "Bytes received in 512 to 1023 byte packets");
5897157642Sps
5898157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5899157642Sps		"stat_EtherStatsPktsRx1024Octetsto1522Octets",
5900157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1024Octetsto1522Octets,
5901157642Sps		0, "Bytes received in 1024 t0 1522 byte packets");
5902157642Sps
5903157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5904157642Sps		"stat_EtherStatsPktsRx1523Octetsto9022Octets",
5905157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsRx1523Octetsto9022Octets,
5906157642Sps		0, "Bytes received in 1523 to 9022 byte packets");
5907157642Sps
5908157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5909157642Sps		"stat_EtherStatsPktsTx64Octets",
5910157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx64Octets,
5911157642Sps		0, "Bytes sent in 64 byte packets");
5912157642Sps
5913157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5914157642Sps		"stat_EtherStatsPktsTx65Octetsto127Octets",
5915157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx65Octetsto127Octets,
5916157642Sps		0, "Bytes sent in 65 to 127 byte packets");
5917157642Sps
5918157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5919157642Sps		"stat_EtherStatsPktsTx128Octetsto255Octets",
5920157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx128Octetsto255Octets,
5921157642Sps		0, "Bytes sent in 128 to 255 byte packets");
5922157642Sps
5923157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5924157642Sps		"stat_EtherStatsPktsTx256Octetsto511Octets",
5925157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx256Octetsto511Octets,
5926157642Sps		0, "Bytes sent in 256 to 511 byte packets");
5927157642Sps
5928157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5929157642Sps		"stat_EtherStatsPktsTx512Octetsto1023Octets",
5930157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx512Octetsto1023Octets,
5931157642Sps		0, "Bytes sent in 512 to 1023 byte packets");
5932157642Sps
5933157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5934157642Sps		"stat_EtherStatsPktsTx1024Octetsto1522Octets",
5935157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1024Octetsto1522Octets,
5936157642Sps		0, "Bytes sent in 1024 to 1522 byte packets");
5937157642Sps
5938157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5939157642Sps		"stat_EtherStatsPktsTx1523Octetsto9022Octets",
5940157642Sps		CTLFLAG_RD, &sc->stat_EtherStatsPktsTx1523Octetsto9022Octets,
5941157642Sps		0, "Bytes sent in 1523 to 9022 byte packets");
5942157642Sps
5943157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5944157642Sps		"stat_XonPauseFramesReceived",
5945157642Sps		CTLFLAG_RD, &sc->stat_XonPauseFramesReceived,
5946157642Sps		0, "XON pause frames receved");
5947157642Sps
5948157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5949157642Sps		"stat_XoffPauseFramesReceived",
5950157642Sps		CTLFLAG_RD, &sc->stat_XoffPauseFramesReceived,
5951157642Sps		0, "XOFF pause frames received");
5952157642Sps
5953157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5954157642Sps		"stat_OutXonSent",
5955157642Sps		CTLFLAG_RD, &sc->stat_OutXonSent,
5956157642Sps		0, "XON pause frames sent");
5957157642Sps
5958157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5959157642Sps		"stat_OutXoffSent",
5960157642Sps		CTLFLAG_RD, &sc->stat_OutXoffSent,
5961157642Sps		0, "XOFF pause frames sent");
5962157642Sps
5963157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5964157642Sps		"stat_FlowControlDone",
5965157642Sps		CTLFLAG_RD, &sc->stat_FlowControlDone,
5966157642Sps		0, "Flow control done");
5967157642Sps
5968157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5969157642Sps		"stat_MacControlFramesReceived",
5970157642Sps		CTLFLAG_RD, &sc->stat_MacControlFramesReceived,
5971157642Sps		0, "MAC control frames received");
5972157642Sps
5973157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5974157642Sps		"stat_XoffStateEntered",
5975157642Sps		CTLFLAG_RD, &sc->stat_XoffStateEntered,
5976157642Sps		0, "XOFF state entered");
5977157642Sps
5978157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5979157642Sps		"stat_IfInFramesL2FilterDiscards",
5980157642Sps		CTLFLAG_RD, &sc->stat_IfInFramesL2FilterDiscards,
5981157642Sps		0, "Received L2 packets discarded");
5982157642Sps
5983157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5984157642Sps		"stat_IfInRuleCheckerDiscards",
5985157642Sps		CTLFLAG_RD, &sc->stat_IfInRuleCheckerDiscards,
5986157642Sps		0, "Received packets discarded by rule");
5987157642Sps
5988157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5989157642Sps		"stat_IfInFTQDiscards",
5990157642Sps		CTLFLAG_RD, &sc->stat_IfInFTQDiscards,
5991157642Sps		0, "Received packet FTQ discards");
5992157642Sps
5993157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5994157642Sps		"stat_IfInMBUFDiscards",
5995157642Sps		CTLFLAG_RD, &sc->stat_IfInMBUFDiscards,
5996157642Sps		0, "Received packets discarded due to lack of controller buffer memory");
5997157642Sps
5998157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
5999157642Sps		"stat_IfInRuleCheckerP4Hit",
6000157642Sps		CTLFLAG_RD, &sc->stat_IfInRuleCheckerP4Hit,
6001157642Sps		0, "Received packets rule checker hits");
6002157642Sps
6003157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
6004157642Sps		"stat_CatchupInRuleCheckerDiscards",
6005157642Sps		CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerDiscards,
6006157642Sps		0, "Received packets discarded in Catchup path");
6007157642Sps
6008157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
6009157642Sps		"stat_CatchupInFTQDiscards",
6010157642Sps		CTLFLAG_RD, &sc->stat_CatchupInFTQDiscards,
6011157642Sps		0, "Received packets discarded in FTQ in Catchup path");
6012157642Sps
6013157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
6014157642Sps		"stat_CatchupInMBUFDiscards",
6015157642Sps		CTLFLAG_RD, &sc->stat_CatchupInMBUFDiscards,
6016157642Sps		0, "Received packets discarded in controller buffer memory in Catchup path");
6017157642Sps
6018157642Sps	SYSCTL_ADD_UINT(ctx, children, OID_AUTO,
6019157642Sps		"stat_CatchupInRuleCheckerP4Hit",
6020157642Sps		CTLFLAG_RD, &sc->stat_CatchupInRuleCheckerP4Hit,
6021157642Sps		0, "Received packets rule checker hits in Catchup path");
6022157642Sps
6023157642Sps#ifdef BCE_DEBUG
6024157642Sps	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
6025157642Sps		"driver_state", CTLTYPE_INT | CTLFLAG_RW,
6026157642Sps		(void *)sc, 0,
6027157642Sps		bce_sysctl_driver_state, "I", "Drive state information");
6028157642Sps
6029157642Sps	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
6030157642Sps		"hw_state", CTLTYPE_INT | CTLFLAG_RW,
6031157642Sps		(void *)sc, 0,
6032157642Sps		bce_sysctl_hw_state, "I", "Hardware state information");
6033157642Sps
6034157642Sps	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
6035157642Sps		"dump_rx_chain", CTLTYPE_INT | CTLFLAG_RW,
6036157642Sps		(void *)sc, 0,
6037157642Sps		bce_sysctl_dump_rx_chain, "I", "Dump rx_bd chain");
6038157642Sps
6039157642Sps	SYSCTL_ADD_PROC(ctx, children, OID_AUTO,
6040157642Sps		"breakpoint", CTLTYPE_INT | CTLFLAG_RW,
6041157642Sps		(void *)sc, 0,
6042157642Sps		bce_sysctl_breakpoint, "I", "Driver breakpoint");
6043157642Sps#endif
6044157642Sps
6045157642Sps}
6046157642Sps
6047157642Sps
6048157642Sps/****************************************************************************/
6049157642Sps/* BCE Debug Routines                                                       */
6050157642Sps/****************************************************************************/
6051157642Sps#ifdef BCE_DEBUG
6052157642Sps
6053157642Sps/****************************************************************************/
6054157642Sps/* Prints out information about an mbuf.                                    */
6055157642Sps/*                                                                          */
6056157642Sps/* Returns:                                                                 */
6057157642Sps/*   Nothing.                                                               */
6058157642Sps/****************************************************************************/
6059157642Spsstatic void
6060157642Spsbce_dump_mbuf(struct bce_softc *sc, struct mbuf *m)
6061157642Sps{
6062157642Sps	u32 val_hi, val_lo;
6063157642Sps	struct mbuf *mp = m;
6064157642Sps
6065157642Sps	if (m == NULL) {
6066157642Sps		/* Index out of range. */
6067157642Sps		printf("mbuf ptr is null!\n");
6068157642Sps		return;
6069157642Sps	}
6070157642Sps
6071157642Sps	while (mp) {
6072157642Sps		val_hi = BCE_ADDR_HI(mp);
6073157642Sps		val_lo = BCE_ADDR_LO(mp);
6074157642Sps		BCE_PRINTF(sc, "mbuf: vaddr = 0x%08X:%08X, m_len = %d, m_flags = ",
6075157642Sps			   val_hi, val_lo, mp->m_len);
6076157642Sps
6077157642Sps		if (mp->m_flags & M_EXT)
6078157642Sps			printf("M_EXT ");
6079157642Sps		if (mp->m_flags & M_PKTHDR)
6080157642Sps			printf("M_PKTHDR ");
6081157642Sps		printf("\n");
6082157642Sps
6083157642Sps		if (mp->m_flags & M_EXT) {
6084157642Sps			val_hi = BCE_ADDR_HI(mp->m_ext.ext_buf);
6085157642Sps			val_lo = BCE_ADDR_LO(mp->m_ext.ext_buf);
6086157642Sps			BCE_PRINTF(sc, "- m_ext: vaddr = 0x%08X:%08X, ext_size = 0x%04X\n",
6087157642Sps				val_hi, val_lo, mp->m_ext.ext_size);
6088157642Sps		}
6089157642Sps
6090157642Sps		mp = mp->m_next;
6091157642Sps	}
6092157642Sps
6093157642Sps
6094157642Sps}
6095157642Sps
6096157642Sps
6097157642Sps/****************************************************************************/
6098157642Sps/* Prints out the mbufs in the TX mbuf chain.                               */
6099157642Sps/*                                                                          */
6100157642Sps/* Returns:                                                                 */
6101157642Sps/*   Nothing.                                                               */
6102157642Sps/****************************************************************************/
6103157642Spsstatic void
6104157642Spsbce_dump_tx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count)
6105157642Sps{
6106157642Sps	struct mbuf *m;
6107157642Sps
6108157642Sps	BCE_PRINTF(sc,
6109157642Sps		"----------------------------"
6110157642Sps		"  tx mbuf data  "
6111157642Sps		"----------------------------\n");
6112157642Sps
6113157642Sps	for (int i = 0; i < count; i++) {
6114157642Sps	 	m = sc->tx_mbuf_ptr[chain_prod];
6115157642Sps		BCE_PRINTF(sc, "txmbuf[%d]\n", chain_prod);
6116157642Sps		bce_dump_mbuf(sc, m);
6117157642Sps		chain_prod = TX_CHAIN_IDX(NEXT_TX_BD(chain_prod));
6118157642Sps	}
6119157642Sps
6120157642Sps	BCE_PRINTF(sc,
6121157642Sps		"----------------------------"
6122157642Sps		"----------------"
6123157642Sps		"----------------------------\n");
6124157642Sps}
6125157642Sps
6126157642Sps
6127157642Sps/*
6128157642Sps * This routine prints the RX mbuf chain.
6129157642Sps */
6130157642Spsstatic void
6131157642Spsbce_dump_rx_mbuf_chain(struct bce_softc *sc, int chain_prod, int count)
6132157642Sps{
6133157642Sps	struct mbuf *m;
6134157642Sps
6135157642Sps	BCE_PRINTF(sc,
6136157642Sps		"----------------------------"
6137157642Sps		"  rx mbuf data  "
6138157642Sps		"----------------------------\n");
6139157642Sps
6140157642Sps	for (int i = 0; i < count; i++) {
6141157642Sps	 	m = sc->rx_mbuf_ptr[chain_prod];
6142157642Sps		BCE_PRINTF(sc, "rxmbuf[0x%04X]\n", chain_prod);
6143157642Sps		bce_dump_mbuf(sc, m);
6144157642Sps		chain_prod = RX_CHAIN_IDX(NEXT_RX_BD(chain_prod));
6145157642Sps	}
6146157642Sps
6147157642Sps
6148157642Sps	BCE_PRINTF(sc,
6149157642Sps		"----------------------------"
6150157642Sps		"----------------"
6151157642Sps		"----------------------------\n");
6152157642Sps}
6153157642Sps
6154157642Sps
6155157642Spsstatic void
6156157642Spsbce_dump_txbd(struct bce_softc *sc, int idx, struct tx_bd *txbd)
6157157642Sps{
6158157642Sps	if (idx > MAX_TX_BD)
6159157642Sps		/* Index out of range. */
6160157642Sps		BCE_PRINTF(sc, "tx_bd[0x%04X]: Invalid tx_bd index!\n", idx);
6161157642Sps	else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
6162157642Sps		/* TX Chain page pointer. */
6163157642Sps		BCE_PRINTF(sc, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page pointer\n",
6164157642Sps			idx, txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo);
6165157642Sps	else
6166157642Sps		/* Normal tx_bd entry. */
6167157642Sps		BCE_PRINTF(sc, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = 0x%08X, "
6168157642Sps			"flags = 0x%08X\n", idx,
6169157642Sps			txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo,
6170157642Sps			txbd->tx_bd_mss_nbytes, txbd->tx_bd_vlan_tag_flags);
6171157642Sps}
6172157642Sps
6173157642Sps
6174157642Spsstatic void
6175157642Spsbce_dump_rxbd(struct bce_softc *sc, int idx, struct rx_bd *rxbd)
6176157642Sps{
6177157642Sps	if (idx > MAX_RX_BD)
6178157642Sps		/* Index out of range. */
6179157642Sps		BCE_PRINTF(sc, "rx_bd[0x%04X]: Invalid rx_bd index!\n", idx);
6180157642Sps	else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
6181157642Sps		/* TX Chain page pointer. */
6182157642Sps		BCE_PRINTF(sc, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page pointer\n",
6183157642Sps			idx, rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo);
6184157642Sps	else
6185157642Sps		/* Normal tx_bd entry. */
6186157642Sps		BCE_PRINTF(sc, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = 0x%08X, "
6187157642Sps			"flags = 0x%08X\n", idx,
6188157642Sps			rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo,
6189157642Sps			rxbd->rx_bd_len, rxbd->rx_bd_flags);
6190157642Sps}
6191157642Sps
6192157642Sps
6193157642Spsstatic void
6194157642Spsbce_dump_l2fhdr(struct bce_softc *sc, int idx, struct l2_fhdr *l2fhdr)
6195157642Sps{
6196157642Sps	BCE_PRINTF(sc, "l2_fhdr[0x%04X]: status = 0x%08X, "
6197157642Sps		"pkt_len = 0x%04X, vlan = 0x%04x, ip_xsum = 0x%04X, "
6198157642Sps		"tcp_udp_xsum = 0x%04X\n", idx,
6199157642Sps		l2fhdr->l2_fhdr_status, l2fhdr->l2_fhdr_pkt_len,
6200157642Sps		l2fhdr->l2_fhdr_vlan_tag, l2fhdr->l2_fhdr_ip_xsum,
6201157642Sps		l2fhdr->l2_fhdr_tcp_udp_xsum);
6202157642Sps}
6203157642Sps
6204157642Sps
6205157642Sps/*
6206157642Sps * This routine prints the TX chain.
6207157642Sps */
6208157642Spsstatic void
6209157642Spsbce_dump_tx_chain(struct bce_softc *sc, int tx_prod, int count)
6210157642Sps{
6211157642Sps	struct tx_bd *txbd;
6212157642Sps
6213157642Sps	/* First some info about the tx_bd chain structure. */
6214157642Sps	BCE_PRINTF(sc,
6215157642Sps		"----------------------------"
6216157642Sps		"  tx_bd  chain  "
6217157642Sps		"----------------------------\n");
6218157642Sps
6219157642Sps	BCE_PRINTF(sc, "page size      = 0x%08X, tx chain pages        = 0x%08X\n",
6220157642Sps		(u32) BCM_PAGE_SIZE, (u32) TX_PAGES);
6221157642Sps
6222157642Sps	BCE_PRINTF(sc, "tx_bd per page = 0x%08X, usable tx_bd per page = 0x%08X\n",
6223157642Sps		(u32) TOTAL_TX_BD_PER_PAGE, (u32) USABLE_TX_BD_PER_PAGE);
6224157642Sps
6225157642Sps	BCE_PRINTF(sc, "total tx_bd    = 0x%08X\n", (u32) TOTAL_TX_BD);
6226157642Sps
6227157642Sps	BCE_PRINTF(sc, ""
6228157642Sps		"-----------------------------"
6229157642Sps		"   tx_bd data   "
6230157642Sps		"-----------------------------\n");
6231157642Sps
6232157642Sps	/* Now print out the tx_bd's themselves. */
6233157642Sps	for (int i = 0; i < count; i++) {
6234157642Sps	 	txbd = &sc->tx_bd_chain[TX_PAGE(tx_prod)][TX_IDX(tx_prod)];
6235157642Sps		bce_dump_txbd(sc, tx_prod, txbd);
6236157642Sps		tx_prod = TX_CHAIN_IDX(NEXT_TX_BD(tx_prod));
6237157642Sps	}
6238157642Sps
6239157642Sps	BCE_PRINTF(sc,
6240157642Sps		"-----------------------------"
6241157642Sps		"--------------"
6242157642Sps		"-----------------------------\n");
6243157642Sps}
6244157642Sps
6245157642Sps
6246157642Sps/*
6247157642Sps * This routine prints the RX chain.
6248157642Sps */
6249157642Spsstatic void
6250157642Spsbce_dump_rx_chain(struct bce_softc *sc, int rx_prod, int count)
6251157642Sps{
6252157642Sps	struct rx_bd *rxbd;
6253157642Sps
6254157642Sps	/* First some info about the tx_bd chain structure. */
6255157642Sps	BCE_PRINTF(sc,
6256157642Sps		"----------------------------"
6257157642Sps		"  rx_bd  chain  "
6258157642Sps		"----------------------------\n");
6259157642Sps
6260157642Sps	BCE_PRINTF(sc, "----- RX_BD Chain -----\n");
6261157642Sps
6262157642Sps	BCE_PRINTF(sc, "page size      = 0x%08X, rx chain pages        = 0x%08X\n",
6263157642Sps		(u32) BCM_PAGE_SIZE, (u32) RX_PAGES);
6264157642Sps
6265157642Sps	BCE_PRINTF(sc, "rx_bd per page = 0x%08X, usable rx_bd per page = 0x%08X\n",
6266157642Sps		(u32) TOTAL_RX_BD_PER_PAGE, (u32) USABLE_RX_BD_PER_PAGE);
6267157642Sps
6268157642Sps	BCE_PRINTF(sc, "total rx_bd    = 0x%08X\n", (u32) TOTAL_RX_BD);
6269157642Sps
6270157642Sps	BCE_PRINTF(sc,
6271157642Sps		"----------------------------"
6272157642Sps		"   rx_bd data   "
6273157642Sps		"----------------------------\n");
6274157642Sps
6275157642Sps	/* Now print out the rx_bd's themselves. */
6276157642Sps	for (int i = 0; i < count; i++) {
6277157642Sps		rxbd = &sc->rx_bd_chain[RX_PAGE(rx_prod)][RX_IDX(rx_prod)];
6278157642Sps		bce_dump_rxbd(sc, rx_prod, rxbd);
6279157642Sps		rx_prod = RX_CHAIN_IDX(NEXT_RX_BD(rx_prod));
6280157642Sps	}
6281157642Sps
6282157642Sps	BCE_PRINTF(sc,
6283157642Sps		"----------------------------"
6284157642Sps		"--------------"
6285157642Sps		"----------------------------\n");
6286157642Sps}
6287157642Sps
6288157642Sps
6289157642Sps/*
6290157642Sps * This routine prints the status block.
6291157642Sps */
6292157642Spsstatic void
6293157642Spsbce_dump_status_block(struct bce_softc *sc)
6294157642Sps{
6295157642Sps	struct status_block *sblk;
6296157642Sps
6297157642Sps	sblk = sc->status_block;
6298157642Sps
6299157642Sps   	BCE_PRINTF(sc, "----------------------------- Status Block "
6300157642Sps		"-----------------------------\n");
6301157642Sps
6302157642Sps	BCE_PRINTF(sc, "attn_bits  = 0x%08X, attn_bits_ack = 0x%08X, index = 0x%04X\n",
6303157642Sps		sblk->status_attn_bits, sblk->status_attn_bits_ack,
6304157642Sps		sblk->status_idx);
6305157642Sps
6306157642Sps	BCE_PRINTF(sc, "rx_cons0   = 0x%08X, tx_cons0      = 0x%08X\n",
6307157642Sps		sblk->status_rx_quick_consumer_index0,
6308157642Sps		sblk->status_tx_quick_consumer_index0);
6309157642Sps
6310157642Sps	BCE_PRINTF(sc, "status_idx = 0x%04X\n", sblk->status_idx);
6311157642Sps
6312157642Sps	/* Theses indices are not used for normal L2 drivers. */
6313157642Sps	if (sblk->status_rx_quick_consumer_index1 ||
6314157642Sps		sblk->status_tx_quick_consumer_index1)
6315157642Sps		BCE_PRINTF(sc, "rx_cons1  = 0x%08X, tx_cons1      = 0x%08X\n",
6316157642Sps			sblk->status_rx_quick_consumer_index1,
6317157642Sps			sblk->status_tx_quick_consumer_index1);
6318157642Sps
6319157642Sps	if (sblk->status_rx_quick_consumer_index2 ||
6320157642Sps		sblk->status_tx_quick_consumer_index2)
6321157642Sps		BCE_PRINTF(sc, "rx_cons2  = 0x%08X, tx_cons2      = 0x%08X\n",
6322157642Sps			sblk->status_rx_quick_consumer_index2,
6323157642Sps			sblk->status_tx_quick_consumer_index2);
6324157642Sps
6325157642Sps	if (sblk->status_rx_quick_consumer_index3 ||
6326157642Sps		sblk->status_tx_quick_consumer_index3)
6327157642Sps		BCE_PRINTF(sc, "rx_cons3  = 0x%08X, tx_cons3      = 0x%08X\n",
6328157642Sps			sblk->status_rx_quick_consumer_index3,
6329157642Sps			sblk->status_tx_quick_consumer_index3);
6330157642Sps
6331157642Sps	if (sblk->status_rx_quick_consumer_index4 ||
6332157642Sps		sblk->status_rx_quick_consumer_index5)
6333157642Sps		BCE_PRINTF(sc, "rx_cons4  = 0x%08X, rx_cons5      = 0x%08X\n",
6334157642Sps			sblk->status_rx_quick_consumer_index4,
6335157642Sps			sblk->status_rx_quick_consumer_index5);
6336157642Sps
6337157642Sps	if (sblk->status_rx_quick_consumer_index6 ||
6338157642Sps		sblk->status_rx_quick_consumer_index7)
6339157642Sps		BCE_PRINTF(sc, "rx_cons6  = 0x%08X, rx_cons7      = 0x%08X\n",
6340157642Sps			sblk->status_rx_quick_consumer_index6,
6341157642Sps			sblk->status_rx_quick_consumer_index7);
6342157642Sps
6343157642Sps	if (sblk->status_rx_quick_consumer_index8 ||
6344157642Sps		sblk->status_rx_quick_consumer_index9)
6345157642Sps		BCE_PRINTF(sc, "rx_cons8  = 0x%08X, rx_cons9      = 0x%08X\n",
6346157642Sps			sblk->status_rx_quick_consumer_index8,
6347157642Sps			sblk->status_rx_quick_consumer_index9);
6348157642Sps
6349157642Sps	if (sblk->status_rx_quick_consumer_index10 ||
6350157642Sps		sblk->status_rx_quick_consumer_index11)
6351157642Sps		BCE_PRINTF(sc, "rx_cons10 = 0x%08X, rx_cons11     = 0x%08X\n",
6352157642Sps			sblk->status_rx_quick_consumer_index10,
6353157642Sps			sblk->status_rx_quick_consumer_index11);
6354157642Sps
6355157642Sps	if (sblk->status_rx_quick_consumer_index12 ||
6356157642Sps		sblk->status_rx_quick_consumer_index13)
6357157642Sps		BCE_PRINTF(sc, "rx_cons12 = 0x%08X, rx_cons13     = 0x%08X\n",
6358157642Sps			sblk->status_rx_quick_consumer_index12,
6359157642Sps			sblk->status_rx_quick_consumer_index13);
6360157642Sps
6361157642Sps	if (sblk->status_rx_quick_consumer_index14 ||
6362157642Sps		sblk->status_rx_quick_consumer_index15)
6363157642Sps		BCE_PRINTF(sc, "rx_cons14 = 0x%08X, rx_cons15     = 0x%08X\n",
6364157642Sps			sblk->status_rx_quick_consumer_index14,
6365157642Sps			sblk->status_rx_quick_consumer_index15);
6366157642Sps
6367157642Sps	if (sblk->status_completion_producer_index ||
6368157642Sps		sblk->status_cmd_consumer_index)
6369157642Sps		BCE_PRINTF(sc, "com_prod  = 0x%08X, cmd_cons      = 0x%08X\n",
6370157642Sps			sblk->status_completion_producer_index,
6371157642Sps			sblk->status_cmd_consumer_index);
6372157642Sps
6373157642Sps	BCE_PRINTF(sc, "-------------------------------------------"
6374157642Sps		"-----------------------------\n");
6375157642Sps}
6376157642Sps
6377157642Sps
6378157642Sps/*
6379157642Sps * This routine prints the statistics block.
6380157642Sps */
6381157642Spsstatic void
6382157642Spsbce_dump_stats_block(struct bce_softc *sc)
6383157642Sps{
6384157642Sps	struct statistics_block *sblk;
6385157642Sps
6386157642Sps	sblk = sc->stats_block;
6387157642Sps
6388157642Sps	BCE_PRINTF(sc, ""
6389157642Sps		"-----------------------------"
6390157642Sps		" Stats  Block "
6391157642Sps		"-----------------------------\n");
6392157642Sps
6393157642Sps	BCE_PRINTF(sc, "IfHcInOctets         = 0x%08X:%08X, "
6394157642Sps		"IfHcInBadOctets      = 0x%08X:%08X\n",
6395157642Sps		sblk->stat_IfHCInOctets_hi, sblk->stat_IfHCInOctets_lo,
6396157642Sps		sblk->stat_IfHCInBadOctets_hi, sblk->stat_IfHCInBadOctets_lo);
6397157642Sps
6398157642Sps	BCE_PRINTF(sc, "IfHcOutOctets        = 0x%08X:%08X, "
6399157642Sps		"IfHcOutBadOctets     = 0x%08X:%08X\n",
6400157642Sps		sblk->stat_IfHCOutOctets_hi, sblk->stat_IfHCOutOctets_lo,
6401157642Sps		sblk->stat_IfHCOutBadOctets_hi, sblk->stat_IfHCOutBadOctets_lo);
6402157642Sps
6403157642Sps	BCE_PRINTF(sc, "IfHcInUcastPkts      = 0x%08X:%08X, "
6404157642Sps		"IfHcInMulticastPkts  = 0x%08X:%08X\n",
6405157642Sps		sblk->stat_IfHCInUcastPkts_hi, sblk->stat_IfHCInUcastPkts_lo,
6406157642Sps		sblk->stat_IfHCInMulticastPkts_hi, sblk->stat_IfHCInMulticastPkts_lo);
6407157642Sps
6408157642Sps	BCE_PRINTF(sc, "IfHcInBroadcastPkts  = 0x%08X:%08X, "
6409157642Sps		"IfHcOutUcastPkts     = 0x%08X:%08X\n",
6410157642Sps		sblk->stat_IfHCInBroadcastPkts_hi, sblk->stat_IfHCInBroadcastPkts_lo,
6411157642Sps		sblk->stat_IfHCOutUcastPkts_hi, sblk->stat_IfHCOutUcastPkts_lo);
6412157642Sps
6413157642Sps	BCE_PRINTF(sc, "IfHcOutMulticastPkts = 0x%08X:%08X, IfHcOutBroadcastPkts = 0x%08X:%08X\n",
6414157642Sps		sblk->stat_IfHCOutMulticastPkts_hi, sblk->stat_IfHCOutMulticastPkts_lo,
6415157642Sps		sblk->stat_IfHCOutBroadcastPkts_hi, sblk->stat_IfHCOutBroadcastPkts_lo);
6416157642Sps
6417157642Sps	if (sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors)
6418157642Sps		BCE_PRINTF(sc, "0x%08X : "
6419157642Sps		"emac_tx_stat_dot3statsinternalmactransmiterrors\n",
6420157642Sps		sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors);
6421157642Sps
6422157642Sps	if (sblk->stat_Dot3StatsCarrierSenseErrors)
6423157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsCarrierSenseErrors\n",
6424157642Sps			sblk->stat_Dot3StatsCarrierSenseErrors);
6425157642Sps
6426157642Sps	if (sblk->stat_Dot3StatsFCSErrors)
6427157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsFCSErrors\n",
6428157642Sps			sblk->stat_Dot3StatsFCSErrors);
6429157642Sps
6430157642Sps	if (sblk->stat_Dot3StatsAlignmentErrors)
6431157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsAlignmentErrors\n",
6432157642Sps			sblk->stat_Dot3StatsAlignmentErrors);
6433157642Sps
6434157642Sps	if (sblk->stat_Dot3StatsSingleCollisionFrames)
6435157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsSingleCollisionFrames\n",
6436157642Sps			sblk->stat_Dot3StatsSingleCollisionFrames);
6437157642Sps
6438157642Sps	if (sblk->stat_Dot3StatsMultipleCollisionFrames)
6439157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsMultipleCollisionFrames\n",
6440157642Sps			sblk->stat_Dot3StatsMultipleCollisionFrames);
6441157642Sps
6442157642Sps	if (sblk->stat_Dot3StatsDeferredTransmissions)
6443157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsDeferredTransmissions\n",
6444157642Sps			sblk->stat_Dot3StatsDeferredTransmissions);
6445157642Sps
6446157642Sps	if (sblk->stat_Dot3StatsExcessiveCollisions)
6447157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsExcessiveCollisions\n",
6448157642Sps			sblk->stat_Dot3StatsExcessiveCollisions);
6449157642Sps
6450157642Sps	if (sblk->stat_Dot3StatsLateCollisions)
6451157642Sps		BCE_PRINTF(sc, "0x%08X : Dot3StatsLateCollisions\n",
6452157642Sps			sblk->stat_Dot3StatsLateCollisions);
6453157642Sps
6454157642Sps	if (sblk->stat_EtherStatsCollisions)
6455157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsCollisions\n",
6456157642Sps			sblk->stat_EtherStatsCollisions);
6457157642Sps
6458157642Sps	if (sblk->stat_EtherStatsFragments)
6459157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsFragments\n",
6460157642Sps			sblk->stat_EtherStatsFragments);
6461157642Sps
6462157642Sps	if (sblk->stat_EtherStatsJabbers)
6463157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsJabbers\n",
6464157642Sps			sblk->stat_EtherStatsJabbers);
6465157642Sps
6466157642Sps	if (sblk->stat_EtherStatsUndersizePkts)
6467157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsUndersizePkts\n",
6468157642Sps			sblk->stat_EtherStatsUndersizePkts);
6469157642Sps
6470157642Sps	if (sblk->stat_EtherStatsOverrsizePkts)
6471157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsOverrsizePkts\n",
6472157642Sps			sblk->stat_EtherStatsOverrsizePkts);
6473157642Sps
6474157642Sps	if (sblk->stat_EtherStatsPktsRx64Octets)
6475157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx64Octets\n",
6476157642Sps			sblk->stat_EtherStatsPktsRx64Octets);
6477157642Sps
6478157642Sps	if (sblk->stat_EtherStatsPktsRx65Octetsto127Octets)
6479157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx65Octetsto127Octets\n",
6480157642Sps			sblk->stat_EtherStatsPktsRx65Octetsto127Octets);
6481157642Sps
6482157642Sps	if (sblk->stat_EtherStatsPktsRx128Octetsto255Octets)
6483157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx128Octetsto255Octets\n",
6484157642Sps			sblk->stat_EtherStatsPktsRx128Octetsto255Octets);
6485157642Sps
6486157642Sps	if (sblk->stat_EtherStatsPktsRx256Octetsto511Octets)
6487157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx256Octetsto511Octets\n",
6488157642Sps			sblk->stat_EtherStatsPktsRx256Octetsto511Octets);
6489157642Sps
6490157642Sps	if (sblk->stat_EtherStatsPktsRx512Octetsto1023Octets)
6491157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx512Octetsto1023Octets\n",
6492157642Sps			sblk->stat_EtherStatsPktsRx512Octetsto1023Octets);
6493157642Sps
6494157642Sps	if (sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets)
6495157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx1024Octetsto1522Octets\n",
6496157642Sps			sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets);
6497157642Sps
6498157642Sps	if (sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets)
6499157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsRx1523Octetsto9022Octets\n",
6500157642Sps			sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets);
6501157642Sps
6502157642Sps	if (sblk->stat_EtherStatsPktsTx64Octets)
6503157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx64Octets\n",
6504157642Sps			sblk->stat_EtherStatsPktsTx64Octets);
6505157642Sps
6506157642Sps	if (sblk->stat_EtherStatsPktsTx65Octetsto127Octets)
6507157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx65Octetsto127Octets\n",
6508157642Sps			sblk->stat_EtherStatsPktsTx65Octetsto127Octets);
6509157642Sps
6510157642Sps	if (sblk->stat_EtherStatsPktsTx128Octetsto255Octets)
6511157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx128Octetsto255Octets\n",
6512157642Sps			sblk->stat_EtherStatsPktsTx128Octetsto255Octets);
6513157642Sps
6514157642Sps	if (sblk->stat_EtherStatsPktsTx256Octetsto511Octets)
6515157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx256Octetsto511Octets\n",
6516157642Sps			sblk->stat_EtherStatsPktsTx256Octetsto511Octets);
6517157642Sps
6518157642Sps	if (sblk->stat_EtherStatsPktsTx512Octetsto1023Octets)
6519157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx512Octetsto1023Octets\n",
6520157642Sps			sblk->stat_EtherStatsPktsTx512Octetsto1023Octets);
6521157642Sps
6522157642Sps	if (sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets)
6523157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx1024Octetsto1522Octets\n",
6524157642Sps			sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets);
6525157642Sps
6526157642Sps	if (sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets)
6527157642Sps		BCE_PRINTF(sc, "0x%08X : EtherStatsPktsTx1523Octetsto9022Octets\n",
6528157642Sps			sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets);
6529157642Sps
6530157642Sps	if (sblk->stat_XonPauseFramesReceived)
6531157642Sps		BCE_PRINTF(sc, "0x%08X : XonPauseFramesReceived\n",
6532157642Sps			sblk->stat_XonPauseFramesReceived);
6533157642Sps
6534157642Sps	if (sblk->stat_XoffPauseFramesReceived)
6535157642Sps	   BCE_PRINTF(sc, "0x%08X : XoffPauseFramesReceived\n",
6536157642Sps			sblk->stat_XoffPauseFramesReceived);
6537157642Sps
6538157642Sps	if (sblk->stat_OutXonSent)
6539157642Sps		BCE_PRINTF(sc, "0x%08X : OutXonSent\n",
6540157642Sps			sblk->stat_OutXonSent);
6541157642Sps
6542157642Sps	if (sblk->stat_OutXoffSent)
6543157642Sps		BCE_PRINTF(sc, "0x%08X : OutXoffSent\n",
6544157642Sps			sblk->stat_OutXoffSent);
6545157642Sps
6546157642Sps	if (sblk->stat_FlowControlDone)
6547157642Sps		BCE_PRINTF(sc, "0x%08X : FlowControlDone\n",
6548157642Sps			sblk->stat_FlowControlDone);
6549157642Sps
6550157642Sps	if (sblk->stat_MacControlFramesReceived)
6551157642Sps		BCE_PRINTF(sc, "0x%08X : MacControlFramesReceived\n",
6552157642Sps			sblk->stat_MacControlFramesReceived);
6553157642Sps
6554157642Sps	if (sblk->stat_XoffStateEntered)
6555157642Sps		BCE_PRINTF(sc, "0x%08X : XoffStateEntered\n",
6556157642Sps			sblk->stat_XoffStateEntered);
6557157642Sps
6558157642Sps	if (sblk->stat_IfInFramesL2FilterDiscards)
6559157642Sps		BCE_PRINTF(sc, "0x%08X : IfInFramesL2FilterDiscards\n",
6560157642Sps			sblk->stat_IfInFramesL2FilterDiscards);
6561157642Sps
6562157642Sps	if (sblk->stat_IfInRuleCheckerDiscards)
6563157642Sps		BCE_PRINTF(sc, "0x%08X : IfInRuleCheckerDiscards\n",
6564157642Sps			sblk->stat_IfInRuleCheckerDiscards);
6565157642Sps
6566157642Sps	if (sblk->stat_IfInFTQDiscards)
6567157642Sps		BCE_PRINTF(sc, "0x%08X : IfInFTQDiscards\n",
6568157642Sps			sblk->stat_IfInFTQDiscards);
6569157642Sps
6570157642Sps	if (sblk->stat_IfInMBUFDiscards)
6571157642Sps		BCE_PRINTF(sc, "0x%08X : IfInMBUFDiscards\n",
6572157642Sps			sblk->stat_IfInMBUFDiscards);
6573157642Sps
6574157642Sps	if (sblk->stat_IfInRuleCheckerP4Hit)
6575157642Sps		BCE_PRINTF(sc, "0x%08X : IfInRuleCheckerP4Hit\n",
6576157642Sps			sblk->stat_IfInRuleCheckerP4Hit);
6577157642Sps
6578157642Sps	if (sblk->stat_CatchupInRuleCheckerDiscards)
6579157642Sps		BCE_PRINTF(sc, "0x%08X : CatchupInRuleCheckerDiscards\n",
6580157642Sps			sblk->stat_CatchupInRuleCheckerDiscards);
6581157642Sps
6582157642Sps	if (sblk->stat_CatchupInFTQDiscards)
6583157642Sps		BCE_PRINTF(sc, "0x%08X : CatchupInFTQDiscards\n",
6584157642Sps			sblk->stat_CatchupInFTQDiscards);
6585157642Sps
6586157642Sps	if (sblk->stat_CatchupInMBUFDiscards)
6587157642Sps		BCE_PRINTF(sc, "0x%08X : CatchupInMBUFDiscards\n",
6588157642Sps			sblk->stat_CatchupInMBUFDiscards);
6589157642Sps
6590157642Sps	if (sblk->stat_CatchupInRuleCheckerP4Hit)
6591157642Sps		BCE_PRINTF(sc, "0x%08X : CatchupInRuleCheckerP4Hit\n",
6592157642Sps			sblk->stat_CatchupInRuleCheckerP4Hit);
6593157642Sps
6594157642Sps	BCE_PRINTF(sc,
6595157642Sps		"-----------------------------"
6596157642Sps		"--------------"
6597157642Sps		"-----------------------------\n");
6598157642Sps}
6599157642Sps
6600157642Sps
6601157642Spsstatic void
6602157642Spsbce_dump_driver_state(struct bce_softc *sc)
6603157642Sps{
6604157642Sps	u32 val_hi, val_lo;
6605157642Sps
6606157642Sps	BCE_PRINTF(sc,
6607157642Sps		"-----------------------------"
6608157642Sps		" Driver State "
6609157642Sps		"-----------------------------\n");
6610157642Sps
6611157642Sps	val_hi = BCE_ADDR_HI(sc);
6612157642Sps	val_lo = BCE_ADDR_LO(sc);
6613157642Sps	BCE_PRINTF(sc, "0x%08X:%08X - (sc) driver softc structure virtual address\n",
6614157642Sps		val_hi, val_lo);
6615157642Sps
6616157642Sps	val_hi = BCE_ADDR_HI(sc->bce_vhandle);
6617157642Sps	val_lo = BCE_ADDR_LO(sc->bce_vhandle);
6618157642Sps	BCE_PRINTF(sc, "0x%08X:%08X - (sc->bce_vhandle) PCI BAR virtual address\n",
6619157642Sps		val_hi, val_lo);
6620157642Sps
6621157642Sps	val_hi = BCE_ADDR_HI(sc->status_block);
6622157642Sps	val_lo = BCE_ADDR_LO(sc->status_block);
6623157642Sps	BCE_PRINTF(sc, "0x%08X:%08X - (sc->status_block) status block virtual address\n",
6624157642Sps		val_hi, val_lo);
6625157642Sps
6626157642Sps	val_hi = BCE_ADDR_HI(sc->stats_block);
6627157642Sps	val_lo = BCE_ADDR_LO(sc->stats_block);
6628157642Sps	BCE_PRINTF(sc, "0x%08X:%08X - (sc->stats_block) statistics block virtual address\n",
6629157642Sps		val_hi, val_lo);
6630157642Sps
6631157642Sps	val_hi = BCE_ADDR_HI(sc->tx_bd_chain);
6632157642Sps	val_lo = BCE_ADDR_LO(sc->tx_bd_chain);
6633157642Sps	BCE_PRINTF(sc,
6634157642Sps		"0x%08X:%08X - (sc->tx_bd_chain) tx_bd chain virtual adddress\n",
6635157642Sps		val_hi, val_lo);
6636157642Sps
6637157642Sps	val_hi = BCE_ADDR_HI(sc->rx_bd_chain);
6638157642Sps	val_lo = BCE_ADDR_LO(sc->rx_bd_chain);
6639157642Sps	BCE_PRINTF(sc,
6640157642Sps		"0x%08X:%08X - (sc->rx_bd_chain) rx_bd chain virtual address\n",
6641157642Sps		val_hi, val_lo);
6642157642Sps
6643157642Sps	val_hi = BCE_ADDR_HI(sc->tx_mbuf_ptr);
6644157642Sps	val_lo = BCE_ADDR_LO(sc->tx_mbuf_ptr);
6645157642Sps	BCE_PRINTF(sc,
6646157642Sps		"0x%08X:%08X - (sc->tx_mbuf_ptr) tx mbuf chain virtual address\n",
6647157642Sps		val_hi, val_lo);
6648157642Sps
6649157642Sps	val_hi = BCE_ADDR_HI(sc->rx_mbuf_ptr);
6650157642Sps	val_lo = BCE_ADDR_LO(sc->rx_mbuf_ptr);
6651157642Sps	BCE_PRINTF(sc,
6652157642Sps		"0x%08X:%08X - (sc->rx_mbuf_ptr) rx mbuf chain virtual address\n",
6653157642Sps		val_hi, val_lo);
6654157642Sps
6655157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->interrupts_generated) h/w intrs\n",
6656157642Sps		sc->interrupts_generated);
6657157642Sps
6658157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->rx_interrupts) rx interrupts handled\n",
6659157642Sps		sc->rx_interrupts);
6660157642Sps
6661157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->tx_interrupts) tx interrupts handled\n",
6662157642Sps		sc->tx_interrupts);
6663157642Sps
6664157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->last_status_idx) status block index\n",
6665157642Sps		sc->last_status_idx);
6666157642Sps
6667157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->tx_prod) tx producer index\n",
6668157642Sps		sc->tx_prod);
6669157642Sps
6670157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->tx_cons) tx consumer index\n",
6671157642Sps		sc->tx_cons);
6672157642Sps
6673157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->tx_prod_bseq) tx producer bseq index\n",
6674157642Sps		sc->tx_prod_bseq);
6675157642Sps
6676157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->rx_prod) rx producer index\n",
6677157642Sps		sc->rx_prod);
6678157642Sps
6679157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->rx_cons) rx consumer index\n",
6680157642Sps		sc->rx_cons);
6681157642Sps
6682157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->rx_prod_bseq) rx producer bseq index\n",
6683157642Sps		sc->rx_prod_bseq);
6684157642Sps
6685157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->rx_mbuf_alloc) rx mbufs allocated\n",
6686157642Sps		sc->rx_mbuf_alloc);
6687157642Sps
6688157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->free_rx_bd) free rx_bd's\n",
6689157642Sps		sc->free_rx_bd);
6690157642Sps
6691157642Sps	BCE_PRINTF(sc, "0x%08X/%08X - (sc->rx_low_watermark) rx low watermark\n",
6692157642Sps		sc->rx_low_watermark, (u32) USABLE_RX_BD);
6693157642Sps
6694157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->txmbuf_alloc) tx mbufs allocated\n",
6695157642Sps		sc->tx_mbuf_alloc);
6696157642Sps
6697157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->rx_mbuf_alloc) rx mbufs allocated\n",
6698157642Sps		sc->rx_mbuf_alloc);
6699157642Sps
6700157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->used_tx_bd) used tx_bd's\n",
6701157642Sps		sc->used_tx_bd);
6702157642Sps
6703157642Sps	BCE_PRINTF(sc, "0x%08X/%08X - (sc->tx_hi_watermark) tx hi watermark\n",
6704157642Sps		sc->tx_hi_watermark, (u32) USABLE_TX_BD);
6705157642Sps
6706157642Sps	BCE_PRINTF(sc, "         0x%08X - (sc->mbuf_alloc_failed) failed mbuf alloc\n",
6707157642Sps		sc->mbuf_alloc_failed);
6708157642Sps
6709157642Sps	BCE_PRINTF(sc,
6710157642Sps		"-----------------------------"
6711157642Sps		"--------------"
6712157642Sps		"-----------------------------\n");
6713157642Sps}
6714157642Sps
6715157642Sps
6716157642Spsstatic void
6717157642Spsbce_dump_hw_state(struct bce_softc *sc)
6718157642Sps{
6719157642Sps	u32 val1;
6720157642Sps
6721157642Sps	BCE_PRINTF(sc,
6722157642Sps		"----------------------------"
6723157642Sps		" Hardware State "
6724157642Sps		"----------------------------\n");
6725157642Sps
6726157642Sps	BCE_PRINTF(sc, "0x%08X : bootcode version\n", sc->bce_fw_ver);
6727157642Sps
6728157642Sps	val1 = REG_RD(sc, BCE_MISC_ENABLE_STATUS_BITS);
6729157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) misc_enable_status_bits\n",
6730157642Sps		val1, BCE_MISC_ENABLE_STATUS_BITS);
6731157642Sps
6732157642Sps	val1 = REG_RD(sc, BCE_DMA_STATUS);
6733157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) dma_status\n", val1, BCE_DMA_STATUS);
6734157642Sps
6735157642Sps	val1 = REG_RD(sc, BCE_CTX_STATUS);
6736157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) ctx_status\n", val1, BCE_CTX_STATUS);
6737157642Sps
6738157642Sps	val1 = REG_RD(sc, BCE_EMAC_STATUS);
6739157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) emac_status\n", val1, BCE_EMAC_STATUS);
6740157642Sps
6741157642Sps	val1 = REG_RD(sc, BCE_RPM_STATUS);
6742157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) rpm_status\n", val1, BCE_RPM_STATUS);
6743157642Sps
6744157642Sps	val1 = REG_RD(sc, BCE_TBDR_STATUS);
6745157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) tbdr_status\n", val1, BCE_TBDR_STATUS);
6746157642Sps
6747157642Sps	val1 = REG_RD(sc, BCE_TDMA_STATUS);
6748157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) tdma_status\n", val1, BCE_TDMA_STATUS);
6749157642Sps
6750157642Sps	val1 = REG_RD(sc, BCE_HC_STATUS);
6751157642Sps	BCE_PRINTF(sc, "0x%08X : (0x%04X) hc_status\n", val1, BCE_HC_STATUS);
6752157642Sps
6753157642Sps	BCE_PRINTF(sc,
6754157642Sps		"----------------------------"
6755157642Sps		"----------------"
6756157642Sps		"----------------------------\n");
6757157642Sps
6758157642Sps	BCE_PRINTF(sc,
6759157642Sps		"----------------------------"
6760157642Sps		" Register  Dump "
6761157642Sps		"----------------------------\n");
6762157642Sps
6763157642Sps	for (int i = 0x400; i < 0x8000; i += 0x10)
6764157642Sps		BCE_PRINTF(sc, "0x%04X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
6765157642Sps			i, REG_RD(sc, i), REG_RD(sc, i + 0x4),
6766157642Sps			REG_RD(sc, i + 0x8), REG_RD(sc, i + 0xC));
6767157642Sps
6768157642Sps	BCE_PRINTF(sc,
6769157642Sps		"----------------------------"
6770157642Sps		"----------------"
6771157642Sps		"----------------------------\n");
6772157642Sps}
6773157642Sps
6774157642Sps
6775157642Spsstatic void
6776157642Spsbce_breakpoint(struct bce_softc *sc)
6777157642Sps{
6778157642Sps
6779157642Sps	/* Unreachable code to shut the compiler up about unused functions. */
6780157642Sps	if (0) {
6781157642Sps   		bce_dump_txbd(sc, 0, NULL);
6782157642Sps		bce_dump_rxbd(sc, 0, NULL);
6783157642Sps		bce_dump_tx_mbuf_chain(sc, 0, USABLE_TX_BD);
6784157642Sps		bce_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD);
6785157642Sps		bce_dump_l2fhdr(sc, 0, NULL);
6786157642Sps		bce_dump_tx_chain(sc, 0, USABLE_TX_BD);
6787157642Sps		bce_dump_rx_chain(sc, 0, USABLE_RX_BD);
6788157642Sps		bce_dump_status_block(sc);
6789157642Sps		bce_dump_stats_block(sc);
6790157642Sps		bce_dump_driver_state(sc);
6791157642Sps		bce_dump_hw_state(sc);
6792157642Sps	}
6793157642Sps
6794157642Sps	bce_dump_driver_state(sc);
6795157642Sps	/* Print the important status block fields. */
6796157642Sps	bce_dump_status_block(sc);
6797157642Sps
6798157642Sps	/* Call the debugger. */
6799157642Sps	breakpoint();
6800157642Sps
6801157642Sps	return;
6802157642Sps}
6803157642Sps#endif
6804