Annotation of sys/dev/pci/if_bnx.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_bnx.c,v 1.53 2007/07/04 00:20:22 krw Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2006 Broadcom Corporation
! 5: * David Christensen <davidch@broadcom.com>. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: *
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. Neither the name of Broadcom Corporation nor the name of its contributors
! 17: * may be used to endorse or promote products derived from this software
! 18: * without specific prior written consent.
! 19: *
! 20: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
! 21: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 23: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
! 24: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 25: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 26: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 27: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 28: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 29: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 30: * THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: #if 0
! 34: #include <sys/cdefs.h>
! 35: __FBSDID("$FreeBSD: src/sys/dev/bce/if_bce.c,v 1.3 2006/04/13 14:12:26 ru Exp $");
! 36: #endif
! 37:
! 38: /*
! 39: * The following controllers are supported by this driver:
! 40: * BCM5706C A2, A3
! 41: * BCM5708C B1
! 42: *
! 43: * The following controllers are not supported by this driver:
! 44: * (These are not "Production" versions of the controller.)
! 45: *
! 46: * BCM5706C A0, A1
! 47: * BCM5706S A0, A1, A2, A3
! 48: * BCM5708C A0, B0
! 49: * BCM5708S A0, B0, B1
! 50: */
! 51:
! 52: #include <dev/pci/if_bnxreg.h>
! 53:
! 54: int bnx_COM_b06FwReleaseMajor;
! 55: int bnx_COM_b06FwReleaseMinor;
! 56: int bnx_COM_b06FwReleaseFix;
! 57: u_int32_t bnx_COM_b06FwStartAddr;
! 58: u_int32_t bnx_COM_b06FwTextAddr;
! 59: int bnx_COM_b06FwTextLen;
! 60: u_int32_t bnx_COM_b06FwDataAddr;
! 61: int bnx_COM_b06FwDataLen;
! 62: u_int32_t bnx_COM_b06FwRodataAddr;
! 63: int bnx_COM_b06FwRodataLen;
! 64: u_int32_t bnx_COM_b06FwBssAddr;
! 65: int bnx_COM_b06FwBssLen;
! 66: u_int32_t bnx_COM_b06FwSbssAddr;
! 67: int bnx_COM_b06FwSbssLen;
! 68:
! 69: int bnx_RXP_b06FwReleaseMajor;
! 70: int bnx_RXP_b06FwReleaseMinor;
! 71: int bnx_RXP_b06FwReleaseFix;
! 72: u_int32_t bnx_RXP_b06FwStartAddr;
! 73: u_int32_t bnx_RXP_b06FwTextAddr;
! 74: int bnx_RXP_b06FwTextLen;
! 75: u_int32_t bnx_RXP_b06FwDataAddr;
! 76: int bnx_RXP_b06FwDataLen;
! 77: u_int32_t bnx_RXP_b06FwRodataAddr;
! 78: int bnx_RXP_b06FwRodataLen;
! 79: u_int32_t bnx_RXP_b06FwBssAddr;
! 80: int bnx_RXP_b06FwBssLen;
! 81: u_int32_t bnx_RXP_b06FwSbssAddr;
! 82: int bnx_RXP_b06FwSbssLen;
! 83:
! 84: int bnx_TPAT_b06FwReleaseMajor;
! 85: int bnx_TPAT_b06FwReleaseMinor;
! 86: int bnx_TPAT_b06FwReleaseFix;
! 87: u_int32_t bnx_TPAT_b06FwStartAddr;
! 88: u_int32_t bnx_TPAT_b06FwTextAddr;
! 89: int bnx_TPAT_b06FwTextLen;
! 90: u_int32_t bnx_TPAT_b06FwDataAddr;
! 91: int bnx_TPAT_b06FwDataLen;
! 92: u_int32_t bnx_TPAT_b06FwRodataAddr;
! 93: int bnx_TPAT_b06FwRodataLen;
! 94: u_int32_t bnx_TPAT_b06FwBssAddr;
! 95: int bnx_TPAT_b06FwBssLen;
! 96: u_int32_t bnx_TPAT_b06FwSbssAddr;
! 97: int bnx_TPAT_b06FwSbssLen;
! 98:
! 99: int bnx_TXP_b06FwReleaseMajor;
! 100: int bnx_TXP_b06FwReleaseMinor;
! 101: int bnx_TXP_b06FwReleaseFix;
! 102: u_int32_t bnx_TXP_b06FwStartAddr;
! 103: u_int32_t bnx_TXP_b06FwTextAddr;
! 104: int bnx_TXP_b06FwTextLen;
! 105: u_int32_t bnx_TXP_b06FwDataAddr;
! 106: int bnx_TXP_b06FwDataLen;
! 107: u_int32_t bnx_TXP_b06FwRodataAddr;
! 108: int bnx_TXP_b06FwRodataLen;
! 109: u_int32_t bnx_TXP_b06FwBssAddr;
! 110: int bnx_TXP_b06FwBssLen;
! 111: u_int32_t bnx_TXP_b06FwSbssAddr;
! 112: int bnx_TXP_b06FwSbssLen;
! 113:
! 114: int bnx_rv2p_proc1len;
! 115: int bnx_rv2p_proc2len;
! 116:
! 117: u_int32_t *bnx_COM_b06FwText;
! 118: u_int32_t *bnx_COM_b06FwData;
! 119: u_int32_t *bnx_COM_b06FwRodata;
! 120: u_int32_t *bnx_COM_b06FwBss;
! 121: u_int32_t *bnx_COM_b06FwSbss;
! 122:
! 123: u_int32_t *bnx_RXP_b06FwText;
! 124: u_int32_t *bnx_RXP_b06FwData;
! 125: u_int32_t *bnx_RXP_b06FwRodata;
! 126: u_int32_t *bnx_RXP_b06FwBss;
! 127: u_int32_t *bnx_RXP_b06FwSbss;
! 128:
! 129: u_int32_t *bnx_TPAT_b06FwText;
! 130: u_int32_t *bnx_TPAT_b06FwData;
! 131: u_int32_t *bnx_TPAT_b06FwRodata;
! 132: u_int32_t *bnx_TPAT_b06FwBss;
! 133: u_int32_t *bnx_TPAT_b06FwSbss;
! 134:
! 135: u_int32_t *bnx_TXP_b06FwText;
! 136: u_int32_t *bnx_TXP_b06FwData;
! 137: u_int32_t *bnx_TXP_b06FwRodata;
! 138: u_int32_t *bnx_TXP_b06FwBss;
! 139: u_int32_t *bnx_TXP_b06FwSbss;
! 140:
! 141: u_int32_t *bnx_rv2p_proc1;
! 142: u_int32_t *bnx_rv2p_proc2;
! 143:
! 144: void nswaph(u_int32_t *p, int wcount);
! 145:
! 146: /****************************************************************************/
! 147: /* BNX Driver Version */
! 148: /****************************************************************************/
! 149: char bnx_driver_version[] = "v0.9.6";
! 150:
! 151: /****************************************************************************/
! 152: /* BNX Debug Options */
! 153: /****************************************************************************/
! 154: #ifdef BNX_DEBUG
! 155: u_int32_t bnx_debug = BNX_WARN;
! 156:
! 157: /* 0 = Never */
! 158: /* 1 = 1 in 2,147,483,648 */
! 159: /* 256 = 1 in 8,388,608 */
! 160: /* 2048 = 1 in 1,048,576 */
! 161: /* 65536 = 1 in 32,768 */
! 162: /* 1048576 = 1 in 2,048 */
! 163: /* 268435456 = 1 in 8 */
! 164: /* 536870912 = 1 in 4 */
! 165: /* 1073741824 = 1 in 2 */
! 166:
! 167: /* Controls how often the l2_fhdr frame error check will fail. */
! 168: int bnx_debug_l2fhdr_status_check = 0;
! 169:
! 170: /* Controls how often the unexpected attention check will fail. */
! 171: int bnx_debug_unexpected_attention = 0;
! 172:
! 173: /* Controls how often to simulate an mbuf allocation failure. */
! 174: int bnx_debug_mbuf_allocation_failure = 0;
! 175:
! 176: /* Controls how often to simulate a DMA mapping failure. */
! 177: int bnx_debug_dma_map_addr_failure = 0;
! 178:
! 179: /* Controls how often to simulate a bootcode failure. */
! 180: int bnx_debug_bootcode_running_failure = 0;
! 181: #endif
! 182:
! 183: /****************************************************************************/
! 184: /* PCI Device ID Table */
! 185: /* */
! 186: /* Used by bnx_probe() to identify the devices supported by this driver. */
! 187: /****************************************************************************/
! 188: const struct pci_matchid bnx_devices[] = {
! 189: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706 },
! 190: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5706S },
! 191: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5708 },
! 192: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5708S }
! 193: #if 0
! 194: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5709 },
! 195: { PCI_VENDOR_BROADCOM, PCI_PRODUCT_BROADCOM_BCM5709S }
! 196: #endif
! 197: };
! 198:
! 199: /****************************************************************************/
! 200: /* Supported Flash NVRAM device data. */
! 201: /****************************************************************************/
! 202: static struct flash_spec flash_table[] =
! 203: {
! 204: /* Slow EEPROM */
! 205: {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
! 206: 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
! 207: SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
! 208: "EEPROM - slow"},
! 209: /* Expansion entry 0001 */
! 210: {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
! 211: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 212: SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
! 213: "Entry 0001"},
! 214: /* Saifun SA25F010 (non-buffered flash) */
! 215: /* strap, cfg1, & write1 need updates */
! 216: {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
! 217: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 218: SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
! 219: "Non-buffered flash (128kB)"},
! 220: /* Saifun SA25F020 (non-buffered flash) */
! 221: /* strap, cfg1, & write1 need updates */
! 222: {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
! 223: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 224: SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
! 225: "Non-buffered flash (256kB)"},
! 226: /* Expansion entry 0100 */
! 227: {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
! 228: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 229: SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
! 230: "Entry 0100"},
! 231: /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
! 232: {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,
! 233: 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
! 234: ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
! 235: "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
! 236: /* Entry 0110: ST M45PE20 (non-buffered flash)*/
! 237: {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
! 238: 0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
! 239: ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
! 240: "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
! 241: /* Saifun SA25F005 (non-buffered flash) */
! 242: /* strap, cfg1, & write1 need updates */
! 243: {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
! 244: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 245: SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
! 246: "Non-buffered flash (64kB)"},
! 247: /* Fast EEPROM */
! 248: {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
! 249: 1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
! 250: SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
! 251: "EEPROM - fast"},
! 252: /* Expansion entry 1001 */
! 253: {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
! 254: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 255: SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
! 256: "Entry 1001"},
! 257: /* Expansion entry 1010 */
! 258: {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
! 259: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 260: SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
! 261: "Entry 1010"},
! 262: /* ATMEL AT45DB011B (buffered flash) */
! 263: {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
! 264: 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
! 265: BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
! 266: "Buffered flash (128kB)"},
! 267: /* Expansion entry 1100 */
! 268: {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
! 269: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 270: SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
! 271: "Entry 1100"},
! 272: /* Expansion entry 1101 */
! 273: {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
! 274: 0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
! 275: SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
! 276: "Entry 1101"},
! 277: /* Ateml Expansion entry 1110 */
! 278: {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
! 279: 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
! 280: BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
! 281: "Entry 1110 (Atmel)"},
! 282: /* ATMEL AT45DB021B (buffered flash) */
! 283: {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
! 284: 1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
! 285: BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
! 286: "Buffered flash (256kB)"},
! 287: };
! 288:
! 289: /****************************************************************************/
! 290: /* OpenBSD device entry points. */
! 291: /****************************************************************************/
! 292: int bnx_probe(struct device *, void *, void *);
! 293: void bnx_attach(struct device *, struct device *, void *);
! 294: void bnx_attachhook(void *);
! 295: int bnx_read_firmware(struct bnx_softc *sc);
! 296: #if 0
! 297: void bnx_detach(void *);
! 298: #endif
! 299: void bnx_shutdown(void *);
! 300:
! 301: /****************************************************************************/
! 302: /* BNX Debug Data Structure Dump Routines */
! 303: /****************************************************************************/
! 304: #ifdef BNX_DEBUG
! 305: void bnx_dump_mbuf(struct bnx_softc *, struct mbuf *);
! 306: void bnx_dump_tx_mbuf_chain(struct bnx_softc *, int, int);
! 307: void bnx_dump_rx_mbuf_chain(struct bnx_softc *, int, int);
! 308: void bnx_dump_txbd(struct bnx_softc *, int, struct tx_bd *);
! 309: void bnx_dump_rxbd(struct bnx_softc *, int, struct rx_bd *);
! 310: void bnx_dump_l2fhdr(struct bnx_softc *, int, struct l2_fhdr *);
! 311: void bnx_dump_tx_chain(struct bnx_softc *, int, int);
! 312: void bnx_dump_rx_chain(struct bnx_softc *, int, int);
! 313: void bnx_dump_status_block(struct bnx_softc *);
! 314: void bnx_dump_stats_block(struct bnx_softc *);
! 315: void bnx_dump_driver_state(struct bnx_softc *);
! 316: void bnx_dump_hw_state(struct bnx_softc *);
! 317: void bnx_breakpoint(struct bnx_softc *);
! 318: #endif
! 319:
! 320: /****************************************************************************/
! 321: /* BNX Register/Memory Access Routines */
! 322: /****************************************************************************/
! 323: u_int32_t bnx_reg_rd_ind(struct bnx_softc *, u_int32_t);
! 324: void bnx_reg_wr_ind(struct bnx_softc *, u_int32_t, u_int32_t);
! 325: void bnx_ctx_wr(struct bnx_softc *, u_int32_t, u_int32_t, u_int32_t);
! 326: int bnx_miibus_read_reg(struct device *, int, int);
! 327: void bnx_miibus_write_reg(struct device *, int, int, int);
! 328: void bnx_miibus_statchg(struct device *);
! 329:
! 330: /****************************************************************************/
! 331: /* BNX NVRAM Access Routines */
! 332: /****************************************************************************/
! 333: int bnx_acquire_nvram_lock(struct bnx_softc *);
! 334: int bnx_release_nvram_lock(struct bnx_softc *);
! 335: void bnx_enable_nvram_access(struct bnx_softc *);
! 336: void bnx_disable_nvram_access(struct bnx_softc *);
! 337: int bnx_nvram_read_dword(struct bnx_softc *, u_int32_t, u_int8_t *,
! 338: u_int32_t);
! 339: int bnx_init_nvram(struct bnx_softc *);
! 340: int bnx_nvram_read(struct bnx_softc *, u_int32_t, u_int8_t *, int);
! 341: int bnx_nvram_test(struct bnx_softc *);
! 342: #ifdef BNX_NVRAM_WRITE_SUPPORT
! 343: int bnx_enable_nvram_write(struct bnx_softc *);
! 344: void bnx_disable_nvram_write(struct bnx_softc *);
! 345: int bnx_nvram_erase_page(struct bnx_softc *, u_int32_t);
! 346: int bnx_nvram_write_dword(struct bnx_softc *, u_int32_t, u_int8_t *,
! 347: u_int32_t);
! 348: int bnx_nvram_write(struct bnx_softc *, u_int32_t, u_int8_t *, int);
! 349: #endif
! 350:
! 351: /****************************************************************************/
! 352: /* */
! 353: /****************************************************************************/
! 354: int bnx_dma_alloc(struct bnx_softc *);
! 355: void bnx_dma_free(struct bnx_softc *);
! 356: void bnx_release_resources(struct bnx_softc *);
! 357:
! 358: /****************************************************************************/
! 359: /* BNX Firmware Synchronization and Load */
! 360: /****************************************************************************/
! 361: int bnx_fw_sync(struct bnx_softc *, u_int32_t);
! 362: void bnx_load_rv2p_fw(struct bnx_softc *, u_int32_t *, u_int32_t,
! 363: u_int32_t);
! 364: void bnx_load_cpu_fw(struct bnx_softc *, struct cpu_reg *,
! 365: struct fw_info *);
! 366: void bnx_init_cpus(struct bnx_softc *);
! 367:
! 368: void bnx_stop(struct bnx_softc *);
! 369: int bnx_reset(struct bnx_softc *, u_int32_t);
! 370: int bnx_chipinit(struct bnx_softc *);
! 371: int bnx_blockinit(struct bnx_softc *);
! 372: int bnx_get_buf(struct bnx_softc *, struct mbuf *, u_int16_t *,
! 373: u_int16_t *, u_int32_t *);
! 374:
! 375: int bnx_init_tx_chain(struct bnx_softc *);
! 376: int bnx_init_rx_chain(struct bnx_softc *);
! 377: void bnx_free_rx_chain(struct bnx_softc *);
! 378: void bnx_free_tx_chain(struct bnx_softc *);
! 379:
! 380: int bnx_tx_encap(struct bnx_softc *, struct mbuf **);
! 381: void bnx_start(struct ifnet *);
! 382: int bnx_ioctl(struct ifnet *, u_long, caddr_t);
! 383: void bnx_watchdog(struct ifnet *);
! 384: int bnx_ifmedia_upd(struct ifnet *);
! 385: void bnx_ifmedia_sts(struct ifnet *, struct ifmediareq *);
! 386: void bnx_init(void *);
! 387: void bnx_mgmt_init(struct bnx_softc *sc);
! 388:
! 389: void bnx_init_context(struct bnx_softc *);
! 390: void bnx_get_mac_addr(struct bnx_softc *);
! 391: void bnx_set_mac_addr(struct bnx_softc *);
! 392: void bnx_phy_intr(struct bnx_softc *);
! 393: void bnx_rx_intr(struct bnx_softc *);
! 394: void bnx_tx_intr(struct bnx_softc *);
! 395: void bnx_disable_intr(struct bnx_softc *);
! 396: void bnx_enable_intr(struct bnx_softc *);
! 397:
! 398: int bnx_intr(void *);
! 399: void bnx_set_rx_mode(struct bnx_softc *);
! 400: void bnx_stats_update(struct bnx_softc *);
! 401: void bnx_tick(void *);
! 402:
! 403: /****************************************************************************/
! 404: /* OpenBSD device dispatch table. */
! 405: /****************************************************************************/
! 406: struct cfattach bnx_ca = {
! 407: sizeof(struct bnx_softc), bnx_probe, bnx_attach
! 408: };
! 409:
! 410: struct cfdriver bnx_cd = {
! 411: 0, "bnx", DV_IFNET
! 412: };
! 413:
! 414: /****************************************************************************/
! 415: /* Device probe function. */
! 416: /* */
! 417: /* Compares the device to the driver's list of supported devices and */
! 418: /* reports back to the OS whether this is the right driver for the device. */
! 419: /* */
! 420: /* Returns: */
! 421: /* BUS_PROBE_DEFAULT on success, positive value on failure. */
! 422: /****************************************************************************/
! 423: int
! 424: bnx_probe(struct device *parent, void *match, void *aux)
! 425: {
! 426: return (pci_matchbyid((struct pci_attach_args *)aux, bnx_devices,
! 427: sizeof(bnx_devices)/sizeof(bnx_devices[0])));
! 428: }
! 429:
! 430: void
! 431: nswaph(u_int32_t *p, int wcount)
! 432: {
! 433: for (; wcount; wcount -=4) {
! 434: *p = ntohl(*p);
! 435: p++;
! 436: }
! 437: }
! 438:
! 439: int
! 440: bnx_read_firmware(struct bnx_softc *sc)
! 441: {
! 442: static struct bnx_firmware_header *hdr;
! 443: u_char *p, *q;
! 444: size_t size;
! 445: int error;
! 446:
! 447: if (hdr)
! 448: return (0);
! 449:
! 450: if ((error = loadfirmware("bnx", &p, &size)) != 0)
! 451: return error;
! 452:
! 453: if (size < sizeof (struct bnx_firmware_header)) {
! 454: free(p, M_DEVBUF);
! 455: return EINVAL;
! 456: }
! 457:
! 458: hdr = (struct bnx_firmware_header *)p;
! 459:
! 460: bnx_COM_b06FwReleaseMajor = ntohl(hdr->bnx_COM_b06FwReleaseMajor);
! 461: bnx_COM_b06FwReleaseMinor = ntohl(hdr->bnx_COM_b06FwReleaseMinor);
! 462: bnx_COM_b06FwReleaseFix = ntohl(hdr->bnx_COM_b06FwReleaseFix);
! 463: bnx_COM_b06FwStartAddr = ntohl(hdr->bnx_COM_b06FwStartAddr);
! 464: bnx_COM_b06FwTextAddr = ntohl(hdr->bnx_COM_b06FwTextAddr);
! 465: bnx_COM_b06FwTextLen = ntohl(hdr->bnx_COM_b06FwTextLen);
! 466: bnx_COM_b06FwDataAddr = ntohl(hdr->bnx_COM_b06FwDataAddr);
! 467: bnx_COM_b06FwDataLen = ntohl(hdr->bnx_COM_b06FwDataLen);
! 468: bnx_COM_b06FwRodataAddr = ntohl(hdr->bnx_COM_b06FwRodataAddr);
! 469: bnx_COM_b06FwRodataLen = ntohl(hdr->bnx_COM_b06FwRodataLen);
! 470: bnx_COM_b06FwBssAddr = ntohl(hdr->bnx_COM_b06FwBssAddr);
! 471: bnx_COM_b06FwBssLen = ntohl(hdr->bnx_COM_b06FwBssLen);
! 472: bnx_COM_b06FwSbssAddr = ntohl(hdr->bnx_COM_b06FwSbssAddr);
! 473: bnx_COM_b06FwSbssLen = ntohl(hdr->bnx_COM_b06FwSbssLen);
! 474:
! 475: bnx_RXP_b06FwReleaseMajor = ntohl(hdr->bnx_RXP_b06FwReleaseMajor);
! 476: bnx_RXP_b06FwReleaseMinor = ntohl(hdr->bnx_RXP_b06FwReleaseMinor);
! 477: bnx_RXP_b06FwReleaseFix = ntohl(hdr->bnx_RXP_b06FwReleaseFix);
! 478: bnx_RXP_b06FwStartAddr = ntohl(hdr->bnx_RXP_b06FwStartAddr);
! 479: bnx_RXP_b06FwTextAddr = ntohl(hdr->bnx_RXP_b06FwTextAddr);
! 480: bnx_RXP_b06FwTextLen = ntohl(hdr->bnx_RXP_b06FwTextLen);
! 481: bnx_RXP_b06FwDataAddr = ntohl(hdr->bnx_RXP_b06FwDataAddr);
! 482: bnx_RXP_b06FwDataLen = ntohl(hdr->bnx_RXP_b06FwDataLen);
! 483: bnx_RXP_b06FwRodataAddr = ntohl(hdr->bnx_RXP_b06FwRodataAddr);
! 484: bnx_RXP_b06FwRodataLen = ntohl(hdr->bnx_RXP_b06FwRodataLen);
! 485: bnx_RXP_b06FwBssAddr = ntohl(hdr->bnx_RXP_b06FwBssAddr);
! 486: bnx_RXP_b06FwBssLen = ntohl(hdr->bnx_RXP_b06FwBssLen);
! 487: bnx_RXP_b06FwSbssAddr = ntohl(hdr->bnx_RXP_b06FwSbssAddr);
! 488: bnx_RXP_b06FwSbssLen = ntohl(hdr->bnx_RXP_b06FwSbssLen);
! 489:
! 490: bnx_TPAT_b06FwReleaseMajor = ntohl(hdr->bnx_TPAT_b06FwReleaseMajor);
! 491: bnx_TPAT_b06FwReleaseMinor = ntohl(hdr->bnx_TPAT_b06FwReleaseMinor);
! 492: bnx_TPAT_b06FwReleaseFix = ntohl(hdr->bnx_TPAT_b06FwReleaseFix);
! 493: bnx_TPAT_b06FwStartAddr = ntohl(hdr->bnx_TPAT_b06FwStartAddr);
! 494: bnx_TPAT_b06FwTextAddr = ntohl(hdr->bnx_TPAT_b06FwTextAddr);
! 495: bnx_TPAT_b06FwTextLen = ntohl(hdr->bnx_TPAT_b06FwTextLen);
! 496: bnx_TPAT_b06FwDataAddr = ntohl(hdr->bnx_TPAT_b06FwDataAddr);
! 497: bnx_TPAT_b06FwDataLen = ntohl(hdr->bnx_TPAT_b06FwDataLen);
! 498: bnx_TPAT_b06FwRodataAddr = ntohl(hdr->bnx_TPAT_b06FwRodataAddr);
! 499: bnx_TPAT_b06FwRodataLen = ntohl(hdr->bnx_TPAT_b06FwRodataLen);
! 500: bnx_TPAT_b06FwBssAddr = ntohl(hdr->bnx_TPAT_b06FwBssAddr);
! 501: bnx_TPAT_b06FwBssLen = ntohl(hdr->bnx_TPAT_b06FwBssLen);
! 502: bnx_TPAT_b06FwSbssAddr = ntohl(hdr->bnx_TPAT_b06FwSbssAddr);
! 503: bnx_TPAT_b06FwSbssLen = ntohl(hdr->bnx_TPAT_b06FwSbssLen);
! 504:
! 505: bnx_TXP_b06FwReleaseMajor = ntohl(hdr->bnx_TXP_b06FwReleaseMajor);
! 506: bnx_TXP_b06FwReleaseMinor = ntohl(hdr->bnx_TXP_b06FwReleaseMinor);
! 507: bnx_TXP_b06FwReleaseFix = ntohl(hdr->bnx_TXP_b06FwReleaseFix);
! 508: bnx_TXP_b06FwStartAddr = ntohl(hdr->bnx_TXP_b06FwStartAddr);
! 509: bnx_TXP_b06FwTextAddr = ntohl(hdr->bnx_TXP_b06FwTextAddr);
! 510: bnx_TXP_b06FwTextLen = ntohl(hdr->bnx_TXP_b06FwTextLen);
! 511: bnx_TXP_b06FwDataAddr = ntohl(hdr->bnx_TXP_b06FwDataAddr);
! 512: bnx_TXP_b06FwDataLen = ntohl(hdr->bnx_TXP_b06FwDataLen);
! 513: bnx_TXP_b06FwRodataAddr = ntohl(hdr->bnx_TXP_b06FwRodataAddr);
! 514: bnx_TXP_b06FwRodataLen = ntohl(hdr->bnx_TXP_b06FwRodataLen);
! 515: bnx_TXP_b06FwBssAddr = ntohl(hdr->bnx_TXP_b06FwBssAddr);
! 516: bnx_TXP_b06FwBssLen = ntohl(hdr->bnx_TXP_b06FwBssLen);
! 517: bnx_TXP_b06FwSbssAddr = ntohl(hdr->bnx_TXP_b06FwSbssAddr);
! 518: bnx_TXP_b06FwSbssLen = ntohl(hdr->bnx_TXP_b06FwSbssLen);
! 519:
! 520: bnx_rv2p_proc1len = ntohl(hdr->bnx_rv2p_proc1len);
! 521: bnx_rv2p_proc2len = ntohl(hdr->bnx_rv2p_proc2len);
! 522:
! 523: q = p + sizeof(*hdr);
! 524:
! 525: bnx_COM_b06FwText = (u_int32_t *)q;
! 526: q += bnx_COM_b06FwTextLen;
! 527: nswaph(bnx_COM_b06FwText, bnx_COM_b06FwTextLen);
! 528: bnx_COM_b06FwData = (u_int32_t *)q;
! 529: q += bnx_COM_b06FwDataLen;
! 530: nswaph(bnx_COM_b06FwData, bnx_COM_b06FwDataLen);
! 531: bnx_COM_b06FwRodata = (u_int32_t *)q;
! 532: q += bnx_COM_b06FwRodataLen;
! 533: nswaph(bnx_COM_b06FwRodata, bnx_COM_b06FwRodataLen);
! 534: bnx_COM_b06FwBss = (u_int32_t *)q;
! 535: q += bnx_COM_b06FwBssLen;
! 536: nswaph(bnx_COM_b06FwBss, bnx_COM_b06FwBssLen);
! 537: bnx_COM_b06FwSbss = (u_int32_t *)q;
! 538: q += bnx_COM_b06FwSbssLen;
! 539: nswaph(bnx_COM_b06FwSbss, bnx_COM_b06FwSbssLen);
! 540:
! 541: bnx_RXP_b06FwText = (u_int32_t *)q;
! 542: q += bnx_RXP_b06FwTextLen;
! 543: nswaph(bnx_RXP_b06FwText, bnx_RXP_b06FwTextLen);
! 544: bnx_RXP_b06FwData = (u_int32_t *)q;
! 545: q += bnx_RXP_b06FwDataLen;
! 546: nswaph(bnx_RXP_b06FwData, bnx_RXP_b06FwDataLen);
! 547: bnx_RXP_b06FwRodata = (u_int32_t *)q;
! 548: q += bnx_RXP_b06FwRodataLen;
! 549: nswaph(bnx_RXP_b06FwRodata, bnx_RXP_b06FwRodataLen);
! 550: bnx_RXP_b06FwBss = (u_int32_t *)q;
! 551: q += bnx_RXP_b06FwBssLen;
! 552: nswaph(bnx_RXP_b06FwBss, bnx_RXP_b06FwBssLen);
! 553: bnx_RXP_b06FwSbss = (u_int32_t *)q;
! 554: q += bnx_RXP_b06FwSbssLen;
! 555: nswaph(bnx_RXP_b06FwSbss, bnx_RXP_b06FwSbssLen);
! 556:
! 557: bnx_TPAT_b06FwText = (u_int32_t *)q;
! 558: q += bnx_TPAT_b06FwTextLen;
! 559: nswaph(bnx_TPAT_b06FwText, bnx_TPAT_b06FwTextLen);
! 560: bnx_TPAT_b06FwData = (u_int32_t *)q;
! 561: q += bnx_TPAT_b06FwDataLen;
! 562: nswaph(bnx_TPAT_b06FwData, bnx_TPAT_b06FwDataLen);
! 563: bnx_TPAT_b06FwRodata = (u_int32_t *)q;
! 564: q += bnx_TPAT_b06FwRodataLen;
! 565: nswaph(bnx_TPAT_b06FwRodata, bnx_TPAT_b06FwRodataLen);
! 566: bnx_TPAT_b06FwBss = (u_int32_t *)q;
! 567: q += bnx_TPAT_b06FwBssLen;
! 568: nswaph(bnx_TPAT_b06FwBss, bnx_TPAT_b06FwBssLen);
! 569: bnx_TPAT_b06FwSbss = (u_int32_t *)q;
! 570: q += bnx_TPAT_b06FwSbssLen;
! 571: nswaph(bnx_TPAT_b06FwSbss, bnx_TPAT_b06FwSbssLen);
! 572:
! 573: bnx_TXP_b06FwText = (u_int32_t *)q;
! 574: q += bnx_TXP_b06FwTextLen;
! 575: nswaph(bnx_TXP_b06FwText, bnx_TXP_b06FwTextLen);
! 576: bnx_TXP_b06FwData = (u_int32_t *)q;
! 577: q += bnx_TXP_b06FwDataLen;
! 578: nswaph(bnx_TXP_b06FwData, bnx_TXP_b06FwDataLen);
! 579: bnx_TXP_b06FwRodata = (u_int32_t *)q;
! 580: q += bnx_TXP_b06FwRodataLen;
! 581: nswaph(bnx_TXP_b06FwRodata, bnx_TXP_b06FwRodataLen);
! 582: bnx_TXP_b06FwBss = (u_int32_t *)q;
! 583: q += bnx_TXP_b06FwBssLen;
! 584: nswaph(bnx_TXP_b06FwBss, bnx_TXP_b06FwBssLen);
! 585: bnx_TXP_b06FwSbss = (u_int32_t *)q;
! 586: q += bnx_TXP_b06FwSbssLen;
! 587: nswaph(bnx_TXP_b06FwSbss, bnx_TXP_b06FwSbssLen);
! 588:
! 589: bnx_rv2p_proc1 = (u_int32_t *)q;
! 590: q += bnx_rv2p_proc1len;
! 591: nswaph(bnx_rv2p_proc1, bnx_rv2p_proc1len);
! 592: bnx_rv2p_proc2 = (u_int32_t *)q;
! 593: q += bnx_rv2p_proc2len;
! 594: nswaph(bnx_rv2p_proc2, bnx_rv2p_proc2len);
! 595:
! 596: if (q - p != size) {
! 597: free(p, M_DEVBUF);
! 598: hdr = NULL;
! 599: return EINVAL;
! 600: }
! 601:
! 602: return (0);
! 603: }
! 604:
! 605:
! 606: /****************************************************************************/
! 607: /* Device attach function. */
! 608: /* */
! 609: /* Allocates device resources, performs secondary chip identification, */
! 610: /* resets and initializes the hardware, and initializes driver instance */
! 611: /* variables. */
! 612: /* */
! 613: /* Returns: */
! 614: /* 0 on success, positive value on failure. */
! 615: /****************************************************************************/
! 616: void
! 617: bnx_attach(struct device *parent, struct device *self, void *aux)
! 618: {
! 619: struct bnx_softc *sc = (struct bnx_softc *)self;
! 620: struct pci_attach_args *pa = aux;
! 621: pci_chipset_tag_t pc = pa->pa_pc;
! 622: u_int32_t val;
! 623: pcireg_t memtype;
! 624: const char *intrstr = NULL;
! 625:
! 626: sc->bnx_pa = *pa;
! 627:
! 628: /*
! 629: * Map control/status registers.
! 630: */
! 631: memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, BNX_PCI_BAR0);
! 632: switch (memtype) {
! 633: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
! 634: case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
! 635: if (pci_mapreg_map(pa, BNX_PCI_BAR0,
! 636: memtype, 0, &sc->bnx_btag, &sc->bnx_bhandle,
! 637: NULL, &sc->bnx_size, 0) == 0)
! 638: break;
! 639: default:
! 640: printf(": can't find mem space\n");
! 641: return;
! 642: }
! 643:
! 644: if (pci_intr_map(pa, &sc->bnx_ih)) {
! 645: printf(": couldn't map interrupt\n");
! 646: goto bnx_attach_fail;
! 647: }
! 648: intrstr = pci_intr_string(pc, sc->bnx_ih);
! 649:
! 650: /*
! 651: * Configure byte swap and enable indirect register access.
! 652: * Rely on CPU to do target byte swapping on big endian systems.
! 653: * Access to registers outside of PCI configurtion space are not
! 654: * valid until this is done.
! 655: */
! 656: pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_MISC_CONFIG,
! 657: BNX_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
! 658: BNX_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
! 659:
! 660: /* Save ASIC revsion info. */
! 661: sc->bnx_chipid = REG_RD(sc, BNX_MISC_ID);
! 662:
! 663: /* Weed out any non-production controller revisions. */
! 664: switch(BNX_CHIP_ID(sc)) {
! 665: case BNX_CHIP_ID_5706_A0:
! 666: case BNX_CHIP_ID_5706_A1:
! 667: case BNX_CHIP_ID_5708_A0:
! 668: case BNX_CHIP_ID_5708_B0:
! 669: printf(": unsupported controller revision (%c%d)!\n",
! 670: (((pci_conf_read(pa->pa_pc, pa->pa_tag, 0x08) & 0xf0) >> 4)
! 671: + 'A'), (pci_conf_read(pa->pa_pc, pa->pa_tag, 0x08) & 0xf));
! 672: goto bnx_attach_fail;
! 673: }
! 674:
! 675: if (BNX_CHIP_BOND_ID(sc) & BNX_CHIP_BOND_ID_SERDES_BIT) {
! 676: printf(": SerDes controllers are not supported!\n");
! 677: goto bnx_attach_fail;
! 678: }
! 679:
! 680: /*
! 681: * Find the base address for shared memory access.
! 682: * Newer versions of bootcode use a signature and offset
! 683: * while older versions use a fixed address.
! 684: */
! 685: val = REG_RD_IND(sc, BNX_SHM_HDR_SIGNATURE);
! 686: if ((val & BNX_SHM_HDR_SIGNATURE_SIG_MASK) == BNX_SHM_HDR_SIGNATURE_SIG)
! 687: sc->bnx_shmem_base = REG_RD_IND(sc, BNX_SHM_HDR_ADDR_0);
! 688: else
! 689: sc->bnx_shmem_base = HOST_VIEW_SHMEM_BASE;
! 690:
! 691: DBPRINT(sc, BNX_INFO, "bnx_shmem_base = 0x%08X\n", sc->bnx_shmem_base);
! 692:
! 693: /* Set initial device and PHY flags */
! 694: sc->bnx_flags = 0;
! 695: sc->bnx_phy_flags = 0;
! 696:
! 697: /* Get PCI bus information (speed and type). */
! 698: val = REG_RD(sc, BNX_PCICFG_MISC_STATUS);
! 699: if (val & BNX_PCICFG_MISC_STATUS_PCIX_DET) {
! 700: u_int32_t clkreg;
! 701:
! 702: sc->bnx_flags |= BNX_PCIX_FLAG;
! 703:
! 704: clkreg = REG_RD(sc, BNX_PCICFG_PCI_CLOCK_CONTROL_BITS);
! 705:
! 706: clkreg &= BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
! 707: switch (clkreg) {
! 708: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
! 709: sc->bus_speed_mhz = 133;
! 710: break;
! 711:
! 712: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
! 713: sc->bus_speed_mhz = 100;
! 714: break;
! 715:
! 716: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
! 717: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
! 718: sc->bus_speed_mhz = 66;
! 719: break;
! 720:
! 721: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
! 722: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
! 723: sc->bus_speed_mhz = 50;
! 724: break;
! 725:
! 726: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
! 727: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
! 728: case BNX_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
! 729: sc->bus_speed_mhz = 33;
! 730: break;
! 731: }
! 732: } else if (val & BNX_PCICFG_MISC_STATUS_M66EN)
! 733: sc->bus_speed_mhz = 66;
! 734: else
! 735: sc->bus_speed_mhz = 33;
! 736:
! 737: if (val & BNX_PCICFG_MISC_STATUS_32BIT_DET)
! 738: sc->bnx_flags |= BNX_PCI_32BIT_FLAG;
! 739:
! 740: printf(": %s\n", intrstr);
! 741:
! 742: /* Hookup IRQ last. */
! 743: sc->bnx_intrhand = pci_intr_establish(pc, sc->bnx_ih, IPL_NET,
! 744: bnx_intr, sc, sc->bnx_dev.dv_xname);
! 745: if (sc->bnx_intrhand == NULL) {
! 746: printf("%s: couldn't establish interrupt\n",
! 747: sc->bnx_dev.dv_xname);
! 748: goto bnx_attach_fail;
! 749: }
! 750:
! 751: mountroothook_establish(bnx_attachhook, sc);
! 752: return;
! 753:
! 754: bnx_attach_fail:
! 755: bnx_release_resources(sc);
! 756: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 757: }
! 758:
! 759: void
! 760: bnx_attachhook(void *xsc)
! 761: {
! 762: struct bnx_softc *sc = xsc;
! 763: struct pci_attach_args *pa = &sc->bnx_pa;
! 764: struct ifnet *ifp;
! 765: u_int32_t val;
! 766: int error;
! 767:
! 768: if ((error = bnx_read_firmware(sc)) != 0) {
! 769: printf("%s: could not read firmware (error=%d)\n",
! 770: sc->bnx_dev.dv_xname, error);
! 771: return;
! 772: }
! 773:
! 774: /* Reset the controller. */
! 775: if (bnx_reset(sc, BNX_DRV_MSG_CODE_RESET))
! 776: goto bnx_attach_fail;
! 777:
! 778: /* Initialize the controller. */
! 779: if (bnx_chipinit(sc)) {
! 780: printf("%s: Controller initialization failed!\n",
! 781: sc->bnx_dev.dv_xname);
! 782: goto bnx_attach_fail;
! 783: }
! 784:
! 785: /* Perform NVRAM test. */
! 786: if (bnx_nvram_test(sc)) {
! 787: printf("%s: NVRAM test failed!\n",
! 788: sc->bnx_dev.dv_xname);
! 789: goto bnx_attach_fail;
! 790: }
! 791:
! 792: /* Fetch the permanent Ethernet MAC address. */
! 793: bnx_get_mac_addr(sc);
! 794:
! 795: /*
! 796: * Trip points control how many BDs
! 797: * should be ready before generating an
! 798: * interrupt while ticks control how long
! 799: * a BD can sit in the chain before
! 800: * generating an interrupt. Set the default
! 801: * values for the RX and TX rings.
! 802: */
! 803:
! 804: #ifdef BNX_DEBUG
! 805: /* Force more frequent interrupts. */
! 806: sc->bnx_tx_quick_cons_trip_int = 1;
! 807: sc->bnx_tx_quick_cons_trip = 1;
! 808: sc->bnx_tx_ticks_int = 0;
! 809: sc->bnx_tx_ticks = 0;
! 810:
! 811: sc->bnx_rx_quick_cons_trip_int = 1;
! 812: sc->bnx_rx_quick_cons_trip = 1;
! 813: sc->bnx_rx_ticks_int = 0;
! 814: sc->bnx_rx_ticks = 0;
! 815: #else
! 816: sc->bnx_tx_quick_cons_trip_int = 20;
! 817: sc->bnx_tx_quick_cons_trip = 20;
! 818: sc->bnx_tx_ticks_int = 80;
! 819: sc->bnx_tx_ticks = 80;
! 820:
! 821: sc->bnx_rx_quick_cons_trip_int = 6;
! 822: sc->bnx_rx_quick_cons_trip = 6;
! 823: sc->bnx_rx_ticks_int = 18;
! 824: sc->bnx_rx_ticks = 18;
! 825: #endif
! 826:
! 827: /* Update statistics once every second. */
! 828: sc->bnx_stats_ticks = 1000000 & 0xffff00;
! 829:
! 830: /*
! 831: * The copper based NetXtreme II controllers
! 832: * use an integrated PHY at address 1 while
! 833: * the SerDes controllers use a PHY at
! 834: * address 2.
! 835: */
! 836: sc->bnx_phy_addr = 1;
! 837:
! 838: if (BNX_CHIP_BOND_ID(sc) & BNX_CHIP_BOND_ID_SERDES_BIT) {
! 839: sc->bnx_phy_flags |= BNX_PHY_SERDES_FLAG;
! 840: sc->bnx_flags |= BNX_NO_WOL_FLAG;
! 841: if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5708) {
! 842: sc->bnx_phy_addr = 2;
! 843: val = REG_RD_IND(sc, sc->bnx_shmem_base +
! 844: BNX_SHARED_HW_CFG_CONFIG);
! 845: if (val & BNX_SHARED_HW_CFG_PHY_2_5G)
! 846: sc->bnx_phy_flags |= BNX_PHY_2_5G_CAPABLE_FLAG;
! 847: }
! 848: }
! 849:
! 850: if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG) {
! 851: printf(": SerDes is not supported by this driver!\n");
! 852: goto bnx_attach_fail;
! 853: }
! 854:
! 855: /* Allocate DMA memory resources. */
! 856: sc->bnx_dmatag = pa->pa_dmat;
! 857: if (bnx_dma_alloc(sc)) {
! 858: printf("%s: DMA resource allocation failed!\n",
! 859: sc->bnx_dev.dv_xname);
! 860: goto bnx_attach_fail;
! 861: }
! 862:
! 863: /* Initialize the ifnet interface. */
! 864: ifp = &sc->arpcom.ac_if;
! 865: ifp->if_softc = sc;
! 866: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
! 867: ifp->if_ioctl = bnx_ioctl;
! 868: ifp->if_start = bnx_start;
! 869: ifp->if_watchdog = bnx_watchdog;
! 870: if (sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG)
! 871: ifp->if_baudrate = IF_Gbps(2.5);
! 872: else
! 873: ifp->if_baudrate = IF_Gbps(1);
! 874: IFQ_SET_MAXLEN(&ifp->if_snd, USABLE_TX_BD - 1);
! 875: IFQ_SET_READY(&ifp->if_snd);
! 876: bcopy(sc->eaddr, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
! 877: bcopy(sc->bnx_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
! 878:
! 879: ifp->if_capabilities = IFCAP_VLAN_MTU;
! 880:
! 881: #ifdef BNX_CSUM
! 882: ifp->if_capabilities |= IFCAP_CSUM_TCPv4 | IFCAP_CSUM_UDPv4;
! 883: #endif
! 884:
! 885: #if NVLAN > 0
! 886: ifp->if_capabilities |= IFCAP_VLAN_HWTAGGING;
! 887: #endif
! 888:
! 889: sc->mbuf_alloc_size = BNX_MAX_MRU;
! 890:
! 891: printf("%s: address %s\n", sc->bnx_dev.dv_xname,
! 892: ether_sprintf(sc->arpcom.ac_enaddr));
! 893:
! 894: sc->bnx_mii.mii_ifp = ifp;
! 895: sc->bnx_mii.mii_readreg = bnx_miibus_read_reg;
! 896: sc->bnx_mii.mii_writereg = bnx_miibus_write_reg;
! 897: sc->bnx_mii.mii_statchg = bnx_miibus_statchg;
! 898:
! 899: /* Look for our PHY. */
! 900: ifmedia_init(&sc->bnx_mii.mii_media, 0, bnx_ifmedia_upd,
! 901: bnx_ifmedia_sts);
! 902: mii_attach(&sc->bnx_dev, &sc->bnx_mii, 0xffffffff,
! 903: MII_PHY_ANY, MII_OFFSET_ANY, 0);
! 904:
! 905: if (LIST_FIRST(&sc->bnx_mii.mii_phys) == NULL) {
! 906: printf("%s: no PHY found!\n", sc->bnx_dev.dv_xname);
! 907: ifmedia_add(&sc->bnx_mii.mii_media,
! 908: IFM_ETHER|IFM_MANUAL, 0, NULL);
! 909: ifmedia_set(&sc->bnx_mii.mii_media,
! 910: IFM_ETHER|IFM_MANUAL);
! 911: } else {
! 912: ifmedia_set(&sc->bnx_mii.mii_media,
! 913: IFM_ETHER|IFM_AUTO);
! 914: }
! 915:
! 916: /* Attach to the Ethernet interface list. */
! 917: if_attach(ifp);
! 918: ether_ifattach(ifp);
! 919:
! 920: timeout_set(&sc->bnx_timeout, bnx_tick, sc);
! 921:
! 922: /* Print some important debugging info. */
! 923: DBRUN(BNX_INFO, bnx_dump_driver_state(sc));
! 924:
! 925: /* Get the firmware running so ASF still works. */
! 926: bnx_mgmt_init(sc);
! 927:
! 928: /* Handle interrupts */
! 929: sc->bnx_flags |= BNX_ACTIVE_FLAG;
! 930:
! 931: goto bnx_attach_exit;
! 932:
! 933: bnx_attach_fail:
! 934: bnx_release_resources(sc);
! 935:
! 936: bnx_attach_exit:
! 937: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 938: }
! 939:
! 940: /****************************************************************************/
! 941: /* Device detach function. */
! 942: /* */
! 943: /* Stops the controller, resets the controller, and releases resources. */
! 944: /* */
! 945: /* Returns: */
! 946: /* 0 on success, positive value on failure. */
! 947: /****************************************************************************/
! 948: #if 0
! 949: void
! 950: bnx_detach(void *xsc)
! 951: {
! 952: struct bnx_softc *sc;
! 953: struct ifnet *ifp = &sc->arpcom.ac_if;
! 954:
! 955: sc = device_get_softc(dev);
! 956:
! 957: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 958:
! 959: /* Stop and reset the controller. */
! 960: bnx_stop(sc);
! 961: bnx_reset(sc, BNX_DRV_MSG_CODE_RESET);
! 962:
! 963: ether_ifdetach(ifp);
! 964:
! 965: /* If we have a child device on the MII bus remove it too. */
! 966: if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG) {
! 967: ifmedia_removeall(&sc->bnx_ifmedia);
! 968: } else {
! 969: bus_generic_detach(dev);
! 970: device_delete_child(dev, sc->bnx_mii);
! 971: }
! 972:
! 973: /* Release all remaining resources. */
! 974: bnx_release_resources(sc);
! 975:
! 976: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 977:
! 978: return(0);
! 979: }
! 980: #endif
! 981:
! 982: /****************************************************************************/
! 983: /* Device shutdown function. */
! 984: /* */
! 985: /* Stops and resets the controller. */
! 986: /* */
! 987: /* Returns: */
! 988: /* Nothing */
! 989: /****************************************************************************/
! 990: void
! 991: bnx_shutdown(void *xsc)
! 992: {
! 993: struct bnx_softc *sc = (struct bnx_softc *)xsc;
! 994:
! 995: bnx_stop(sc);
! 996: bnx_reset(sc, BNX_DRV_MSG_CODE_RESET);
! 997: }
! 998:
! 999: /****************************************************************************/
! 1000: /* Indirect register read. */
! 1001: /* */
! 1002: /* Reads NetXtreme II registers using an index/data register pair in PCI */
! 1003: /* configuration space. Using this mechanism avoids issues with posted */
! 1004: /* reads but is much slower than memory-mapped I/O. */
! 1005: /* */
! 1006: /* Returns: */
! 1007: /* The value of the register. */
! 1008: /****************************************************************************/
! 1009: u_int32_t
! 1010: bnx_reg_rd_ind(struct bnx_softc *sc, u_int32_t offset)
! 1011: {
! 1012: struct pci_attach_args *pa = &(sc->bnx_pa);
! 1013:
! 1014: pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW_ADDRESS,
! 1015: offset);
! 1016: #ifdef BNX_DEBUG
! 1017: {
! 1018: u_int32_t val;
! 1019: val = pci_conf_read(pa->pa_pc, pa->pa_tag,
! 1020: BNX_PCICFG_REG_WINDOW);
! 1021: DBPRINT(sc, BNX_EXCESSIVE, "%s(); offset = 0x%08X, "
! 1022: "val = 0x%08X\n", __FUNCTION__, offset, val);
! 1023: return (val);
! 1024: }
! 1025: #else
! 1026: return pci_conf_read(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW);
! 1027: #endif
! 1028: }
! 1029:
! 1030: /****************************************************************************/
! 1031: /* Indirect register write. */
! 1032: /* */
! 1033: /* Writes NetXtreme II registers using an index/data register pair in PCI */
! 1034: /* configuration space. Using this mechanism avoids issues with posted */
! 1035: /* writes but is muchh slower than memory-mapped I/O. */
! 1036: /* */
! 1037: /* Returns: */
! 1038: /* Nothing. */
! 1039: /****************************************************************************/
! 1040: void
! 1041: bnx_reg_wr_ind(struct bnx_softc *sc, u_int32_t offset, u_int32_t val)
! 1042: {
! 1043: struct pci_attach_args *pa = &(sc->bnx_pa);
! 1044:
! 1045: DBPRINT(sc, BNX_EXCESSIVE, "%s(); offset = 0x%08X, val = 0x%08X\n",
! 1046: __FUNCTION__, offset, val);
! 1047:
! 1048: pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW_ADDRESS,
! 1049: offset);
! 1050: pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCICFG_REG_WINDOW, val);
! 1051: }
! 1052:
! 1053: /****************************************************************************/
! 1054: /* Context memory write. */
! 1055: /* */
! 1056: /* The NetXtreme II controller uses context memory to track connection */
! 1057: /* information for L2 and higher network protocols. */
! 1058: /* */
! 1059: /* Returns: */
! 1060: /* Nothing. */
! 1061: /****************************************************************************/
! 1062: void
! 1063: bnx_ctx_wr(struct bnx_softc *sc, u_int32_t cid_addr, u_int32_t offset,
! 1064: u_int32_t val)
! 1065: {
! 1066:
! 1067: DBPRINT(sc, BNX_EXCESSIVE, "%s(); cid_addr = 0x%08X, offset = 0x%08X, "
! 1068: "val = 0x%08X\n", __FUNCTION__, cid_addr, offset, val);
! 1069:
! 1070: offset += cid_addr;
! 1071: REG_WR(sc, BNX_CTX_DATA_ADR, offset);
! 1072: REG_WR(sc, BNX_CTX_DATA, val);
! 1073: }
! 1074:
! 1075: /****************************************************************************/
! 1076: /* PHY register read. */
! 1077: /* */
! 1078: /* Implements register reads on the MII bus. */
! 1079: /* */
! 1080: /* Returns: */
! 1081: /* The value of the register. */
! 1082: /****************************************************************************/
! 1083: int
! 1084: bnx_miibus_read_reg(struct device *dev, int phy, int reg)
! 1085: {
! 1086: struct bnx_softc *sc = (struct bnx_softc *)dev;
! 1087: u_int32_t val;
! 1088: int i;
! 1089:
! 1090: /* Make sure we are accessing the correct PHY address. */
! 1091: if (phy != sc->bnx_phy_addr) {
! 1092: DBPRINT(sc, BNX_VERBOSE,
! 1093: "Invalid PHY address %d for PHY read!\n", phy);
! 1094: return(0);
! 1095: }
! 1096:
! 1097: if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) {
! 1098: val = REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1099: val &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL;
! 1100:
! 1101: REG_WR(sc, BNX_EMAC_MDIO_MODE, val);
! 1102: REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1103:
! 1104: DELAY(40);
! 1105: }
! 1106:
! 1107: val = BNX_MIPHY(phy) | BNX_MIREG(reg) |
! 1108: BNX_EMAC_MDIO_COMM_COMMAND_READ | BNX_EMAC_MDIO_COMM_DISEXT |
! 1109: BNX_EMAC_MDIO_COMM_START_BUSY;
! 1110: REG_WR(sc, BNX_EMAC_MDIO_COMM, val);
! 1111:
! 1112: for (i = 0; i < BNX_PHY_TIMEOUT; i++) {
! 1113: DELAY(10);
! 1114:
! 1115: val = REG_RD(sc, BNX_EMAC_MDIO_COMM);
! 1116: if (!(val & BNX_EMAC_MDIO_COMM_START_BUSY)) {
! 1117: DELAY(5);
! 1118:
! 1119: val = REG_RD(sc, BNX_EMAC_MDIO_COMM);
! 1120: val &= BNX_EMAC_MDIO_COMM_DATA;
! 1121:
! 1122: break;
! 1123: }
! 1124: }
! 1125:
! 1126: if (val & BNX_EMAC_MDIO_COMM_START_BUSY) {
! 1127: BNX_PRINTF(sc, "%s(%d): Error: PHY read timeout! phy = %d, "
! 1128: "reg = 0x%04X\n", __FILE__, __LINE__, phy, reg);
! 1129: val = 0x0;
! 1130: } else
! 1131: val = REG_RD(sc, BNX_EMAC_MDIO_COMM);
! 1132:
! 1133: DBPRINT(sc, BNX_EXCESSIVE,
! 1134: "%s(): phy = %d, reg = 0x%04X, val = 0x%04X\n", __FUNCTION__, phy,
! 1135: (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff);
! 1136:
! 1137: if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) {
! 1138: val = REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1139: val |= BNX_EMAC_MDIO_MODE_AUTO_POLL;
! 1140:
! 1141: REG_WR(sc, BNX_EMAC_MDIO_MODE, val);
! 1142: REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1143:
! 1144: DELAY(40);
! 1145: }
! 1146:
! 1147: return (val & 0xffff);
! 1148: }
! 1149:
! 1150: /****************************************************************************/
! 1151: /* PHY register write. */
! 1152: /* */
! 1153: /* Implements register writes on the MII bus. */
! 1154: /* */
! 1155: /* Returns: */
! 1156: /* The value of the register. */
! 1157: /****************************************************************************/
! 1158: void
! 1159: bnx_miibus_write_reg(struct device *dev, int phy, int reg, int val)
! 1160: {
! 1161: struct bnx_softc *sc = (struct bnx_softc *)dev;
! 1162: u_int32_t val1;
! 1163: int i;
! 1164:
! 1165: /* Make sure we are accessing the correct PHY address. */
! 1166: if (phy != sc->bnx_phy_addr) {
! 1167: DBPRINT(sc, BNX_WARN, "Invalid PHY address %d for PHY write!\n",
! 1168: phy);
! 1169: return;
! 1170: }
! 1171:
! 1172: DBPRINT(sc, BNX_EXCESSIVE, "%s(): phy = %d, reg = 0x%04X, "
! 1173: "val = 0x%04X\n", __FUNCTION__,
! 1174: phy, (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff);
! 1175:
! 1176: if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) {
! 1177: val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1178: val1 &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL;
! 1179:
! 1180: REG_WR(sc, BNX_EMAC_MDIO_MODE, val1);
! 1181: REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1182:
! 1183: DELAY(40);
! 1184: }
! 1185:
! 1186: val1 = BNX_MIPHY(phy) | BNX_MIREG(reg) | val |
! 1187: BNX_EMAC_MDIO_COMM_COMMAND_WRITE |
! 1188: BNX_EMAC_MDIO_COMM_START_BUSY | BNX_EMAC_MDIO_COMM_DISEXT;
! 1189: REG_WR(sc, BNX_EMAC_MDIO_COMM, val1);
! 1190:
! 1191: for (i = 0; i < BNX_PHY_TIMEOUT; i++) {
! 1192: DELAY(10);
! 1193:
! 1194: val1 = REG_RD(sc, BNX_EMAC_MDIO_COMM);
! 1195: if (!(val1 & BNX_EMAC_MDIO_COMM_START_BUSY)) {
! 1196: DELAY(5);
! 1197: break;
! 1198: }
! 1199: }
! 1200:
! 1201: if (val1 & BNX_EMAC_MDIO_COMM_START_BUSY) {
! 1202: BNX_PRINTF(sc, "%s(%d): PHY write timeout!\n", __FILE__,
! 1203: __LINE__);
! 1204: }
! 1205:
! 1206: if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) {
! 1207: val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1208: val1 |= BNX_EMAC_MDIO_MODE_AUTO_POLL;
! 1209:
! 1210: REG_WR(sc, BNX_EMAC_MDIO_MODE, val1);
! 1211: REG_RD(sc, BNX_EMAC_MDIO_MODE);
! 1212:
! 1213: DELAY(40);
! 1214: }
! 1215: }
! 1216:
! 1217: /****************************************************************************/
! 1218: /* MII bus status change. */
! 1219: /* */
! 1220: /* Called by the MII bus driver when the PHY establishes link to set the */
! 1221: /* MAC interface registers. */
! 1222: /* */
! 1223: /* Returns: */
! 1224: /* Nothing. */
! 1225: /****************************************************************************/
! 1226: void
! 1227: bnx_miibus_statchg(struct device *dev)
! 1228: {
! 1229: struct bnx_softc *sc = (struct bnx_softc *)dev;
! 1230: struct mii_data *mii = &sc->bnx_mii;
! 1231:
! 1232: BNX_CLRBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_PORT);
! 1233:
! 1234: /* Set MII or GMII inerface based on the speed negotiated by the PHY. */
! 1235: if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
! 1236: DBPRINT(sc, BNX_INFO, "Setting GMII interface.\n");
! 1237: BNX_SETBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_PORT_GMII);
! 1238: } else {
! 1239: DBPRINT(sc, BNX_INFO, "Setting MII interface.\n");
! 1240: BNX_SETBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_PORT_MII);
! 1241: }
! 1242:
! 1243: /* Set half or full duplex based on the duplicity
! 1244: * negotiated by the PHY.
! 1245: */
! 1246: if ((mii->mii_media_active & IFM_GMASK) == IFM_FDX) {
! 1247: DBPRINT(sc, BNX_INFO, "Setting Full-Duplex interface.\n");
! 1248: BNX_CLRBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_HALF_DUPLEX);
! 1249: } else {
! 1250: DBPRINT(sc, BNX_INFO, "Setting Half-Duplex interface.\n");
! 1251: BNX_SETBIT(sc, BNX_EMAC_MODE, BNX_EMAC_MODE_HALF_DUPLEX);
! 1252: }
! 1253: }
! 1254:
! 1255: /****************************************************************************/
! 1256: /* Acquire NVRAM lock. */
! 1257: /* */
! 1258: /* Before the NVRAM can be accessed the caller must acquire an NVRAM lock. */
! 1259: /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */
! 1260: /* for use by the driver. */
! 1261: /* */
! 1262: /* Returns: */
! 1263: /* 0 on success, positive value on failure. */
! 1264: /****************************************************************************/
! 1265: int
! 1266: bnx_acquire_nvram_lock(struct bnx_softc *sc)
! 1267: {
! 1268: u_int32_t val;
! 1269: int j;
! 1270:
! 1271: DBPRINT(sc, BNX_VERBOSE, "Acquiring NVRAM lock.\n");
! 1272:
! 1273: /* Request access to the flash interface. */
! 1274: REG_WR(sc, BNX_NVM_SW_ARB, BNX_NVM_SW_ARB_ARB_REQ_SET2);
! 1275: for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
! 1276: val = REG_RD(sc, BNX_NVM_SW_ARB);
! 1277: if (val & BNX_NVM_SW_ARB_ARB_ARB2)
! 1278: break;
! 1279:
! 1280: DELAY(5);
! 1281: }
! 1282:
! 1283: if (j >= NVRAM_TIMEOUT_COUNT) {
! 1284: DBPRINT(sc, BNX_WARN, "Timeout acquiring NVRAM lock!\n");
! 1285: return (EBUSY);
! 1286: }
! 1287:
! 1288: return (0);
! 1289: }
! 1290:
! 1291: /****************************************************************************/
! 1292: /* Release NVRAM lock. */
! 1293: /* */
! 1294: /* When the caller is finished accessing NVRAM the lock must be released. */
! 1295: /* Locks 0 and 2 are reserved, lock 1 is used by firmware and lock 2 is */
! 1296: /* for use by the driver. */
! 1297: /* */
! 1298: /* Returns: */
! 1299: /* 0 on success, positive value on failure. */
! 1300: /****************************************************************************/
! 1301: int
! 1302: bnx_release_nvram_lock(struct bnx_softc *sc)
! 1303: {
! 1304: int j;
! 1305: u_int32_t val;
! 1306:
! 1307: DBPRINT(sc, BNX_VERBOSE, "Releasing NVRAM lock.\n");
! 1308:
! 1309: /* Relinquish nvram interface. */
! 1310: REG_WR(sc, BNX_NVM_SW_ARB, BNX_NVM_SW_ARB_ARB_REQ_CLR2);
! 1311:
! 1312: for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
! 1313: val = REG_RD(sc, BNX_NVM_SW_ARB);
! 1314: if (!(val & BNX_NVM_SW_ARB_ARB_ARB2))
! 1315: break;
! 1316:
! 1317: DELAY(5);
! 1318: }
! 1319:
! 1320: if (j >= NVRAM_TIMEOUT_COUNT) {
! 1321: DBPRINT(sc, BNX_WARN, "Timeout reeasing NVRAM lock!\n");
! 1322: return (EBUSY);
! 1323: }
! 1324:
! 1325: return (0);
! 1326: }
! 1327:
! 1328: #ifdef BNX_NVRAM_WRITE_SUPPORT
! 1329: /****************************************************************************/
! 1330: /* Enable NVRAM write access. */
! 1331: /* */
! 1332: /* Before writing to NVRAM the caller must enable NVRAM writes. */
! 1333: /* */
! 1334: /* Returns: */
! 1335: /* 0 on success, positive value on failure. */
! 1336: /****************************************************************************/
! 1337: int
! 1338: bnx_enable_nvram_write(struct bnx_softc *sc)
! 1339: {
! 1340: u_int32_t val;
! 1341:
! 1342: DBPRINT(sc, BNX_VERBOSE, "Enabling NVRAM write.\n");
! 1343:
! 1344: val = REG_RD(sc, BNX_MISC_CFG);
! 1345: REG_WR(sc, BNX_MISC_CFG, val | BNX_MISC_CFG_NVM_WR_EN_PCI);
! 1346:
! 1347: if (!sc->bnx_flash_info->buffered) {
! 1348: int j;
! 1349:
! 1350: REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE);
! 1351: REG_WR(sc, BNX_NVM_COMMAND,
! 1352: BNX_NVM_COMMAND_WREN | BNX_NVM_COMMAND_DOIT);
! 1353:
! 1354: for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
! 1355: DELAY(5);
! 1356:
! 1357: val = REG_RD(sc, BNX_NVM_COMMAND);
! 1358: if (val & BNX_NVM_COMMAND_DONE)
! 1359: break;
! 1360: }
! 1361:
! 1362: if (j >= NVRAM_TIMEOUT_COUNT) {
! 1363: DBPRINT(sc, BNX_WARN, "Timeout writing NVRAM!\n");
! 1364: return (EBUSY);
! 1365: }
! 1366: }
! 1367:
! 1368: return (0);
! 1369: }
! 1370:
! 1371: /****************************************************************************/
! 1372: /* Disable NVRAM write access. */
! 1373: /* */
! 1374: /* When the caller is finished writing to NVRAM write access must be */
! 1375: /* disabled. */
! 1376: /* */
! 1377: /* Returns: */
! 1378: /* Nothing. */
! 1379: /****************************************************************************/
! 1380: void
! 1381: bnx_disable_nvram_write(struct bnx_softc *sc)
! 1382: {
! 1383: u_int32_t val;
! 1384:
! 1385: DBPRINT(sc, BNX_VERBOSE, "Disabling NVRAM write.\n");
! 1386:
! 1387: val = REG_RD(sc, BNX_MISC_CFG);
! 1388: REG_WR(sc, BNX_MISC_CFG, val & ~BNX_MISC_CFG_NVM_WR_EN);
! 1389: }
! 1390: #endif
! 1391:
! 1392: /****************************************************************************/
! 1393: /* Enable NVRAM access. */
! 1394: /* */
! 1395: /* Before accessing NVRAM for read or write operations the caller must */
! 1396: /* enabled NVRAM access. */
! 1397: /* */
! 1398: /* Returns: */
! 1399: /* Nothing. */
! 1400: /****************************************************************************/
! 1401: void
! 1402: bnx_enable_nvram_access(struct bnx_softc *sc)
! 1403: {
! 1404: u_int32_t val;
! 1405:
! 1406: DBPRINT(sc, BNX_VERBOSE, "Enabling NVRAM access.\n");
! 1407:
! 1408: val = REG_RD(sc, BNX_NVM_ACCESS_ENABLE);
! 1409: /* Enable both bits, even on read. */
! 1410: REG_WR(sc, BNX_NVM_ACCESS_ENABLE,
! 1411: val | BNX_NVM_ACCESS_ENABLE_EN | BNX_NVM_ACCESS_ENABLE_WR_EN);
! 1412: }
! 1413:
! 1414: /****************************************************************************/
! 1415: /* Disable NVRAM access. */
! 1416: /* */
! 1417: /* When the caller is finished accessing NVRAM access must be disabled. */
! 1418: /* */
! 1419: /* Returns: */
! 1420: /* Nothing. */
! 1421: /****************************************************************************/
! 1422: void
! 1423: bnx_disable_nvram_access(struct bnx_softc *sc)
! 1424: {
! 1425: u_int32_t val;
! 1426:
! 1427: DBPRINT(sc, BNX_VERBOSE, "Disabling NVRAM access.\n");
! 1428:
! 1429: val = REG_RD(sc, BNX_NVM_ACCESS_ENABLE);
! 1430:
! 1431: /* Disable both bits, even after read. */
! 1432: REG_WR(sc, BNX_NVM_ACCESS_ENABLE,
! 1433: val & ~(BNX_NVM_ACCESS_ENABLE_EN | BNX_NVM_ACCESS_ENABLE_WR_EN));
! 1434: }
! 1435:
! 1436: #ifdef BNX_NVRAM_WRITE_SUPPORT
! 1437: /****************************************************************************/
! 1438: /* Erase NVRAM page before writing. */
! 1439: /* */
! 1440: /* Non-buffered flash parts require that a page be erased before it is */
! 1441: /* written. */
! 1442: /* */
! 1443: /* Returns: */
! 1444: /* 0 on success, positive value on failure. */
! 1445: /****************************************************************************/
! 1446: int
! 1447: bnx_nvram_erase_page(struct bnx_softc *sc, u_int32_t offset)
! 1448: {
! 1449: u_int32_t cmd;
! 1450: int j;
! 1451:
! 1452: /* Buffered flash doesn't require an erase. */
! 1453: if (sc->bnx_flash_info->buffered)
! 1454: return (0);
! 1455:
! 1456: DBPRINT(sc, BNX_VERBOSE, "Erasing NVRAM page.\n");
! 1457:
! 1458: /* Build an erase command. */
! 1459: cmd = BNX_NVM_COMMAND_ERASE | BNX_NVM_COMMAND_WR |
! 1460: BNX_NVM_COMMAND_DOIT;
! 1461:
! 1462: /*
! 1463: * Clear the DONE bit separately, set the NVRAM address to erase,
! 1464: * and issue the erase command.
! 1465: */
! 1466: REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE);
! 1467: REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE);
! 1468: REG_WR(sc, BNX_NVM_COMMAND, cmd);
! 1469:
! 1470: /* Wait for completion. */
! 1471: for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
! 1472: u_int32_t val;
! 1473:
! 1474: DELAY(5);
! 1475:
! 1476: val = REG_RD(sc, BNX_NVM_COMMAND);
! 1477: if (val & BNX_NVM_COMMAND_DONE)
! 1478: break;
! 1479: }
! 1480:
! 1481: if (j >= NVRAM_TIMEOUT_COUNT) {
! 1482: DBPRINT(sc, BNX_WARN, "Timeout erasing NVRAM.\n");
! 1483: return (EBUSY);
! 1484: }
! 1485:
! 1486: return (0);
! 1487: }
! 1488: #endif /* BNX_NVRAM_WRITE_SUPPORT */
! 1489:
! 1490: /****************************************************************************/
! 1491: /* Read a dword (32 bits) from NVRAM. */
! 1492: /* */
! 1493: /* Read a 32 bit word from NVRAM. The caller is assumed to have already */
! 1494: /* obtained the NVRAM lock and enabled the controller for NVRAM access. */
! 1495: /* */
! 1496: /* Returns: */
! 1497: /* 0 on success and the 32 bit value read, positive value on failure. */
! 1498: /****************************************************************************/
! 1499: int
! 1500: bnx_nvram_read_dword(struct bnx_softc *sc, u_int32_t offset,
! 1501: u_int8_t *ret_val, u_int32_t cmd_flags)
! 1502: {
! 1503: u_int32_t cmd;
! 1504: int i, rc = 0;
! 1505:
! 1506: /* Build the command word. */
! 1507: cmd = BNX_NVM_COMMAND_DOIT | cmd_flags;
! 1508:
! 1509: /* Calculate the offset for buffered flash. */
! 1510: if (sc->bnx_flash_info->buffered)
! 1511: offset = ((offset / sc->bnx_flash_info->page_size) <<
! 1512: sc->bnx_flash_info->page_bits) +
! 1513: (offset % sc->bnx_flash_info->page_size);
! 1514:
! 1515: /*
! 1516: * Clear the DONE bit separately, set the address to read,
! 1517: * and issue the read.
! 1518: */
! 1519: REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE);
! 1520: REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE);
! 1521: REG_WR(sc, BNX_NVM_COMMAND, cmd);
! 1522:
! 1523: /* Wait for completion. */
! 1524: for (i = 0; i < NVRAM_TIMEOUT_COUNT; i++) {
! 1525: u_int32_t val;
! 1526:
! 1527: DELAY(5);
! 1528:
! 1529: val = REG_RD(sc, BNX_NVM_COMMAND);
! 1530: if (val & BNX_NVM_COMMAND_DONE) {
! 1531: val = REG_RD(sc, BNX_NVM_READ);
! 1532:
! 1533: val = bnx_be32toh(val);
! 1534: memcpy(ret_val, &val, 4);
! 1535: break;
! 1536: }
! 1537: }
! 1538:
! 1539: /* Check for errors. */
! 1540: if (i >= NVRAM_TIMEOUT_COUNT) {
! 1541: BNX_PRINTF(sc, "%s(%d): Timeout error reading NVRAM at "
! 1542: "offset 0x%08X!\n", __FILE__, __LINE__, offset);
! 1543: rc = EBUSY;
! 1544: }
! 1545:
! 1546: return(rc);
! 1547: }
! 1548:
! 1549: #ifdef BNX_NVRAM_WRITE_SUPPORT
! 1550: /****************************************************************************/
! 1551: /* Write a dword (32 bits) to NVRAM. */
! 1552: /* */
! 1553: /* Write a 32 bit word to NVRAM. The caller is assumed to have already */
! 1554: /* obtained the NVRAM lock, enabled the controller for NVRAM access, and */
! 1555: /* enabled NVRAM write access. */
! 1556: /* */
! 1557: /* Returns: */
! 1558: /* 0 on success, positive value on failure. */
! 1559: /****************************************************************************/
! 1560: int
! 1561: bnx_nvram_write_dword(struct bnx_softc *sc, u_int32_t offset, u_int8_t *val,
! 1562: u_int32_t cmd_flags)
! 1563: {
! 1564: u_int32_t cmd, val32;
! 1565: int j;
! 1566:
! 1567: /* Build the command word. */
! 1568: cmd = BNX_NVM_COMMAND_DOIT | BNX_NVM_COMMAND_WR | cmd_flags;
! 1569:
! 1570: /* Calculate the offset for buffered flash. */
! 1571: if (sc->bnx_flash_info->buffered)
! 1572: offset = ((offset / sc->bnx_flash_info->page_size) <<
! 1573: sc->bnx_flash_info->page_bits) +
! 1574: (offset % sc->bnx_flash_info->page_size);
! 1575:
! 1576: /*
! 1577: * Clear the DONE bit separately, convert NVRAM data to big-endian,
! 1578: * set the NVRAM address to write, and issue the write command
! 1579: */
! 1580: REG_WR(sc, BNX_NVM_COMMAND, BNX_NVM_COMMAND_DONE);
! 1581: memcpy(&val32, val, 4);
! 1582: val32 = htobe32(val32);
! 1583: REG_WR(sc, BNX_NVM_WRITE, val32);
! 1584: REG_WR(sc, BNX_NVM_ADDR, offset & BNX_NVM_ADDR_NVM_ADDR_VALUE);
! 1585: REG_WR(sc, BNX_NVM_COMMAND, cmd);
! 1586:
! 1587: /* Wait for completion. */
! 1588: for (j = 0; j < NVRAM_TIMEOUT_COUNT; j++) {
! 1589: DELAY(5);
! 1590:
! 1591: if (REG_RD(sc, BNX_NVM_COMMAND) & BNX_NVM_COMMAND_DONE)
! 1592: break;
! 1593: }
! 1594: if (j >= NVRAM_TIMEOUT_COUNT) {
! 1595: BNX_PRINTF(sc, "%s(%d): Timeout error writing NVRAM at "
! 1596: "offset 0x%08X\n", __FILE__, __LINE__, offset);
! 1597: return (EBUSY);
! 1598: }
! 1599:
! 1600: return (0);
! 1601: }
! 1602: #endif /* BNX_NVRAM_WRITE_SUPPORT */
! 1603:
! 1604: /****************************************************************************/
! 1605: /* Initialize NVRAM access. */
! 1606: /* */
! 1607: /* Identify the NVRAM device in use and prepare the NVRAM interface to */
! 1608: /* access that device. */
! 1609: /* */
! 1610: /* Returns: */
! 1611: /* 0 on success, positive value on failure. */
! 1612: /****************************************************************************/
! 1613: int
! 1614: bnx_init_nvram(struct bnx_softc *sc)
! 1615: {
! 1616: u_int32_t val;
! 1617: int j, entry_count, rc;
! 1618: struct flash_spec *flash;
! 1619:
! 1620: DBPRINT(sc,BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 1621:
! 1622: /* Determine the selected interface. */
! 1623: val = REG_RD(sc, BNX_NVM_CFG1);
! 1624:
! 1625: entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
! 1626:
! 1627: rc = 0;
! 1628:
! 1629: /*
! 1630: * Flash reconfiguration is required to support additional
! 1631: * NVRAM devices not directly supported in hardware.
! 1632: * Check if the flash interface was reconfigured
! 1633: * by the bootcode.
! 1634: */
! 1635:
! 1636: if (val & 0x40000000) {
! 1637: /* Flash interface reconfigured by bootcode. */
! 1638:
! 1639: DBPRINT(sc,BNX_INFO_LOAD,
! 1640: "bnx_init_nvram(): Flash WAS reconfigured.\n");
! 1641:
! 1642: for (j = 0, flash = &flash_table[0]; j < entry_count;
! 1643: j++, flash++) {
! 1644: if ((val & FLASH_BACKUP_STRAP_MASK) ==
! 1645: (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
! 1646: sc->bnx_flash_info = flash;
! 1647: break;
! 1648: }
! 1649: }
! 1650: } else {
! 1651: /* Flash interface not yet reconfigured. */
! 1652: u_int32_t mask;
! 1653:
! 1654: DBPRINT(sc,BNX_INFO_LOAD,
! 1655: "bnx_init_nvram(): Flash was NOT reconfigured.\n");
! 1656:
! 1657: if (val & (1 << 23))
! 1658: mask = FLASH_BACKUP_STRAP_MASK;
! 1659: else
! 1660: mask = FLASH_STRAP_MASK;
! 1661:
! 1662: /* Look for the matching NVRAM device configuration data. */
! 1663: for (j = 0, flash = &flash_table[0]; j < entry_count;
! 1664: j++, flash++) {
! 1665: /* Check if the dev matches any of the known devices. */
! 1666: if ((val & mask) == (flash->strapping & mask)) {
! 1667: /* Found a device match. */
! 1668: sc->bnx_flash_info = flash;
! 1669:
! 1670: /* Request access to the flash interface. */
! 1671: if ((rc = bnx_acquire_nvram_lock(sc)) != 0)
! 1672: return (rc);
! 1673:
! 1674: /* Reconfigure the flash interface. */
! 1675: bnx_enable_nvram_access(sc);
! 1676: REG_WR(sc, BNX_NVM_CFG1, flash->config1);
! 1677: REG_WR(sc, BNX_NVM_CFG2, flash->config2);
! 1678: REG_WR(sc, BNX_NVM_CFG3, flash->config3);
! 1679: REG_WR(sc, BNX_NVM_WRITE1, flash->write1);
! 1680: bnx_disable_nvram_access(sc);
! 1681: bnx_release_nvram_lock(sc);
! 1682:
! 1683: break;
! 1684: }
! 1685: }
! 1686: }
! 1687:
! 1688: /* Check if a matching device was found. */
! 1689: if (j == entry_count) {
! 1690: sc->bnx_flash_info = NULL;
! 1691: BNX_PRINTF(sc, "%s(%d): Unknown Flash NVRAM found!\n",
! 1692: __FILE__, __LINE__);
! 1693: rc = ENODEV;
! 1694: }
! 1695:
! 1696: /* Write the flash config data to the shared memory interface. */
! 1697: val = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_SHARED_HW_CFG_CONFIG2);
! 1698: val &= BNX_SHARED_HW_CFG2_NVM_SIZE_MASK;
! 1699: if (val)
! 1700: sc->bnx_flash_size = val;
! 1701: else
! 1702: sc->bnx_flash_size = sc->bnx_flash_info->total_size;
! 1703:
! 1704: DBPRINT(sc, BNX_INFO_LOAD, "bnx_init_nvram() flash->total_size = "
! 1705: "0x%08X\n", sc->bnx_flash_info->total_size);
! 1706:
! 1707: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 1708:
! 1709: return (rc);
! 1710: }
! 1711:
! 1712: /****************************************************************************/
! 1713: /* Read an arbitrary range of data from NVRAM. */
! 1714: /* */
! 1715: /* Prepares the NVRAM interface for access and reads the requested data */
! 1716: /* into the supplied buffer. */
! 1717: /* */
! 1718: /* Returns: */
! 1719: /* 0 on success and the data read, positive value on failure. */
! 1720: /****************************************************************************/
! 1721: int
! 1722: bnx_nvram_read(struct bnx_softc *sc, u_int32_t offset, u_int8_t *ret_buf,
! 1723: int buf_size)
! 1724: {
! 1725: int rc = 0;
! 1726: u_int32_t cmd_flags, offset32, len32, extra;
! 1727:
! 1728: if (buf_size == 0)
! 1729: return (0);
! 1730:
! 1731: /* Request access to the flash interface. */
! 1732: if ((rc = bnx_acquire_nvram_lock(sc)) != 0)
! 1733: return (rc);
! 1734:
! 1735: /* Enable access to flash interface */
! 1736: bnx_enable_nvram_access(sc);
! 1737:
! 1738: len32 = buf_size;
! 1739: offset32 = offset;
! 1740: extra = 0;
! 1741:
! 1742: cmd_flags = 0;
! 1743:
! 1744: if (offset32 & 3) {
! 1745: u_int8_t buf[4];
! 1746: u_int32_t pre_len;
! 1747:
! 1748: offset32 &= ~3;
! 1749: pre_len = 4 - (offset & 3);
! 1750:
! 1751: if (pre_len >= len32) {
! 1752: pre_len = len32;
! 1753: cmd_flags =
! 1754: BNX_NVM_COMMAND_FIRST | BNX_NVM_COMMAND_LAST;
! 1755: } else
! 1756: cmd_flags = BNX_NVM_COMMAND_FIRST;
! 1757:
! 1758: rc = bnx_nvram_read_dword(sc, offset32, buf, cmd_flags);
! 1759:
! 1760: if (rc)
! 1761: return (rc);
! 1762:
! 1763: memcpy(ret_buf, buf + (offset & 3), pre_len);
! 1764:
! 1765: offset32 += 4;
! 1766: ret_buf += pre_len;
! 1767: len32 -= pre_len;
! 1768: }
! 1769:
! 1770: if (len32 & 3) {
! 1771: extra = 4 - (len32 & 3);
! 1772: len32 = (len32 + 4) & ~3;
! 1773: }
! 1774:
! 1775: if (len32 == 4) {
! 1776: u_int8_t buf[4];
! 1777:
! 1778: if (cmd_flags)
! 1779: cmd_flags = BNX_NVM_COMMAND_LAST;
! 1780: else
! 1781: cmd_flags =
! 1782: BNX_NVM_COMMAND_FIRST | BNX_NVM_COMMAND_LAST;
! 1783:
! 1784: rc = bnx_nvram_read_dword(sc, offset32, buf, cmd_flags);
! 1785:
! 1786: memcpy(ret_buf, buf, 4 - extra);
! 1787: } else if (len32 > 0) {
! 1788: u_int8_t buf[4];
! 1789:
! 1790: /* Read the first word. */
! 1791: if (cmd_flags)
! 1792: cmd_flags = 0;
! 1793: else
! 1794: cmd_flags = BNX_NVM_COMMAND_FIRST;
! 1795:
! 1796: rc = bnx_nvram_read_dword(sc, offset32, ret_buf, cmd_flags);
! 1797:
! 1798: /* Advance to the next dword. */
! 1799: offset32 += 4;
! 1800: ret_buf += 4;
! 1801: len32 -= 4;
! 1802:
! 1803: while (len32 > 4 && rc == 0) {
! 1804: rc = bnx_nvram_read_dword(sc, offset32, ret_buf, 0);
! 1805:
! 1806: /* Advance to the next dword. */
! 1807: offset32 += 4;
! 1808: ret_buf += 4;
! 1809: len32 -= 4;
! 1810: }
! 1811:
! 1812: if (rc)
! 1813: return (rc);
! 1814:
! 1815: cmd_flags = BNX_NVM_COMMAND_LAST;
! 1816: rc = bnx_nvram_read_dword(sc, offset32, buf, cmd_flags);
! 1817:
! 1818: memcpy(ret_buf, buf, 4 - extra);
! 1819: }
! 1820:
! 1821: /* Disable access to flash interface and release the lock. */
! 1822: bnx_disable_nvram_access(sc);
! 1823: bnx_release_nvram_lock(sc);
! 1824:
! 1825: return (rc);
! 1826: }
! 1827:
! 1828: #ifdef BNX_NVRAM_WRITE_SUPPORT
! 1829: /****************************************************************************/
! 1830: /* Write an arbitrary range of data from NVRAM. */
! 1831: /* */
! 1832: /* Prepares the NVRAM interface for write access and writes the requested */
! 1833: /* data from the supplied buffer. The caller is responsible for */
! 1834: /* calculating any appropriate CRCs. */
! 1835: /* */
! 1836: /* Returns: */
! 1837: /* 0 on success, positive value on failure. */
! 1838: /****************************************************************************/
! 1839: int
! 1840: bnx_nvram_write(struct bnx_softc *sc, u_int32_t offset, u_int8_t *data_buf,
! 1841: int buf_size)
! 1842: {
! 1843: u_int32_t written, offset32, len32;
! 1844: u_int8_t *buf, start[4], end[4];
! 1845: int rc = 0;
! 1846: int align_start, align_end;
! 1847:
! 1848: buf = data_buf;
! 1849: offset32 = offset;
! 1850: len32 = buf_size;
! 1851: align_start = align_end = 0;
! 1852:
! 1853: if ((align_start = (offset32 & 3))) {
! 1854: offset32 &= ~3;
! 1855: len32 += align_start;
! 1856: if ((rc = bnx_nvram_read(sc, offset32, start, 4)))
! 1857: return (rc);
! 1858: }
! 1859:
! 1860: if (len32 & 3) {
! 1861: if ((len32 > 4) || !align_start) {
! 1862: align_end = 4 - (len32 & 3);
! 1863: len32 += align_end;
! 1864: if ((rc = bnx_nvram_read(sc, offset32 + len32 - 4,
! 1865: end, 4))) {
! 1866: return (rc);
! 1867: }
! 1868: }
! 1869: }
! 1870:
! 1871: if (align_start || align_end) {
! 1872: buf = malloc(len32, M_DEVBUF, M_NOWAIT);
! 1873: if (buf == 0)
! 1874: return (ENOMEM);
! 1875:
! 1876: if (align_start)
! 1877: memcpy(buf, start, 4);
! 1878:
! 1879: if (align_end)
! 1880: memcpy(buf + len32 - 4, end, 4);
! 1881:
! 1882: memcpy(buf + align_start, data_buf, buf_size);
! 1883: }
! 1884:
! 1885: written = 0;
! 1886: while ((written < len32) && (rc == 0)) {
! 1887: u_int32_t page_start, page_end, data_start, data_end;
! 1888: u_int32_t addr, cmd_flags;
! 1889: int i;
! 1890: u_int8_t flash_buffer[264];
! 1891:
! 1892: /* Find the page_start addr */
! 1893: page_start = offset32 + written;
! 1894: page_start -= (page_start % sc->bnx_flash_info->page_size);
! 1895: /* Find the page_end addr */
! 1896: page_end = page_start + sc->bnx_flash_info->page_size;
! 1897: /* Find the data_start addr */
! 1898: data_start = (written == 0) ? offset32 : page_start;
! 1899: /* Find the data_end addr */
! 1900: data_end = (page_end > offset32 + len32) ?
! 1901: (offset32 + len32) : page_end;
! 1902:
! 1903: /* Request access to the flash interface. */
! 1904: if ((rc = bnx_acquire_nvram_lock(sc)) != 0)
! 1905: goto nvram_write_end;
! 1906:
! 1907: /* Enable access to flash interface */
! 1908: bnx_enable_nvram_access(sc);
! 1909:
! 1910: cmd_flags = BNX_NVM_COMMAND_FIRST;
! 1911: if (sc->bnx_flash_info->buffered == 0) {
! 1912: int j;
! 1913:
! 1914: /* Read the whole page into the buffer
! 1915: * (non-buffer flash only) */
! 1916: for (j = 0; j < sc->bnx_flash_info->page_size; j += 4) {
! 1917: if (j == (sc->bnx_flash_info->page_size - 4))
! 1918: cmd_flags |= BNX_NVM_COMMAND_LAST;
! 1919:
! 1920: rc = bnx_nvram_read_dword(sc,
! 1921: page_start + j,
! 1922: &flash_buffer[j],
! 1923: cmd_flags);
! 1924:
! 1925: if (rc)
! 1926: goto nvram_write_end;
! 1927:
! 1928: cmd_flags = 0;
! 1929: }
! 1930: }
! 1931:
! 1932: /* Enable writes to flash interface (unlock write-protect) */
! 1933: if ((rc = bnx_enable_nvram_write(sc)) != 0)
! 1934: goto nvram_write_end;
! 1935:
! 1936: /* Erase the page */
! 1937: if ((rc = bnx_nvram_erase_page(sc, page_start)) != 0)
! 1938: goto nvram_write_end;
! 1939:
! 1940: /* Re-enable the write again for the actual write */
! 1941: bnx_enable_nvram_write(sc);
! 1942:
! 1943: /* Loop to write back the buffer data from page_start to
! 1944: * data_start */
! 1945: i = 0;
! 1946: if (sc->bnx_flash_info->buffered == 0) {
! 1947: for (addr = page_start; addr < data_start;
! 1948: addr += 4, i += 4) {
! 1949:
! 1950: rc = bnx_nvram_write_dword(sc, addr,
! 1951: &flash_buffer[i], cmd_flags);
! 1952:
! 1953: if (rc != 0)
! 1954: goto nvram_write_end;
! 1955:
! 1956: cmd_flags = 0;
! 1957: }
! 1958: }
! 1959:
! 1960: /* Loop to write the new data from data_start to data_end */
! 1961: for (addr = data_start; addr < data_end; addr += 4, i++) {
! 1962: if ((addr == page_end - 4) ||
! 1963: ((sc->bnx_flash_info->buffered) &&
! 1964: (addr == data_end - 4))) {
! 1965:
! 1966: cmd_flags |= BNX_NVM_COMMAND_LAST;
! 1967: }
! 1968:
! 1969: rc = bnx_nvram_write_dword(sc, addr, buf, cmd_flags);
! 1970:
! 1971: if (rc != 0)
! 1972: goto nvram_write_end;
! 1973:
! 1974: cmd_flags = 0;
! 1975: buf += 4;
! 1976: }
! 1977:
! 1978: /* Loop to write back the buffer data from data_end
! 1979: * to page_end */
! 1980: if (sc->bnx_flash_info->buffered == 0) {
! 1981: for (addr = data_end; addr < page_end;
! 1982: addr += 4, i += 4) {
! 1983:
! 1984: if (addr == page_end-4)
! 1985: cmd_flags = BNX_NVM_COMMAND_LAST;
! 1986:
! 1987: rc = bnx_nvram_write_dword(sc, addr,
! 1988: &flash_buffer[i], cmd_flags);
! 1989:
! 1990: if (rc != 0)
! 1991: goto nvram_write_end;
! 1992:
! 1993: cmd_flags = 0;
! 1994: }
! 1995: }
! 1996:
! 1997: /* Disable writes to flash interface (lock write-protect) */
! 1998: bnx_disable_nvram_write(sc);
! 1999:
! 2000: /* Disable access to flash interface */
! 2001: bnx_disable_nvram_access(sc);
! 2002: bnx_release_nvram_lock(sc);
! 2003:
! 2004: /* Increment written */
! 2005: written += data_end - data_start;
! 2006: }
! 2007:
! 2008: nvram_write_end:
! 2009: if (align_start || align_end)
! 2010: free(buf, M_DEVBUF);
! 2011:
! 2012: return (rc);
! 2013: }
! 2014: #endif /* BNX_NVRAM_WRITE_SUPPORT */
! 2015:
! 2016: /****************************************************************************/
! 2017: /* Verifies that NVRAM is accessible and contains valid data. */
! 2018: /* */
! 2019: /* Reads the configuration data from NVRAM and verifies that the CRC is */
! 2020: /* correct. */
! 2021: /* */
! 2022: /* Returns: */
! 2023: /* 0 on success, positive value on failure. */
! 2024: /****************************************************************************/
! 2025: int
! 2026: bnx_nvram_test(struct bnx_softc *sc)
! 2027: {
! 2028: u_int32_t buf[BNX_NVRAM_SIZE / 4];
! 2029: u_int8_t *data = (u_int8_t *) buf;
! 2030: int rc = 0;
! 2031: u_int32_t magic, csum;
! 2032:
! 2033: /*
! 2034: * Check that the device NVRAM is valid by reading
! 2035: * the magic value at offset 0.
! 2036: */
! 2037: if ((rc = bnx_nvram_read(sc, 0, data, 4)) != 0)
! 2038: goto bnx_nvram_test_done;
! 2039:
! 2040: magic = bnx_be32toh(buf[0]);
! 2041: if (magic != BNX_NVRAM_MAGIC) {
! 2042: rc = ENODEV;
! 2043: BNX_PRINTF(sc, "%s(%d): Invalid NVRAM magic value! "
! 2044: "Expected: 0x%08X, Found: 0x%08X\n",
! 2045: __FILE__, __LINE__, BNX_NVRAM_MAGIC, magic);
! 2046: goto bnx_nvram_test_done;
! 2047: }
! 2048:
! 2049: /*
! 2050: * Verify that the device NVRAM includes valid
! 2051: * configuration data.
! 2052: */
! 2053: if ((rc = bnx_nvram_read(sc, 0x100, data, BNX_NVRAM_SIZE)) != 0)
! 2054: goto bnx_nvram_test_done;
! 2055:
! 2056: csum = ether_crc32_le(data, 0x100);
! 2057: if (csum != BNX_CRC32_RESIDUAL) {
! 2058: rc = ENODEV;
! 2059: BNX_PRINTF(sc, "%s(%d): Invalid Manufacturing Information "
! 2060: "NVRAM CRC! Expected: 0x%08X, Found: 0x%08X\n",
! 2061: __FILE__, __LINE__, BNX_CRC32_RESIDUAL, csum);
! 2062: goto bnx_nvram_test_done;
! 2063: }
! 2064:
! 2065: csum = ether_crc32_le(data + 0x100, 0x100);
! 2066: if (csum != BNX_CRC32_RESIDUAL) {
! 2067: BNX_PRINTF(sc, "%s(%d): Invalid Feature Configuration "
! 2068: "Information NVRAM CRC! Expected: 0x%08X, Found: 08%08X\n",
! 2069: __FILE__, __LINE__, BNX_CRC32_RESIDUAL, csum);
! 2070: rc = ENODEV;
! 2071: }
! 2072:
! 2073: bnx_nvram_test_done:
! 2074: return (rc);
! 2075: }
! 2076:
! 2077: /****************************************************************************/
! 2078: /* Free any DMA memory owned by the driver. */
! 2079: /* */
! 2080: /* Scans through each data structre that requires DMA memory and frees */
! 2081: /* the memory if allocated. */
! 2082: /* */
! 2083: /* Returns: */
! 2084: /* Nothing. */
! 2085: /****************************************************************************/
! 2086: void
! 2087: bnx_dma_free(struct bnx_softc *sc)
! 2088: {
! 2089: int i;
! 2090:
! 2091: DBPRINT(sc,BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 2092:
! 2093: /* Destroy the status block. */
! 2094: if (sc->status_block != NULL && sc->status_map != NULL) {
! 2095: bus_dmamap_unload(sc->bnx_dmatag, sc->status_map);
! 2096: bus_dmamem_unmap(sc->bnx_dmatag, (caddr_t)sc->status_block,
! 2097: BNX_STATUS_BLK_SZ);
! 2098: bus_dmamem_free(sc->bnx_dmatag, &sc->status_seg,
! 2099: sc->status_rseg);
! 2100: bus_dmamap_destroy(sc->bnx_dmatag, sc->status_map);
! 2101: sc->status_block = NULL;
! 2102: sc->status_map = NULL;
! 2103: }
! 2104:
! 2105: /* Destroy the statistics block. */
! 2106: if (sc->stats_block != NULL && sc->stats_map != NULL) {
! 2107: bus_dmamap_unload(sc->bnx_dmatag, sc->stats_map);
! 2108: bus_dmamem_unmap(sc->bnx_dmatag, (caddr_t)sc->stats_block,
! 2109: BNX_STATS_BLK_SZ);
! 2110: bus_dmamem_free(sc->bnx_dmatag, &sc->stats_seg,
! 2111: sc->stats_rseg);
! 2112: bus_dmamap_destroy(sc->bnx_dmatag, sc->stats_map);
! 2113: sc->stats_block = NULL;
! 2114: sc->stats_map = NULL;
! 2115: }
! 2116:
! 2117: /* Free, unmap and destroy all TX buffer descriptor chain pages. */
! 2118: for (i = 0; i < TX_PAGES; i++ ) {
! 2119: if (sc->tx_bd_chain[i] != NULL &&
! 2120: sc->tx_bd_chain_map[i] != NULL) {
! 2121: bus_dmamap_unload(sc->bnx_dmatag,
! 2122: sc->tx_bd_chain_map[i]);
! 2123: bus_dmamem_unmap(sc->bnx_dmatag,
! 2124: (caddr_t)sc->tx_bd_chain[i], BNX_TX_CHAIN_PAGE_SZ);
! 2125: bus_dmamem_free(sc->bnx_dmatag, &sc->tx_bd_chain_seg[i],
! 2126: sc->tx_bd_chain_rseg[i]);
! 2127: bus_dmamap_destroy(sc->bnx_dmatag,
! 2128: sc->tx_bd_chain_map[i]);
! 2129: sc->tx_bd_chain[i] = NULL;
! 2130: sc->tx_bd_chain_map[i] = NULL;
! 2131: }
! 2132: }
! 2133:
! 2134: /* Unload and destroy the TX mbuf maps. */
! 2135: for (i = 0; i < TOTAL_TX_BD; i++) {
! 2136: if (sc->tx_mbuf_map[i] != NULL) {
! 2137: bus_dmamap_unload(sc->bnx_dmatag, sc->tx_mbuf_map[i]);
! 2138: bus_dmamap_destroy(sc->bnx_dmatag, sc->tx_mbuf_map[i]);
! 2139: }
! 2140: }
! 2141:
! 2142: /* Free, unmap and destroy all RX buffer descriptor chain pages. */
! 2143: for (i = 0; i < RX_PAGES; i++ ) {
! 2144: if (sc->rx_bd_chain[i] != NULL &&
! 2145: sc->rx_bd_chain_map[i] != NULL) {
! 2146: bus_dmamap_unload(sc->bnx_dmatag,
! 2147: sc->rx_bd_chain_map[i]);
! 2148: bus_dmamem_unmap(sc->bnx_dmatag,
! 2149: (caddr_t)sc->rx_bd_chain[i], BNX_RX_CHAIN_PAGE_SZ);
! 2150: bus_dmamem_free(sc->bnx_dmatag, &sc->rx_bd_chain_seg[i],
! 2151: sc->rx_bd_chain_rseg[i]);
! 2152:
! 2153: bus_dmamap_destroy(sc->bnx_dmatag,
! 2154: sc->rx_bd_chain_map[i]);
! 2155: sc->rx_bd_chain[i] = NULL;
! 2156: sc->rx_bd_chain_map[i] = NULL;
! 2157: }
! 2158: }
! 2159:
! 2160: /* Unload and destroy the RX mbuf maps. */
! 2161: for (i = 0; i < TOTAL_RX_BD; i++) {
! 2162: if (sc->rx_mbuf_map[i] != NULL) {
! 2163: bus_dmamap_unload(sc->bnx_dmatag, sc->rx_mbuf_map[i]);
! 2164: bus_dmamap_destroy(sc->bnx_dmatag, sc->rx_mbuf_map[i]);
! 2165: }
! 2166: }
! 2167:
! 2168: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 2169: }
! 2170:
! 2171: /****************************************************************************/
! 2172: /* Allocate any DMA memory needed by the driver. */
! 2173: /* */
! 2174: /* Allocates DMA memory needed for the various global structures needed by */
! 2175: /* hardware. */
! 2176: /* */
! 2177: /* Returns: */
! 2178: /* 0 for success, positive value for failure. */
! 2179: /****************************************************************************/
! 2180: int
! 2181: bnx_dma_alloc(struct bnx_softc *sc)
! 2182: {
! 2183: int i, rc = 0;
! 2184:
! 2185: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 2186:
! 2187: /*
! 2188: * Allocate DMA memory for the status block, map the memory into DMA
! 2189: * space, and fetch the physical address of the block.
! 2190: */
! 2191: if (bus_dmamap_create(sc->bnx_dmatag, BNX_STATUS_BLK_SZ, 1,
! 2192: BNX_STATUS_BLK_SZ, 0, BUS_DMA_NOWAIT, &sc->status_map)) {
! 2193: printf(": Could not create status block DMA map!\n");
! 2194: rc = ENOMEM;
! 2195: goto bnx_dma_alloc_exit;
! 2196: }
! 2197:
! 2198: if (bus_dmamem_alloc(sc->bnx_dmatag, BNX_STATUS_BLK_SZ,
! 2199: BNX_DMA_ALIGN, BNX_DMA_BOUNDARY, &sc->status_seg, 1,
! 2200: &sc->status_rseg, BUS_DMA_NOWAIT)) {
! 2201: printf(": Could not allocate status block DMA memory!\n");
! 2202: rc = ENOMEM;
! 2203: goto bnx_dma_alloc_exit;
! 2204: }
! 2205:
! 2206: if (bus_dmamem_map(sc->bnx_dmatag, &sc->status_seg, sc->status_rseg,
! 2207: BNX_STATUS_BLK_SZ, (caddr_t *)&sc->status_block, BUS_DMA_NOWAIT)) {
! 2208: printf(": Could not map status block DMA memory!\n");
! 2209: rc = ENOMEM;
! 2210: goto bnx_dma_alloc_exit;
! 2211: }
! 2212:
! 2213: if (bus_dmamap_load(sc->bnx_dmatag, sc->status_map,
! 2214: sc->status_block, BNX_STATUS_BLK_SZ, NULL, BUS_DMA_NOWAIT)) {
! 2215: printf(": Could not load status block DMA memory!\n");
! 2216: rc = ENOMEM;
! 2217: goto bnx_dma_alloc_exit;
! 2218: }
! 2219:
! 2220: sc->status_block_paddr = sc->status_map->dm_segs[0].ds_addr;
! 2221: bzero(sc->status_block, BNX_STATUS_BLK_SZ);
! 2222:
! 2223: /* DRC - Fix for 64 bit addresses. */
! 2224: DBPRINT(sc, BNX_INFO, "status_block_paddr = 0x%08X\n",
! 2225: (u_int32_t) sc->status_block_paddr);
! 2226:
! 2227: /*
! 2228: * Allocate DMA memory for the statistics block, map the memory into
! 2229: * DMA space, and fetch the physical address of the block.
! 2230: */
! 2231: if (bus_dmamap_create(sc->bnx_dmatag, BNX_STATS_BLK_SZ, 1,
! 2232: BNX_STATS_BLK_SZ, 0, BUS_DMA_NOWAIT, &sc->stats_map)) {
! 2233: printf(": Could not create stats block DMA map!\n");
! 2234: rc = ENOMEM;
! 2235: goto bnx_dma_alloc_exit;
! 2236: }
! 2237:
! 2238: if (bus_dmamem_alloc(sc->bnx_dmatag, BNX_STATS_BLK_SZ,
! 2239: BNX_DMA_ALIGN, BNX_DMA_BOUNDARY, &sc->stats_seg, 1,
! 2240: &sc->stats_rseg, BUS_DMA_NOWAIT)) {
! 2241: printf(": Could not allocate stats block DMA memory!\n");
! 2242: rc = ENOMEM;
! 2243: goto bnx_dma_alloc_exit;
! 2244: }
! 2245:
! 2246: if (bus_dmamem_map(sc->bnx_dmatag, &sc->stats_seg, sc->stats_rseg,
! 2247: BNX_STATS_BLK_SZ, (caddr_t *)&sc->stats_block, BUS_DMA_NOWAIT)) {
! 2248: printf(": Could not map stats block DMA memory!\n");
! 2249: rc = ENOMEM;
! 2250: goto bnx_dma_alloc_exit;
! 2251: }
! 2252:
! 2253: if (bus_dmamap_load(sc->bnx_dmatag, sc->stats_map,
! 2254: sc->stats_block, BNX_STATS_BLK_SZ, NULL, BUS_DMA_NOWAIT)) {
! 2255: printf(": Could not load status block DMA memory!\n");
! 2256: rc = ENOMEM;
! 2257: goto bnx_dma_alloc_exit;
! 2258: }
! 2259:
! 2260: sc->stats_block_paddr = sc->stats_map->dm_segs[0].ds_addr;
! 2261: bzero(sc->stats_block, BNX_STATS_BLK_SZ);
! 2262:
! 2263: /* DRC - Fix for 64 bit address. */
! 2264: DBPRINT(sc,BNX_INFO, "stats_block_paddr = 0x%08X\n",
! 2265: (u_int32_t) sc->stats_block_paddr);
! 2266:
! 2267: /*
! 2268: * Allocate DMA memory for the TX buffer descriptor chain,
! 2269: * and fetch the physical address of the block.
! 2270: */
! 2271: for (i = 0; i < TX_PAGES; i++) {
! 2272: if (bus_dmamap_create(sc->bnx_dmatag, BNX_TX_CHAIN_PAGE_SZ, 1,
! 2273: BNX_TX_CHAIN_PAGE_SZ, 0, BUS_DMA_NOWAIT,
! 2274: &sc->tx_bd_chain_map[i])) {
! 2275: printf(": Could not create Tx desc %d DMA map!\n", i);
! 2276: rc = ENOMEM;
! 2277: goto bnx_dma_alloc_exit;
! 2278: }
! 2279:
! 2280: if (bus_dmamem_alloc(sc->bnx_dmatag, BNX_TX_CHAIN_PAGE_SZ,
! 2281: BCM_PAGE_SIZE, BNX_DMA_BOUNDARY, &sc->tx_bd_chain_seg[i], 1,
! 2282: &sc->tx_bd_chain_rseg[i], BUS_DMA_NOWAIT)) {
! 2283: printf(": Could not allocate TX desc %d DMA memory!\n",
! 2284: i);
! 2285: rc = ENOMEM;
! 2286: goto bnx_dma_alloc_exit;
! 2287: }
! 2288:
! 2289: if (bus_dmamem_map(sc->bnx_dmatag, &sc->tx_bd_chain_seg[i],
! 2290: sc->tx_bd_chain_rseg[i], BNX_TX_CHAIN_PAGE_SZ,
! 2291: (caddr_t *)&sc->tx_bd_chain[i], BUS_DMA_NOWAIT)) {
! 2292: printf(": Could not map TX desc %d DMA memory!\n", i);
! 2293: rc = ENOMEM;
! 2294: goto bnx_dma_alloc_exit;
! 2295: }
! 2296:
! 2297: if (bus_dmamap_load(sc->bnx_dmatag, sc->tx_bd_chain_map[i],
! 2298: (caddr_t)sc->tx_bd_chain[i], BNX_TX_CHAIN_PAGE_SZ, NULL,
! 2299: BUS_DMA_NOWAIT)) {
! 2300: printf(": Could not load TX desc %d DMA memory!\n", i);
! 2301: rc = ENOMEM;
! 2302: goto bnx_dma_alloc_exit;
! 2303: }
! 2304:
! 2305: sc->tx_bd_chain_paddr[i] =
! 2306: sc->tx_bd_chain_map[i]->dm_segs[0].ds_addr;
! 2307:
! 2308: /* DRC - Fix for 64 bit systems. */
! 2309: DBPRINT(sc, BNX_INFO, "tx_bd_chain_paddr[%d] = 0x%08X\n",
! 2310: i, (u_int32_t) sc->tx_bd_chain_paddr[i]);
! 2311: }
! 2312:
! 2313: /*
! 2314: * Create DMA maps for the TX buffer mbufs.
! 2315: */
! 2316: for (i = 0; i < TOTAL_TX_BD; i++) {
! 2317: if (bus_dmamap_create(sc->bnx_dmatag,
! 2318: MCLBYTES * BNX_MAX_SEGMENTS,
! 2319: USABLE_TX_BD - BNX_TX_SLACK_SPACE,
! 2320: MCLBYTES, 0, BUS_DMA_NOWAIT,
! 2321: &sc->tx_mbuf_map[i])) {
! 2322: printf(": Could not create Tx mbuf %d DMA map!\n", i);
! 2323: rc = ENOMEM;
! 2324: goto bnx_dma_alloc_exit;
! 2325: }
! 2326: }
! 2327:
! 2328: /*
! 2329: * Allocate DMA memory for the Rx buffer descriptor chain,
! 2330: * and fetch the physical address of the block.
! 2331: */
! 2332: for (i = 0; i < RX_PAGES; i++) {
! 2333: if (bus_dmamap_create(sc->bnx_dmatag, BNX_RX_CHAIN_PAGE_SZ, 1,
! 2334: BNX_RX_CHAIN_PAGE_SZ, 0, BUS_DMA_NOWAIT,
! 2335: &sc->rx_bd_chain_map[i])) {
! 2336: printf(": Could not create Rx desc %d DMA map!\n", i);
! 2337: rc = ENOMEM;
! 2338: goto bnx_dma_alloc_exit;
! 2339: }
! 2340:
! 2341: if (bus_dmamem_alloc(sc->bnx_dmatag, BNX_RX_CHAIN_PAGE_SZ,
! 2342: BCM_PAGE_SIZE, BNX_DMA_BOUNDARY, &sc->rx_bd_chain_seg[i], 1,
! 2343: &sc->rx_bd_chain_rseg[i], BUS_DMA_NOWAIT)) {
! 2344: printf(": Could not allocate Rx desc %d DMA memory!\n",
! 2345: i);
! 2346: rc = ENOMEM;
! 2347: goto bnx_dma_alloc_exit;
! 2348: }
! 2349:
! 2350: if (bus_dmamem_map(sc->bnx_dmatag, &sc->rx_bd_chain_seg[i],
! 2351: sc->rx_bd_chain_rseg[i], BNX_RX_CHAIN_PAGE_SZ,
! 2352: (caddr_t *)&sc->rx_bd_chain[i], BUS_DMA_NOWAIT)) {
! 2353: printf(": Could not map Rx desc %d DMA memory!\n", i);
! 2354: rc = ENOMEM;
! 2355: goto bnx_dma_alloc_exit;
! 2356: }
! 2357:
! 2358: if (bus_dmamap_load(sc->bnx_dmatag, sc->rx_bd_chain_map[i],
! 2359: (caddr_t)sc->rx_bd_chain[i], BNX_RX_CHAIN_PAGE_SZ, NULL,
! 2360: BUS_DMA_NOWAIT)) {
! 2361: printf(": Could not load Rx desc %d DMA memory!\n", i);
! 2362: rc = ENOMEM;
! 2363: goto bnx_dma_alloc_exit;
! 2364: }
! 2365:
! 2366: bzero(sc->rx_bd_chain[i], BNX_RX_CHAIN_PAGE_SZ);
! 2367: sc->rx_bd_chain_paddr[i] =
! 2368: sc->rx_bd_chain_map[i]->dm_segs[0].ds_addr;
! 2369:
! 2370: /* DRC - Fix for 64 bit systems. */
! 2371: DBPRINT(sc, BNX_INFO, "rx_bd_chain_paddr[%d] = 0x%08X\n",
! 2372: i, (u_int32_t) sc->rx_bd_chain_paddr[i]);
! 2373: }
! 2374:
! 2375: /*
! 2376: * Create DMA maps for the Rx buffer mbufs.
! 2377: */
! 2378: for (i = 0; i < TOTAL_RX_BD; i++) {
! 2379: if (bus_dmamap_create(sc->bnx_dmatag, BNX_MAX_MRU,
! 2380: BNX_MAX_SEGMENTS, BNX_MAX_MRU, 0, BUS_DMA_NOWAIT,
! 2381: &sc->rx_mbuf_map[i])) {
! 2382: printf(": Could not create Rx mbuf %d DMA map!\n", i);
! 2383: rc = ENOMEM;
! 2384: goto bnx_dma_alloc_exit;
! 2385: }
! 2386: }
! 2387:
! 2388: bnx_dma_alloc_exit:
! 2389: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 2390:
! 2391: return(rc);
! 2392: }
! 2393:
! 2394: /****************************************************************************/
! 2395: /* Release all resources used by the driver. */
! 2396: /* */
! 2397: /* Releases all resources acquired by the driver including interrupts, */
! 2398: /* interrupt handler, interfaces, mutexes, and DMA memory. */
! 2399: /* */
! 2400: /* Returns: */
! 2401: /* Nothing. */
! 2402: /****************************************************************************/
! 2403: void
! 2404: bnx_release_resources(struct bnx_softc *sc)
! 2405: {
! 2406: struct pci_attach_args *pa = &(sc->bnx_pa);
! 2407:
! 2408: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 2409:
! 2410: bnx_dma_free(sc);
! 2411:
! 2412: if (sc->bnx_intrhand != NULL)
! 2413: pci_intr_disestablish(pa->pa_pc, sc->bnx_intrhand);
! 2414:
! 2415: if (sc->bnx_size)
! 2416: bus_space_unmap(sc->bnx_btag, sc->bnx_bhandle, sc->bnx_size);
! 2417:
! 2418: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 2419: }
! 2420:
! 2421: /****************************************************************************/
! 2422: /* Firmware synchronization. */
! 2423: /* */
! 2424: /* Before performing certain events such as a chip reset, synchronize with */
! 2425: /* the firmware first. */
! 2426: /* */
! 2427: /* Returns: */
! 2428: /* 0 for success, positive value for failure. */
! 2429: /****************************************************************************/
! 2430: int
! 2431: bnx_fw_sync(struct bnx_softc *sc, u_int32_t msg_data)
! 2432: {
! 2433: int i, rc = 0;
! 2434: u_int32_t val;
! 2435:
! 2436: /* Don't waste any time if we've timed out before. */
! 2437: if (sc->bnx_fw_timed_out) {
! 2438: rc = EBUSY;
! 2439: goto bnx_fw_sync_exit;
! 2440: }
! 2441:
! 2442: /* Increment the message sequence number. */
! 2443: sc->bnx_fw_wr_seq++;
! 2444: msg_data |= sc->bnx_fw_wr_seq;
! 2445:
! 2446: DBPRINT(sc, BNX_VERBOSE, "bnx_fw_sync(): msg_data = 0x%08X\n",
! 2447: msg_data);
! 2448:
! 2449: /* Send the message to the bootcode driver mailbox. */
! 2450: REG_WR_IND(sc, sc->bnx_shmem_base + BNX_DRV_MB, msg_data);
! 2451:
! 2452: /* Wait for the bootcode to acknowledge the message. */
! 2453: for (i = 0; i < FW_ACK_TIME_OUT_MS; i++) {
! 2454: /* Check for a response in the bootcode firmware mailbox. */
! 2455: val = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_FW_MB);
! 2456: if ((val & BNX_FW_MSG_ACK) == (msg_data & BNX_DRV_MSG_SEQ))
! 2457: break;
! 2458: DELAY(1000);
! 2459: }
! 2460:
! 2461: /* If we've timed out, tell the bootcode that we've stopped waiting. */
! 2462: if (((val & BNX_FW_MSG_ACK) != (msg_data & BNX_DRV_MSG_SEQ)) &&
! 2463: ((msg_data & BNX_DRV_MSG_DATA) != BNX_DRV_MSG_DATA_WAIT0)) {
! 2464: BNX_PRINTF(sc, "%s(%d): Firmware synchronization timeout! "
! 2465: "msg_data = 0x%08X\n", __FILE__, __LINE__, msg_data);
! 2466:
! 2467: msg_data &= ~BNX_DRV_MSG_CODE;
! 2468: msg_data |= BNX_DRV_MSG_CODE_FW_TIMEOUT;
! 2469:
! 2470: REG_WR_IND(sc, sc->bnx_shmem_base + BNX_DRV_MB, msg_data);
! 2471:
! 2472: sc->bnx_fw_timed_out = 1;
! 2473: rc = EBUSY;
! 2474: }
! 2475:
! 2476: bnx_fw_sync_exit:
! 2477: return (rc);
! 2478: }
! 2479:
! 2480: /****************************************************************************/
! 2481: /* Load Receive Virtual 2 Physical (RV2P) processor firmware. */
! 2482: /* */
! 2483: /* Returns: */
! 2484: /* Nothing. */
! 2485: /****************************************************************************/
! 2486: void
! 2487: bnx_load_rv2p_fw(struct bnx_softc *sc, u_int32_t *rv2p_code,
! 2488: u_int32_t rv2p_code_len, u_int32_t rv2p_proc)
! 2489: {
! 2490: int i;
! 2491: u_int32_t val;
! 2492:
! 2493: for (i = 0; i < rv2p_code_len; i += 8) {
! 2494: REG_WR(sc, BNX_RV2P_INSTR_HIGH, *rv2p_code);
! 2495: rv2p_code++;
! 2496: REG_WR(sc, BNX_RV2P_INSTR_LOW, *rv2p_code);
! 2497: rv2p_code++;
! 2498:
! 2499: if (rv2p_proc == RV2P_PROC1) {
! 2500: val = (i / 8) | BNX_RV2P_PROC1_ADDR_CMD_RDWR;
! 2501: REG_WR(sc, BNX_RV2P_PROC1_ADDR_CMD, val);
! 2502: }
! 2503: else {
! 2504: val = (i / 8) | BNX_RV2P_PROC2_ADDR_CMD_RDWR;
! 2505: REG_WR(sc, BNX_RV2P_PROC2_ADDR_CMD, val);
! 2506: }
! 2507: }
! 2508:
! 2509: /* Reset the processor, un-stall is done later. */
! 2510: if (rv2p_proc == RV2P_PROC1)
! 2511: REG_WR(sc, BNX_RV2P_COMMAND, BNX_RV2P_COMMAND_PROC1_RESET);
! 2512: else
! 2513: REG_WR(sc, BNX_RV2P_COMMAND, BNX_RV2P_COMMAND_PROC2_RESET);
! 2514: }
! 2515:
! 2516: /****************************************************************************/
! 2517: /* Load RISC processor firmware. */
! 2518: /* */
! 2519: /* Loads firmware from the file if_bnxfw.h into the scratchpad memory */
! 2520: /* associated with a particular processor. */
! 2521: /* */
! 2522: /* Returns: */
! 2523: /* Nothing. */
! 2524: /****************************************************************************/
! 2525: void
! 2526: bnx_load_cpu_fw(struct bnx_softc *sc, struct cpu_reg *cpu_reg,
! 2527: struct fw_info *fw)
! 2528: {
! 2529: u_int32_t offset;
! 2530: u_int32_t val;
! 2531:
! 2532: /* Halt the CPU. */
! 2533: val = REG_RD_IND(sc, cpu_reg->mode);
! 2534: val |= cpu_reg->mode_value_halt;
! 2535: REG_WR_IND(sc, cpu_reg->mode, val);
! 2536: REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
! 2537:
! 2538: /* Load the Text area. */
! 2539: offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
! 2540: if (fw->text) {
! 2541: int j;
! 2542:
! 2543: for (j = 0; j < (fw->text_len / 4); j++, offset += 4)
! 2544: REG_WR_IND(sc, offset, fw->text[j]);
! 2545: }
! 2546:
! 2547: /* Load the Data area. */
! 2548: offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
! 2549: if (fw->data) {
! 2550: int j;
! 2551:
! 2552: for (j = 0; j < (fw->data_len / 4); j++, offset += 4)
! 2553: REG_WR_IND(sc, offset, fw->data[j]);
! 2554: }
! 2555:
! 2556: /* Load the SBSS area. */
! 2557: offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
! 2558: if (fw->sbss) {
! 2559: int j;
! 2560:
! 2561: for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4)
! 2562: REG_WR_IND(sc, offset, fw->sbss[j]);
! 2563: }
! 2564:
! 2565: /* Load the BSS area. */
! 2566: offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
! 2567: if (fw->bss) {
! 2568: int j;
! 2569:
! 2570: for (j = 0; j < (fw->bss_len/4); j++, offset += 4)
! 2571: REG_WR_IND(sc, offset, fw->bss[j]);
! 2572: }
! 2573:
! 2574: /* Load the Read-Only area. */
! 2575: offset = cpu_reg->spad_base +
! 2576: (fw->rodata_addr - cpu_reg->mips_view_base);
! 2577: if (fw->rodata) {
! 2578: int j;
! 2579:
! 2580: for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4)
! 2581: REG_WR_IND(sc, offset, fw->rodata[j]);
! 2582: }
! 2583:
! 2584: /* Clear the pre-fetch instruction. */
! 2585: REG_WR_IND(sc, cpu_reg->inst, 0);
! 2586: REG_WR_IND(sc, cpu_reg->pc, fw->start_addr);
! 2587:
! 2588: /* Start the CPU. */
! 2589: val = REG_RD_IND(sc, cpu_reg->mode);
! 2590: val &= ~cpu_reg->mode_value_halt;
! 2591: REG_WR_IND(sc, cpu_reg->state, cpu_reg->state_value_clear);
! 2592: REG_WR_IND(sc, cpu_reg->mode, val);
! 2593: }
! 2594:
! 2595: /****************************************************************************/
! 2596: /* Initialize the RV2P, RX, TX, TPAT, and COM CPUs. */
! 2597: /* */
! 2598: /* Loads the firmware for each CPU and starts the CPU. */
! 2599: /* */
! 2600: /* Returns: */
! 2601: /* Nothing. */
! 2602: /****************************************************************************/
! 2603: void
! 2604: bnx_init_cpus(struct bnx_softc *sc)
! 2605: {
! 2606: struct cpu_reg cpu_reg;
! 2607: struct fw_info fw;
! 2608:
! 2609: /* Initialize the RV2P processor. */
! 2610: bnx_load_rv2p_fw(sc, bnx_rv2p_proc1, bnx_rv2p_proc1len,
! 2611: RV2P_PROC1);
! 2612: bnx_load_rv2p_fw(sc, bnx_rv2p_proc2, bnx_rv2p_proc2len,
! 2613: RV2P_PROC2);
! 2614:
! 2615: /* Initialize the RX Processor. */
! 2616: cpu_reg.mode = BNX_RXP_CPU_MODE;
! 2617: cpu_reg.mode_value_halt = BNX_RXP_CPU_MODE_SOFT_HALT;
! 2618: cpu_reg.mode_value_sstep = BNX_RXP_CPU_MODE_STEP_ENA;
! 2619: cpu_reg.state = BNX_RXP_CPU_STATE;
! 2620: cpu_reg.state_value_clear = 0xffffff;
! 2621: cpu_reg.gpr0 = BNX_RXP_CPU_REG_FILE;
! 2622: cpu_reg.evmask = BNX_RXP_CPU_EVENT_MASK;
! 2623: cpu_reg.pc = BNX_RXP_CPU_PROGRAM_COUNTER;
! 2624: cpu_reg.inst = BNX_RXP_CPU_INSTRUCTION;
! 2625: cpu_reg.bp = BNX_RXP_CPU_HW_BREAKPOINT;
! 2626: cpu_reg.spad_base = BNX_RXP_SCRATCH;
! 2627: cpu_reg.mips_view_base = 0x8000000;
! 2628:
! 2629: fw.ver_major = bnx_RXP_b06FwReleaseMajor;
! 2630: fw.ver_minor = bnx_RXP_b06FwReleaseMinor;
! 2631: fw.ver_fix = bnx_RXP_b06FwReleaseFix;
! 2632: fw.start_addr = bnx_RXP_b06FwStartAddr;
! 2633:
! 2634: fw.text_addr = bnx_RXP_b06FwTextAddr;
! 2635: fw.text_len = bnx_RXP_b06FwTextLen;
! 2636: fw.text_index = 0;
! 2637: fw.text = bnx_RXP_b06FwText;
! 2638:
! 2639: fw.data_addr = bnx_RXP_b06FwDataAddr;
! 2640: fw.data_len = bnx_RXP_b06FwDataLen;
! 2641: fw.data_index = 0;
! 2642: fw.data = bnx_RXP_b06FwData;
! 2643:
! 2644: fw.sbss_addr = bnx_RXP_b06FwSbssAddr;
! 2645: fw.sbss_len = bnx_RXP_b06FwSbssLen;
! 2646: fw.sbss_index = 0;
! 2647: fw.sbss = bnx_RXP_b06FwSbss;
! 2648:
! 2649: fw.bss_addr = bnx_RXP_b06FwBssAddr;
! 2650: fw.bss_len = bnx_RXP_b06FwBssLen;
! 2651: fw.bss_index = 0;
! 2652: fw.bss = bnx_RXP_b06FwBss;
! 2653:
! 2654: fw.rodata_addr = bnx_RXP_b06FwRodataAddr;
! 2655: fw.rodata_len = bnx_RXP_b06FwRodataLen;
! 2656: fw.rodata_index = 0;
! 2657: fw.rodata = bnx_RXP_b06FwRodata;
! 2658:
! 2659: DBPRINT(sc, BNX_INFO_RESET, "Loading RX firmware.\n");
! 2660: bnx_load_cpu_fw(sc, &cpu_reg, &fw);
! 2661:
! 2662: /* Initialize the TX Processor. */
! 2663: cpu_reg.mode = BNX_TXP_CPU_MODE;
! 2664: cpu_reg.mode_value_halt = BNX_TXP_CPU_MODE_SOFT_HALT;
! 2665: cpu_reg.mode_value_sstep = BNX_TXP_CPU_MODE_STEP_ENA;
! 2666: cpu_reg.state = BNX_TXP_CPU_STATE;
! 2667: cpu_reg.state_value_clear = 0xffffff;
! 2668: cpu_reg.gpr0 = BNX_TXP_CPU_REG_FILE;
! 2669: cpu_reg.evmask = BNX_TXP_CPU_EVENT_MASK;
! 2670: cpu_reg.pc = BNX_TXP_CPU_PROGRAM_COUNTER;
! 2671: cpu_reg.inst = BNX_TXP_CPU_INSTRUCTION;
! 2672: cpu_reg.bp = BNX_TXP_CPU_HW_BREAKPOINT;
! 2673: cpu_reg.spad_base = BNX_TXP_SCRATCH;
! 2674: cpu_reg.mips_view_base = 0x8000000;
! 2675:
! 2676: fw.ver_major = bnx_TXP_b06FwReleaseMajor;
! 2677: fw.ver_minor = bnx_TXP_b06FwReleaseMinor;
! 2678: fw.ver_fix = bnx_TXP_b06FwReleaseFix;
! 2679: fw.start_addr = bnx_TXP_b06FwStartAddr;
! 2680:
! 2681: fw.text_addr = bnx_TXP_b06FwTextAddr;
! 2682: fw.text_len = bnx_TXP_b06FwTextLen;
! 2683: fw.text_index = 0;
! 2684: fw.text = bnx_TXP_b06FwText;
! 2685:
! 2686: fw.data_addr = bnx_TXP_b06FwDataAddr;
! 2687: fw.data_len = bnx_TXP_b06FwDataLen;
! 2688: fw.data_index = 0;
! 2689: fw.data = bnx_TXP_b06FwData;
! 2690:
! 2691: fw.sbss_addr = bnx_TXP_b06FwSbssAddr;
! 2692: fw.sbss_len = bnx_TXP_b06FwSbssLen;
! 2693: fw.sbss_index = 0;
! 2694: fw.sbss = bnx_TXP_b06FwSbss;
! 2695:
! 2696: fw.bss_addr = bnx_TXP_b06FwBssAddr;
! 2697: fw.bss_len = bnx_TXP_b06FwBssLen;
! 2698: fw.bss_index = 0;
! 2699: fw.bss = bnx_TXP_b06FwBss;
! 2700:
! 2701: fw.rodata_addr = bnx_TXP_b06FwRodataAddr;
! 2702: fw.rodata_len = bnx_TXP_b06FwRodataLen;
! 2703: fw.rodata_index = 0;
! 2704: fw.rodata = bnx_TXP_b06FwRodata;
! 2705:
! 2706: DBPRINT(sc, BNX_INFO_RESET, "Loading TX firmware.\n");
! 2707: bnx_load_cpu_fw(sc, &cpu_reg, &fw);
! 2708:
! 2709: /* Initialize the TX Patch-up Processor. */
! 2710: cpu_reg.mode = BNX_TPAT_CPU_MODE;
! 2711: cpu_reg.mode_value_halt = BNX_TPAT_CPU_MODE_SOFT_HALT;
! 2712: cpu_reg.mode_value_sstep = BNX_TPAT_CPU_MODE_STEP_ENA;
! 2713: cpu_reg.state = BNX_TPAT_CPU_STATE;
! 2714: cpu_reg.state_value_clear = 0xffffff;
! 2715: cpu_reg.gpr0 = BNX_TPAT_CPU_REG_FILE;
! 2716: cpu_reg.evmask = BNX_TPAT_CPU_EVENT_MASK;
! 2717: cpu_reg.pc = BNX_TPAT_CPU_PROGRAM_COUNTER;
! 2718: cpu_reg.inst = BNX_TPAT_CPU_INSTRUCTION;
! 2719: cpu_reg.bp = BNX_TPAT_CPU_HW_BREAKPOINT;
! 2720: cpu_reg.spad_base = BNX_TPAT_SCRATCH;
! 2721: cpu_reg.mips_view_base = 0x8000000;
! 2722:
! 2723: fw.ver_major = bnx_TPAT_b06FwReleaseMajor;
! 2724: fw.ver_minor = bnx_TPAT_b06FwReleaseMinor;
! 2725: fw.ver_fix = bnx_TPAT_b06FwReleaseFix;
! 2726: fw.start_addr = bnx_TPAT_b06FwStartAddr;
! 2727:
! 2728: fw.text_addr = bnx_TPAT_b06FwTextAddr;
! 2729: fw.text_len = bnx_TPAT_b06FwTextLen;
! 2730: fw.text_index = 0;
! 2731: fw.text = bnx_TPAT_b06FwText;
! 2732:
! 2733: fw.data_addr = bnx_TPAT_b06FwDataAddr;
! 2734: fw.data_len = bnx_TPAT_b06FwDataLen;
! 2735: fw.data_index = 0;
! 2736: fw.data = bnx_TPAT_b06FwData;
! 2737:
! 2738: fw.sbss_addr = bnx_TPAT_b06FwSbssAddr;
! 2739: fw.sbss_len = bnx_TPAT_b06FwSbssLen;
! 2740: fw.sbss_index = 0;
! 2741: fw.sbss = bnx_TPAT_b06FwSbss;
! 2742:
! 2743: fw.bss_addr = bnx_TPAT_b06FwBssAddr;
! 2744: fw.bss_len = bnx_TPAT_b06FwBssLen;
! 2745: fw.bss_index = 0;
! 2746: fw.bss = bnx_TPAT_b06FwBss;
! 2747:
! 2748: fw.rodata_addr = bnx_TPAT_b06FwRodataAddr;
! 2749: fw.rodata_len = bnx_TPAT_b06FwRodataLen;
! 2750: fw.rodata_index = 0;
! 2751: fw.rodata = bnx_TPAT_b06FwRodata;
! 2752:
! 2753: DBPRINT(sc, BNX_INFO_RESET, "Loading TPAT firmware.\n");
! 2754: bnx_load_cpu_fw(sc, &cpu_reg, &fw);
! 2755:
! 2756: /* Initialize the Completion Processor. */
! 2757: cpu_reg.mode = BNX_COM_CPU_MODE;
! 2758: cpu_reg.mode_value_halt = BNX_COM_CPU_MODE_SOFT_HALT;
! 2759: cpu_reg.mode_value_sstep = BNX_COM_CPU_MODE_STEP_ENA;
! 2760: cpu_reg.state = BNX_COM_CPU_STATE;
! 2761: cpu_reg.state_value_clear = 0xffffff;
! 2762: cpu_reg.gpr0 = BNX_COM_CPU_REG_FILE;
! 2763: cpu_reg.evmask = BNX_COM_CPU_EVENT_MASK;
! 2764: cpu_reg.pc = BNX_COM_CPU_PROGRAM_COUNTER;
! 2765: cpu_reg.inst = BNX_COM_CPU_INSTRUCTION;
! 2766: cpu_reg.bp = BNX_COM_CPU_HW_BREAKPOINT;
! 2767: cpu_reg.spad_base = BNX_COM_SCRATCH;
! 2768: cpu_reg.mips_view_base = 0x8000000;
! 2769:
! 2770: fw.ver_major = bnx_COM_b06FwReleaseMajor;
! 2771: fw.ver_minor = bnx_COM_b06FwReleaseMinor;
! 2772: fw.ver_fix = bnx_COM_b06FwReleaseFix;
! 2773: fw.start_addr = bnx_COM_b06FwStartAddr;
! 2774:
! 2775: fw.text_addr = bnx_COM_b06FwTextAddr;
! 2776: fw.text_len = bnx_COM_b06FwTextLen;
! 2777: fw.text_index = 0;
! 2778: fw.text = bnx_COM_b06FwText;
! 2779:
! 2780: fw.data_addr = bnx_COM_b06FwDataAddr;
! 2781: fw.data_len = bnx_COM_b06FwDataLen;
! 2782: fw.data_index = 0;
! 2783: fw.data = bnx_COM_b06FwData;
! 2784:
! 2785: fw.sbss_addr = bnx_COM_b06FwSbssAddr;
! 2786: fw.sbss_len = bnx_COM_b06FwSbssLen;
! 2787: fw.sbss_index = 0;
! 2788: fw.sbss = bnx_COM_b06FwSbss;
! 2789:
! 2790: fw.bss_addr = bnx_COM_b06FwBssAddr;
! 2791: fw.bss_len = bnx_COM_b06FwBssLen;
! 2792: fw.bss_index = 0;
! 2793: fw.bss = bnx_COM_b06FwBss;
! 2794:
! 2795: fw.rodata_addr = bnx_COM_b06FwRodataAddr;
! 2796: fw.rodata_len = bnx_COM_b06FwRodataLen;
! 2797: fw.rodata_index = 0;
! 2798: fw.rodata = bnx_COM_b06FwRodata;
! 2799:
! 2800: DBPRINT(sc, BNX_INFO_RESET, "Loading COM firmware.\n");
! 2801: bnx_load_cpu_fw(sc, &cpu_reg, &fw);
! 2802: }
! 2803:
! 2804: /****************************************************************************/
! 2805: /* Initialize context memory. */
! 2806: /* */
! 2807: /* Clears the memory associated with each Context ID (CID). */
! 2808: /* */
! 2809: /* Returns: */
! 2810: /* Nothing. */
! 2811: /****************************************************************************/
! 2812: void
! 2813: bnx_init_context(struct bnx_softc *sc)
! 2814: {
! 2815: u_int32_t vcid;
! 2816:
! 2817: vcid = 96;
! 2818: while (vcid) {
! 2819: u_int32_t vcid_addr, pcid_addr, offset;
! 2820:
! 2821: vcid--;
! 2822:
! 2823: vcid_addr = GET_CID_ADDR(vcid);
! 2824: pcid_addr = vcid_addr;
! 2825:
! 2826: REG_WR(sc, BNX_CTX_VIRT_ADDR, 0x00);
! 2827: REG_WR(sc, BNX_CTX_PAGE_TBL, pcid_addr);
! 2828:
! 2829: /* Zero out the context. */
! 2830: for (offset = 0; offset < PHY_CTX_SIZE; offset += 4)
! 2831: CTX_WR(sc, 0x00, offset, 0);
! 2832:
! 2833: REG_WR(sc, BNX_CTX_VIRT_ADDR, vcid_addr);
! 2834: REG_WR(sc, BNX_CTX_PAGE_TBL, pcid_addr);
! 2835: }
! 2836: }
! 2837:
! 2838: /****************************************************************************/
! 2839: /* Fetch the permanent MAC address of the controller. */
! 2840: /* */
! 2841: /* Returns: */
! 2842: /* Nothing. */
! 2843: /****************************************************************************/
! 2844: void
! 2845: bnx_get_mac_addr(struct bnx_softc *sc)
! 2846: {
! 2847: u_int32_t mac_lo = 0, mac_hi = 0;
! 2848:
! 2849: /*
! 2850: * The NetXtreme II bootcode populates various NIC
! 2851: * power-on and runtime configuration items in a
! 2852: * shared memory area. The factory configured MAC
! 2853: * address is available from both NVRAM and the
! 2854: * shared memory area so we'll read the value from
! 2855: * shared memory for speed.
! 2856: */
! 2857:
! 2858: mac_hi = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_PORT_HW_CFG_MAC_UPPER);
! 2859: mac_lo = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_PORT_HW_CFG_MAC_LOWER);
! 2860:
! 2861: if ((mac_lo == 0) && (mac_hi == 0)) {
! 2862: BNX_PRINTF(sc, "%s(%d): Invalid Ethernet address!\n",
! 2863: __FILE__, __LINE__);
! 2864: } else {
! 2865: sc->eaddr[0] = (u_char)(mac_hi >> 8);
! 2866: sc->eaddr[1] = (u_char)(mac_hi >> 0);
! 2867: sc->eaddr[2] = (u_char)(mac_lo >> 24);
! 2868: sc->eaddr[3] = (u_char)(mac_lo >> 16);
! 2869: sc->eaddr[4] = (u_char)(mac_lo >> 8);
! 2870: sc->eaddr[5] = (u_char)(mac_lo >> 0);
! 2871: }
! 2872:
! 2873: DBPRINT(sc, BNX_INFO, "Permanent Ethernet address = "
! 2874: "%6D\n", sc->eaddr, ":");
! 2875: }
! 2876:
! 2877: /****************************************************************************/
! 2878: /* Program the MAC address. */
! 2879: /* */
! 2880: /* Returns: */
! 2881: /* Nothing. */
! 2882: /****************************************************************************/
! 2883: void
! 2884: bnx_set_mac_addr(struct bnx_softc *sc)
! 2885: {
! 2886: u_int32_t val;
! 2887: u_int8_t *mac_addr = sc->eaddr;
! 2888:
! 2889: DBPRINT(sc, BNX_INFO, "Setting Ethernet address = "
! 2890: "%6D\n", sc->eaddr, ":");
! 2891:
! 2892: val = (mac_addr[0] << 8) | mac_addr[1];
! 2893:
! 2894: REG_WR(sc, BNX_EMAC_MAC_MATCH0, val);
! 2895:
! 2896: val = (mac_addr[2] << 24) | (mac_addr[3] << 16) |
! 2897: (mac_addr[4] << 8) | mac_addr[5];
! 2898:
! 2899: REG_WR(sc, BNX_EMAC_MAC_MATCH1, val);
! 2900: }
! 2901:
! 2902: /****************************************************************************/
! 2903: /* Stop the controller. */
! 2904: /* */
! 2905: /* Returns: */
! 2906: /* Nothing. */
! 2907: /****************************************************************************/
! 2908: void
! 2909: bnx_stop(struct bnx_softc *sc)
! 2910: {
! 2911: struct ifnet *ifp = &sc->arpcom.ac_if;
! 2912: struct mii_data *mii = NULL;
! 2913:
! 2914: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 2915:
! 2916: mii = &sc->bnx_mii;
! 2917:
! 2918: timeout_del(&sc->bnx_timeout);
! 2919:
! 2920: ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
! 2921:
! 2922: /* Disable the transmit/receive blocks. */
! 2923: REG_WR(sc, BNX_MISC_ENABLE_CLR_BITS, 0x5ffffff);
! 2924: REG_RD(sc, BNX_MISC_ENABLE_CLR_BITS);
! 2925: DELAY(20);
! 2926:
! 2927: bnx_disable_intr(sc);
! 2928:
! 2929: /* Tell firmware that the driver is going away. */
! 2930: bnx_reset(sc, BNX_DRV_MSG_CODE_SUSPEND_NO_WOL);
! 2931:
! 2932: /* Free the RX lists. */
! 2933: bnx_free_rx_chain(sc);
! 2934:
! 2935: /* Free TX buffers. */
! 2936: bnx_free_tx_chain(sc);
! 2937:
! 2938: ifp->if_timer = 0;
! 2939:
! 2940: sc->bnx_link = 0;
! 2941:
! 2942: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 2943:
! 2944: bnx_mgmt_init(sc);
! 2945: }
! 2946:
! 2947: int
! 2948: bnx_reset(struct bnx_softc *sc, u_int32_t reset_code)
! 2949: {
! 2950: u_int32_t val;
! 2951: int i, rc = 0;
! 2952:
! 2953: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 2954:
! 2955: /* Wait for pending PCI transactions to complete. */
! 2956: REG_WR(sc, BNX_MISC_ENABLE_CLR_BITS,
! 2957: BNX_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
! 2958: BNX_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
! 2959: BNX_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
! 2960: BNX_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
! 2961: val = REG_RD(sc, BNX_MISC_ENABLE_CLR_BITS);
! 2962: DELAY(5);
! 2963:
! 2964: /* Assume bootcode is running. */
! 2965: sc->bnx_fw_timed_out = 0;
! 2966:
! 2967: /* Give the firmware a chance to prepare for the reset. */
! 2968: rc = bnx_fw_sync(sc, BNX_DRV_MSG_DATA_WAIT0 | reset_code);
! 2969: if (rc)
! 2970: goto bnx_reset_exit;
! 2971:
! 2972: /* Set a firmware reminder that this is a soft reset. */
! 2973: REG_WR_IND(sc, sc->bnx_shmem_base + BNX_DRV_RESET_SIGNATURE,
! 2974: BNX_DRV_RESET_SIGNATURE_MAGIC);
! 2975:
! 2976: /* Dummy read to force the chip to complete all current transactions. */
! 2977: val = REG_RD(sc, BNX_MISC_ID);
! 2978:
! 2979: /* Chip reset. */
! 2980: val = BNX_PCICFG_MISC_CONFIG_CORE_RST_REQ |
! 2981: BNX_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
! 2982: BNX_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
! 2983: REG_WR(sc, BNX_PCICFG_MISC_CONFIG, val);
! 2984:
! 2985: /* Allow up to 30us for reset to complete. */
! 2986: for (i = 0; i < 10; i++) {
! 2987: val = REG_RD(sc, BNX_PCICFG_MISC_CONFIG);
! 2988: if ((val & (BNX_PCICFG_MISC_CONFIG_CORE_RST_REQ |
! 2989: BNX_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0)
! 2990: break;
! 2991:
! 2992: DELAY(10);
! 2993: }
! 2994:
! 2995: /* Check that reset completed successfully. */
! 2996: if (val & (BNX_PCICFG_MISC_CONFIG_CORE_RST_REQ |
! 2997: BNX_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
! 2998: BNX_PRINTF(sc, "%s(%d): Reset failed!\n", __FILE__, __LINE__);
! 2999: rc = EBUSY;
! 3000: goto bnx_reset_exit;
! 3001: }
! 3002:
! 3003: /* Make sure byte swapping is properly configured. */
! 3004: val = REG_RD(sc, BNX_PCI_SWAP_DIAG0);
! 3005: if (val != 0x01020304) {
! 3006: BNX_PRINTF(sc, "%s(%d): Byte swap is incorrect!\n",
! 3007: __FILE__, __LINE__);
! 3008: rc = ENODEV;
! 3009: goto bnx_reset_exit;
! 3010: }
! 3011:
! 3012: /* Just completed a reset, assume that firmware is running again. */
! 3013: sc->bnx_fw_timed_out = 0;
! 3014:
! 3015: /* Wait for the firmware to finish its initialization. */
! 3016: rc = bnx_fw_sync(sc, BNX_DRV_MSG_DATA_WAIT1 | reset_code);
! 3017: if (rc)
! 3018: BNX_PRINTF(sc, "%s(%d): Firmware did not complete "
! 3019: "initialization!\n", __FILE__, __LINE__);
! 3020:
! 3021: bnx_reset_exit:
! 3022: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 3023:
! 3024: return (rc);
! 3025: }
! 3026:
! 3027: int
! 3028: bnx_chipinit(struct bnx_softc *sc)
! 3029: {
! 3030: struct pci_attach_args *pa = &(sc->bnx_pa);
! 3031: u_int32_t val;
! 3032: int rc = 0;
! 3033:
! 3034: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 3035:
! 3036: /* Make sure the interrupt is not active. */
! 3037: REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, BNX_PCICFG_INT_ACK_CMD_MASK_INT);
! 3038:
! 3039: /* Initialize DMA byte/word swapping, configure the number of DMA */
! 3040: /* channels and PCI clock compensation delay. */
! 3041: val = BNX_DMA_CONFIG_DATA_BYTE_SWAP |
! 3042: BNX_DMA_CONFIG_DATA_WORD_SWAP |
! 3043: #if BYTE_ORDER == BIG_ENDIAN
! 3044: BNX_DMA_CONFIG_CNTL_BYTE_SWAP |
! 3045: #endif
! 3046: BNX_DMA_CONFIG_CNTL_WORD_SWAP |
! 3047: DMA_READ_CHANS << 12 |
! 3048: DMA_WRITE_CHANS << 16;
! 3049:
! 3050: val |= (0x2 << 20) | BNX_DMA_CONFIG_CNTL_PCI_COMP_DLY;
! 3051:
! 3052: if ((sc->bnx_flags & BNX_PCIX_FLAG) && (sc->bus_speed_mhz == 133))
! 3053: val |= BNX_DMA_CONFIG_PCI_FAST_CLK_CMP;
! 3054:
! 3055: /*
! 3056: * This setting resolves a problem observed on certain Intel PCI
! 3057: * chipsets that cannot handle multiple outstanding DMA operations.
! 3058: * See errata E9_5706A1_65.
! 3059: */
! 3060: if ((BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5706) &&
! 3061: (BNX_CHIP_ID(sc) != BNX_CHIP_ID_5706_A0) &&
! 3062: !(sc->bnx_flags & BNX_PCIX_FLAG))
! 3063: val |= BNX_DMA_CONFIG_CNTL_PING_PONG_DMA;
! 3064:
! 3065: REG_WR(sc, BNX_DMA_CONFIG, val);
! 3066:
! 3067: /* Clear the PCI-X relaxed ordering bit. See errata E3_5708CA0_570. */
! 3068: if (sc->bnx_flags & BNX_PCIX_FLAG) {
! 3069: u_int16_t val;
! 3070:
! 3071: val = pci_conf_read(pa->pa_pc, pa->pa_tag, BNX_PCI_PCIX_CMD);
! 3072: pci_conf_write(pa->pa_pc, pa->pa_tag, BNX_PCI_PCIX_CMD,
! 3073: val & ~0x2);
! 3074: }
! 3075:
! 3076: /* Enable the RX_V2P and Context state machines before access. */
! 3077: REG_WR(sc, BNX_MISC_ENABLE_SET_BITS,
! 3078: BNX_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
! 3079: BNX_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
! 3080: BNX_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
! 3081:
! 3082: /* Initialize context mapping and zero out the quick contexts. */
! 3083: bnx_init_context(sc);
! 3084:
! 3085: /* Initialize the on-boards CPUs */
! 3086: bnx_init_cpus(sc);
! 3087:
! 3088: /* Prepare NVRAM for access. */
! 3089: if (bnx_init_nvram(sc)) {
! 3090: rc = ENODEV;
! 3091: goto bnx_chipinit_exit;
! 3092: }
! 3093:
! 3094: /* Set the kernel bypass block size */
! 3095: val = REG_RD(sc, BNX_MQ_CONFIG);
! 3096: val &= ~BNX_MQ_CONFIG_KNL_BYP_BLK_SIZE;
! 3097: val |= BNX_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
! 3098: REG_WR(sc, BNX_MQ_CONFIG, val);
! 3099:
! 3100: val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
! 3101: REG_WR(sc, BNX_MQ_KNL_BYP_WIND_START, val);
! 3102: REG_WR(sc, BNX_MQ_KNL_WIND_END, val);
! 3103:
! 3104: val = (BCM_PAGE_BITS - 8) << 24;
! 3105: REG_WR(sc, BNX_RV2P_CONFIG, val);
! 3106:
! 3107: /* Configure page size. */
! 3108: val = REG_RD(sc, BNX_TBDR_CONFIG);
! 3109: val &= ~BNX_TBDR_CONFIG_PAGE_SIZE;
! 3110: val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
! 3111: REG_WR(sc, BNX_TBDR_CONFIG, val);
! 3112:
! 3113: bnx_chipinit_exit:
! 3114: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 3115:
! 3116: return(rc);
! 3117: }
! 3118:
! 3119: /****************************************************************************/
! 3120: /* Initialize the controller in preparation to send/receive traffic. */
! 3121: /* */
! 3122: /* Returns: */
! 3123: /* 0 for success, positive value for failure. */
! 3124: /****************************************************************************/
! 3125: int
! 3126: bnx_blockinit(struct bnx_softc *sc)
! 3127: {
! 3128: u_int32_t reg, val;
! 3129: int rc = 0;
! 3130:
! 3131: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 3132:
! 3133: /* Load the hardware default MAC address. */
! 3134: bnx_set_mac_addr(sc);
! 3135:
! 3136: /* Set the Ethernet backoff seed value */
! 3137: val = sc->eaddr[0] + (sc->eaddr[1] << 8) + (sc->eaddr[2] << 16) +
! 3138: (sc->eaddr[3]) + (sc->eaddr[4] << 8) + (sc->eaddr[5] << 16);
! 3139: REG_WR(sc, BNX_EMAC_BACKOFF_SEED, val);
! 3140:
! 3141: sc->last_status_idx = 0;
! 3142: sc->rx_mode = BNX_EMAC_RX_MODE_SORT_MODE;
! 3143:
! 3144: /* Set up link change interrupt generation. */
! 3145: REG_WR(sc, BNX_EMAC_ATTENTION_ENA, BNX_EMAC_ATTENTION_ENA_LINK);
! 3146:
! 3147: /* Program the physical address of the status block. */
! 3148: REG_WR(sc, BNX_HC_STATUS_ADDR_L, (u_int32_t)(sc->status_block_paddr));
! 3149: REG_WR(sc, BNX_HC_STATUS_ADDR_H,
! 3150: (u_int32_t)((u_int64_t)sc->status_block_paddr >> 32));
! 3151:
! 3152: /* Program the physical address of the statistics block. */
! 3153: REG_WR(sc, BNX_HC_STATISTICS_ADDR_L,
! 3154: (u_int32_t)(sc->stats_block_paddr));
! 3155: REG_WR(sc, BNX_HC_STATISTICS_ADDR_H,
! 3156: (u_int32_t)((u_int64_t)sc->stats_block_paddr >> 32));
! 3157:
! 3158: /* Program various host coalescing parameters. */
! 3159: REG_WR(sc, BNX_HC_TX_QUICK_CONS_TRIP, (sc->bnx_tx_quick_cons_trip_int
! 3160: << 16) | sc->bnx_tx_quick_cons_trip);
! 3161: REG_WR(sc, BNX_HC_RX_QUICK_CONS_TRIP, (sc->bnx_rx_quick_cons_trip_int
! 3162: << 16) | sc->bnx_rx_quick_cons_trip);
! 3163: REG_WR(sc, BNX_HC_COMP_PROD_TRIP, (sc->bnx_comp_prod_trip_int << 16) |
! 3164: sc->bnx_comp_prod_trip);
! 3165: REG_WR(sc, BNX_HC_TX_TICKS, (sc->bnx_tx_ticks_int << 16) |
! 3166: sc->bnx_tx_ticks);
! 3167: REG_WR(sc, BNX_HC_RX_TICKS, (sc->bnx_rx_ticks_int << 16) |
! 3168: sc->bnx_rx_ticks);
! 3169: REG_WR(sc, BNX_HC_COM_TICKS, (sc->bnx_com_ticks_int << 16) |
! 3170: sc->bnx_com_ticks);
! 3171: REG_WR(sc, BNX_HC_CMD_TICKS, (sc->bnx_cmd_ticks_int << 16) |
! 3172: sc->bnx_cmd_ticks);
! 3173: REG_WR(sc, BNX_HC_STATS_TICKS, (sc->bnx_stats_ticks & 0xffff00));
! 3174: REG_WR(sc, BNX_HC_STAT_COLLECT_TICKS, 0xbb8); /* 3ms */
! 3175: REG_WR(sc, BNX_HC_CONFIG,
! 3176: (BNX_HC_CONFIG_RX_TMR_MODE | BNX_HC_CONFIG_TX_TMR_MODE |
! 3177: BNX_HC_CONFIG_COLLECT_STATS));
! 3178:
! 3179: /* Clear the internal statistics counters. */
! 3180: REG_WR(sc, BNX_HC_COMMAND, BNX_HC_COMMAND_CLR_STAT_NOW);
! 3181:
! 3182: /* Verify that bootcode is running. */
! 3183: reg = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_DEV_INFO_SIGNATURE);
! 3184:
! 3185: DBRUNIF(DB_RANDOMTRUE(bnx_debug_bootcode_running_failure),
! 3186: BNX_PRINTF(sc, "%s(%d): Simulating bootcode failure.\n",
! 3187: __FILE__, __LINE__); reg = 0);
! 3188:
! 3189: if ((reg & BNX_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
! 3190: BNX_DEV_INFO_SIGNATURE_MAGIC) {
! 3191: BNX_PRINTF(sc, "%s(%d): Bootcode not running! Found: 0x%08X, "
! 3192: "Expected: 08%08X\n", __FILE__, __LINE__,
! 3193: (reg & BNX_DEV_INFO_SIGNATURE_MAGIC_MASK),
! 3194: BNX_DEV_INFO_SIGNATURE_MAGIC);
! 3195: rc = ENODEV;
! 3196: goto bnx_blockinit_exit;
! 3197: }
! 3198:
! 3199: /* Check if any management firmware is running. */
! 3200: reg = REG_RD_IND(sc, sc->bnx_shmem_base + BNX_PORT_FEATURE);
! 3201: if (reg & (BNX_PORT_FEATURE_ASF_ENABLED |
! 3202: BNX_PORT_FEATURE_IMD_ENABLED)) {
! 3203: DBPRINT(sc, BNX_INFO, "Management F/W Enabled.\n");
! 3204: sc->bnx_flags |= BNX_MFW_ENABLE_FLAG;
! 3205: }
! 3206:
! 3207: sc->bnx_fw_ver = REG_RD_IND(sc, sc->bnx_shmem_base +
! 3208: BNX_DEV_INFO_BC_REV);
! 3209:
! 3210: DBPRINT(sc, BNX_INFO, "bootcode rev = 0x%08X\n", sc->bnx_fw_ver);
! 3211:
! 3212: /* Allow bootcode to apply any additional fixes before enabling MAC. */
! 3213: rc = bnx_fw_sync(sc, BNX_DRV_MSG_DATA_WAIT2 | BNX_DRV_MSG_CODE_RESET);
! 3214:
! 3215: /* Enable link state change interrupt generation. */
! 3216: REG_WR(sc, BNX_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
! 3217:
! 3218: /* Enable all remaining blocks in the MAC. */
! 3219: REG_WR(sc, BNX_MISC_ENABLE_SET_BITS, 0x5ffffff);
! 3220: REG_RD(sc, BNX_MISC_ENABLE_SET_BITS);
! 3221: DELAY(20);
! 3222:
! 3223: bnx_blockinit_exit:
! 3224: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 3225:
! 3226: return (rc);
! 3227: }
! 3228:
! 3229: /****************************************************************************/
! 3230: /* Encapsulate an mbuf cluster into the rx_bd chain. */
! 3231: /* */
! 3232: /* The NetXtreme II can support Jumbo frames by using multiple rx_bd's. */
! 3233: /* This routine will map an mbuf cluster into 1 or more rx_bd's as */
! 3234: /* necessary. */
! 3235: /* */
! 3236: /* Returns: */
! 3237: /* 0 for success, positive value for failure. */
! 3238: /****************************************************************************/
! 3239: int
! 3240: bnx_get_buf(struct bnx_softc *sc, struct mbuf *m, u_int16_t *prod,
! 3241: u_int16_t *chain_prod, u_int32_t *prod_bseq)
! 3242: {
! 3243: bus_dmamap_t map;
! 3244: struct mbuf *m_new = NULL;
! 3245: struct rx_bd *rxbd;
! 3246: int i, rc = 0;
! 3247: u_int32_t addr;
! 3248: #ifdef BNX_DEBUG
! 3249: u_int16_t debug_chain_prod = *chain_prod;
! 3250: #endif
! 3251: u_int16_t first_chain_prod;
! 3252:
! 3253: DBPRINT(sc, (BNX_VERBOSE_RESET | BNX_VERBOSE_RECV), "Entering %s()\n",
! 3254: __FUNCTION__);
! 3255:
! 3256: /* Make sure the inputs are valid. */
! 3257: DBRUNIF((*chain_prod > MAX_RX_BD),
! 3258: printf("%s: RX producer out of range: 0x%04X > 0x%04X\n",
! 3259: *chain_prod, (u_int16_t) MAX_RX_BD));
! 3260:
! 3261: DBPRINT(sc, BNX_VERBOSE_RECV, "%s(enter): prod = 0x%04X, chain_prod = "
! 3262: "0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__, *prod, *chain_prod,
! 3263: *prod_bseq);
! 3264:
! 3265: if (m == NULL) {
! 3266: DBRUNIF(DB_RANDOMTRUE(bnx_debug_mbuf_allocation_failure),
! 3267: BNX_PRINTF(sc, "Simulating mbuf allocation failure.\n");
! 3268:
! 3269: sc->mbuf_alloc_failed++;
! 3270: rc = ENOBUFS;
! 3271: goto bnx_get_buf_exit);
! 3272:
! 3273: /* This is a new mbuf allocation. */
! 3274: MGETHDR(m_new, M_DONTWAIT, MT_DATA);
! 3275: if (m_new == NULL) {
! 3276: DBPRINT(sc, BNX_WARN,
! 3277: "%s(%d): RX mbuf header allocation failed!\n",
! 3278: __FILE__, __LINE__);
! 3279:
! 3280: DBRUNIF(1, sc->mbuf_alloc_failed++);
! 3281:
! 3282: rc = ENOBUFS;
! 3283: goto bnx_get_buf_exit;
! 3284: }
! 3285:
! 3286: DBRUNIF(1, sc->rx_mbuf_alloc++);
! 3287: MCLGET(m_new, M_DONTWAIT);
! 3288: if (!(m_new->m_flags & M_EXT)) {
! 3289: DBPRINT(sc, BNX_WARN,
! 3290: "%s(%d): RX mbuf chain allocation failed!\n",
! 3291: __FILE__, __LINE__);
! 3292:
! 3293: m_freem(m_new);
! 3294:
! 3295: DBRUNIF(1, sc->rx_mbuf_alloc--);
! 3296: DBRUNIF(1, sc->mbuf_alloc_failed++);
! 3297:
! 3298: rc = ENOBUFS;
! 3299: goto bnx_get_buf_exit;
! 3300: }
! 3301:
! 3302: m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size;
! 3303: } else {
! 3304: m_new = m;
! 3305: m_new->m_len = m_new->m_pkthdr.len = sc->mbuf_alloc_size;
! 3306: m_new->m_data = m_new->m_ext.ext_buf;
! 3307: }
! 3308:
! 3309: /* Map the mbuf cluster into device memory. */
! 3310: map = sc->rx_mbuf_map[*chain_prod];
! 3311: first_chain_prod = *chain_prod;
! 3312: if (bus_dmamap_load_mbuf(sc->bnx_dmatag, map, m_new, BUS_DMA_NOWAIT)) {
! 3313: BNX_PRINTF(sc, "%s(%d): Error mapping mbuf into RX chain!\n",
! 3314: __FILE__, __LINE__);
! 3315:
! 3316: m_freem(m_new);
! 3317:
! 3318: DBRUNIF(1, sc->rx_mbuf_alloc--);
! 3319:
! 3320: rc = ENOBUFS;
! 3321: goto bnx_get_buf_exit;
! 3322: }
! 3323:
! 3324: /* Watch for overflow. */
! 3325: DBRUNIF((sc->free_rx_bd > USABLE_RX_BD),
! 3326: printf("%s: Too many free rx_bd (0x%04X > 0x%04X)!\n",
! 3327: sc->free_rx_bd, (u_int16_t) USABLE_RX_BD));
! 3328:
! 3329: DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
! 3330: sc->rx_low_watermark = sc->free_rx_bd);
! 3331:
! 3332: /* Setup the rx_bd for the first segment. */
! 3333: rxbd = &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
! 3334:
! 3335: addr = (u_int32_t)(map->dm_segs[0].ds_addr);
! 3336: rxbd->rx_bd_haddr_lo = htole32(addr);
! 3337: addr = (u_int32_t)((u_int64_t)map->dm_segs[0].ds_addr >> 32);
! 3338: rxbd->rx_bd_haddr_hi = htole32(addr);
! 3339: rxbd->rx_bd_len = htole32(map->dm_segs[0].ds_len);
! 3340: rxbd->rx_bd_flags = htole32(RX_BD_FLAGS_START);
! 3341: *prod_bseq += map->dm_segs[0].ds_len;
! 3342:
! 3343: for (i = 1; i < map->dm_nsegs; i++) {
! 3344: *prod = NEXT_RX_BD(*prod);
! 3345: *chain_prod = RX_CHAIN_IDX(*prod);
! 3346:
! 3347: rxbd =
! 3348: &sc->rx_bd_chain[RX_PAGE(*chain_prod)][RX_IDX(*chain_prod)];
! 3349:
! 3350: addr = (u_int32_t)(map->dm_segs[i].ds_addr);
! 3351: rxbd->rx_bd_haddr_lo = htole32(addr);
! 3352: addr = (u_int32_t)((u_int64_t)map->dm_segs[i].ds_addr >> 32);
! 3353: rxbd->rx_bd_haddr_hi = htole32(addr);
! 3354: rxbd->rx_bd_len = htole32(map->dm_segs[i].ds_len);
! 3355: rxbd->rx_bd_flags = 0;
! 3356: *prod_bseq += map->dm_segs[i].ds_len;
! 3357: }
! 3358:
! 3359: rxbd->rx_bd_flags |= htole32(RX_BD_FLAGS_END);
! 3360:
! 3361: /*
! 3362: * Save the mbuf, adjust the map pointer (swap map for first and
! 3363: * last rx_bd entry so that rx_mbuf_ptr and rx_mbuf_map matches)
! 3364: * and update our counter.
! 3365: */
! 3366: sc->rx_mbuf_ptr[*chain_prod] = m_new;
! 3367: sc->rx_mbuf_map[first_chain_prod] = sc->rx_mbuf_map[*chain_prod];
! 3368: sc->rx_mbuf_map[*chain_prod] = map;
! 3369: sc->free_rx_bd -= map->dm_nsegs;
! 3370:
! 3371: DBRUN(BNX_VERBOSE_RECV, bnx_dump_rx_mbuf_chain(sc, debug_chain_prod,
! 3372: map->dm_nsegs));
! 3373:
! 3374: DBPRINT(sc, BNX_VERBOSE_RECV, "%s(exit): prod = 0x%04X, chain_prod "
! 3375: "= 0x%04X, prod_bseq = 0x%08X\n", __FUNCTION__, *prod,
! 3376: *chain_prod, *prod_bseq);
! 3377:
! 3378: bnx_get_buf_exit:
! 3379: DBPRINT(sc, (BNX_VERBOSE_RESET | BNX_VERBOSE_RECV), "Exiting %s()\n",
! 3380: __FUNCTION__);
! 3381:
! 3382: return(rc);
! 3383: }
! 3384:
! 3385: /****************************************************************************/
! 3386: /* Allocate memory and initialize the TX data structures. */
! 3387: /* */
! 3388: /* Returns: */
! 3389: /* 0 for success, positive value for failure. */
! 3390: /****************************************************************************/
! 3391: int
! 3392: bnx_init_tx_chain(struct bnx_softc *sc)
! 3393: {
! 3394: struct tx_bd *txbd;
! 3395: u_int32_t val, addr;
! 3396: int i, rc = 0;
! 3397:
! 3398: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 3399:
! 3400: /* Set the initial TX producer/consumer indices. */
! 3401: sc->tx_prod = 0;
! 3402: sc->tx_cons = 0;
! 3403: sc->tx_prod_bseq = 0;
! 3404: sc->used_tx_bd = 0;
! 3405: DBRUNIF(1, sc->tx_hi_watermark = USABLE_TX_BD);
! 3406:
! 3407: /*
! 3408: * The NetXtreme II supports a linked-list structure called
! 3409: * a Buffer Descriptor Chain (or BD chain). A BD chain
! 3410: * consists of a series of 1 or more chain pages, each of which
! 3411: * consists of a fixed number of BD entries.
! 3412: * The last BD entry on each page is a pointer to the next page
! 3413: * in the chain, and the last pointer in the BD chain
! 3414: * points back to the beginning of the chain.
! 3415: */
! 3416:
! 3417: /* Set the TX next pointer chain entries. */
! 3418: for (i = 0; i < TX_PAGES; i++) {
! 3419: int j;
! 3420:
! 3421: txbd = &sc->tx_bd_chain[i][USABLE_TX_BD_PER_PAGE];
! 3422:
! 3423: /* Check if we've reached the last page. */
! 3424: if (i == (TX_PAGES - 1))
! 3425: j = 0;
! 3426: else
! 3427: j = i + 1;
! 3428:
! 3429: addr = (u_int32_t)(sc->tx_bd_chain_paddr[j]);
! 3430: txbd->tx_bd_haddr_lo = htole32(addr);
! 3431: addr = (u_int32_t)((u_int64_t)sc->tx_bd_chain_paddr[j] >> 32);
! 3432: txbd->tx_bd_haddr_hi = htole32(addr);
! 3433: }
! 3434:
! 3435: /*
! 3436: * Initialize the context ID for an L2 TX chain.
! 3437: */
! 3438: val = BNX_L2CTX_TYPE_TYPE_L2;
! 3439: val |= BNX_L2CTX_TYPE_SIZE_L2;
! 3440: CTX_WR(sc, GET_CID_ADDR(TX_CID), BNX_L2CTX_TYPE, val);
! 3441:
! 3442: val = BNX_L2CTX_CMD_TYPE_TYPE_L2 | (8 << 16);
! 3443: CTX_WR(sc, GET_CID_ADDR(TX_CID), BNX_L2CTX_CMD_TYPE, val);
! 3444:
! 3445: /* Point the hardware to the first page in the chain. */
! 3446: val = (u_int32_t)((u_int64_t)sc->tx_bd_chain_paddr[0] >> 32);
! 3447: CTX_WR(sc, GET_CID_ADDR(TX_CID), BNX_L2CTX_TBDR_BHADDR_HI, val);
! 3448: val = (u_int32_t)(sc->tx_bd_chain_paddr[0]);
! 3449: CTX_WR(sc, GET_CID_ADDR(TX_CID), BNX_L2CTX_TBDR_BHADDR_LO, val);
! 3450:
! 3451: DBRUN(BNX_VERBOSE_SEND, bnx_dump_tx_chain(sc, 0, TOTAL_TX_BD));
! 3452:
! 3453: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 3454:
! 3455: return(rc);
! 3456: }
! 3457:
! 3458: /****************************************************************************/
! 3459: /* Free memory and clear the TX data structures. */
! 3460: /* */
! 3461: /* Returns: */
! 3462: /* Nothing. */
! 3463: /****************************************************************************/
! 3464: void
! 3465: bnx_free_tx_chain(struct bnx_softc *sc)
! 3466: {
! 3467: int i;
! 3468:
! 3469: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 3470:
! 3471: /* Unmap, unload, and free any mbufs still in the TX mbuf chain. */
! 3472: for (i = 0; i < TOTAL_TX_BD; i++) {
! 3473: if (sc->tx_mbuf_ptr[i] != NULL) {
! 3474: if (sc->tx_mbuf_map != NULL)
! 3475: bus_dmamap_sync(sc->bnx_dmatag,
! 3476: sc->tx_mbuf_map[i], 0,
! 3477: sc->tx_mbuf_map[i]->dm_mapsize,
! 3478: BUS_DMASYNC_POSTWRITE);
! 3479: m_freem(sc->tx_mbuf_ptr[i]);
! 3480: sc->tx_mbuf_ptr[i] = NULL;
! 3481: DBRUNIF(1, sc->tx_mbuf_alloc--);
! 3482: }
! 3483: }
! 3484:
! 3485: /* Clear each TX chain page. */
! 3486: for (i = 0; i < TX_PAGES; i++)
! 3487: bzero((char *)sc->tx_bd_chain[i], BNX_TX_CHAIN_PAGE_SZ);
! 3488:
! 3489: /* Check if we lost any mbufs in the process. */
! 3490: DBRUNIF((sc->tx_mbuf_alloc),
! 3491: printf("%s: Memory leak! Lost %d mbufs from tx chain!\n",
! 3492: sc->tx_mbuf_alloc));
! 3493:
! 3494: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 3495: }
! 3496:
! 3497: /****************************************************************************/
! 3498: /* Allocate memory and initialize the RX data structures. */
! 3499: /* */
! 3500: /* Returns: */
! 3501: /* 0 for success, positive value for failure. */
! 3502: /****************************************************************************/
! 3503: int
! 3504: bnx_init_rx_chain(struct bnx_softc *sc)
! 3505: {
! 3506: struct rx_bd *rxbd;
! 3507: int i, rc = 0;
! 3508: u_int16_t prod, chain_prod;
! 3509: u_int32_t prod_bseq, val, addr;
! 3510:
! 3511: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 3512:
! 3513: /* Initialize the RX producer and consumer indices. */
! 3514: sc->rx_prod = 0;
! 3515: sc->rx_cons = 0;
! 3516: sc->rx_prod_bseq = 0;
! 3517: sc->free_rx_bd = BNX_RX_SLACK_SPACE;
! 3518: DBRUNIF(1, sc->rx_low_watermark = USABLE_RX_BD);
! 3519:
! 3520: /* Initialize the RX next pointer chain entries. */
! 3521: for (i = 0; i < RX_PAGES; i++) {
! 3522: int j;
! 3523:
! 3524: rxbd = &sc->rx_bd_chain[i][USABLE_RX_BD_PER_PAGE];
! 3525:
! 3526: /* Check if we've reached the last page. */
! 3527: if (i == (RX_PAGES - 1))
! 3528: j = 0;
! 3529: else
! 3530: j = i + 1;
! 3531:
! 3532: /* Setup the chain page pointers. */
! 3533: addr = (u_int32_t)((u_int64_t)sc->rx_bd_chain_paddr[j] >> 32);
! 3534: rxbd->rx_bd_haddr_hi = htole32(addr);
! 3535: addr = (u_int32_t)(sc->rx_bd_chain_paddr[j]);
! 3536: rxbd->rx_bd_haddr_lo = htole32(addr);
! 3537: }
! 3538:
! 3539: /* Initialize the context ID for an L2 RX chain. */
! 3540: val = BNX_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
! 3541: val |= BNX_L2CTX_CTX_TYPE_SIZE_L2;
! 3542: val |= 0x02 << 8;
! 3543: CTX_WR(sc, GET_CID_ADDR(RX_CID), BNX_L2CTX_CTX_TYPE, val);
! 3544:
! 3545: /* Point the hardware to the first page in the chain. */
! 3546: val = (u_int32_t)((u_int64_t)sc->rx_bd_chain_paddr[0] >> 32);
! 3547: CTX_WR(sc, GET_CID_ADDR(RX_CID), BNX_L2CTX_NX_BDHADDR_HI, val);
! 3548: val = (u_int32_t)(sc->rx_bd_chain_paddr[0]);
! 3549: CTX_WR(sc, GET_CID_ADDR(RX_CID), BNX_L2CTX_NX_BDHADDR_LO, val);
! 3550:
! 3551: /* Allocate mbuf clusters for the rx_bd chain. */
! 3552: prod = prod_bseq = 0;
! 3553: while (prod < BNX_RX_SLACK_SPACE) {
! 3554: chain_prod = RX_CHAIN_IDX(prod);
! 3555: if (bnx_get_buf(sc, NULL, &prod, &chain_prod, &prod_bseq)) {
! 3556: BNX_PRINTF(sc, "Error filling RX chain: rx_bd[0x%04X]!\n",
! 3557: chain_prod);
! 3558: rc = ENOBUFS;
! 3559: break;
! 3560: }
! 3561: prod = NEXT_RX_BD(prod);
! 3562: }
! 3563:
! 3564: /* Save the RX chain producer index. */
! 3565: sc->rx_prod = prod;
! 3566: sc->rx_prod_bseq = prod_bseq;
! 3567:
! 3568: for (i = 0; i < RX_PAGES; i++)
! 3569: bus_dmamap_sync(sc->bnx_dmatag, sc->rx_bd_chain_map[i], 0,
! 3570: sc->rx_bd_chain_map[i]->dm_mapsize,
! 3571: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 3572:
! 3573: /* Tell the chip about the waiting rx_bd's. */
! 3574: REG_WR16(sc, MB_RX_CID_ADDR + BNX_L2CTX_HOST_BDIDX, sc->rx_prod);
! 3575: REG_WR(sc, MB_RX_CID_ADDR + BNX_L2CTX_HOST_BSEQ, sc->rx_prod_bseq);
! 3576:
! 3577: DBRUN(BNX_VERBOSE_RECV, bnx_dump_rx_chain(sc, 0, TOTAL_RX_BD));
! 3578:
! 3579: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 3580:
! 3581: return(rc);
! 3582: }
! 3583:
! 3584: /****************************************************************************/
! 3585: /* Free memory and clear the RX data structures. */
! 3586: /* */
! 3587: /* Returns: */
! 3588: /* Nothing. */
! 3589: /****************************************************************************/
! 3590: void
! 3591: bnx_free_rx_chain(struct bnx_softc *sc)
! 3592: {
! 3593: int i;
! 3594:
! 3595: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 3596:
! 3597: /* Free any mbufs still in the RX mbuf chain. */
! 3598: for (i = 0; i < TOTAL_RX_BD; i++) {
! 3599: if (sc->rx_mbuf_ptr[i] != NULL) {
! 3600: if (sc->rx_mbuf_map[i] != NULL)
! 3601: bus_dmamap_sync(sc->bnx_dmatag,
! 3602: sc->rx_mbuf_map[i], 0,
! 3603: sc->rx_mbuf_map[i]->dm_mapsize,
! 3604: BUS_DMASYNC_POSTREAD);
! 3605: m_freem(sc->rx_mbuf_ptr[i]);
! 3606: sc->rx_mbuf_ptr[i] = NULL;
! 3607: DBRUNIF(1, sc->rx_mbuf_alloc--);
! 3608: }
! 3609: }
! 3610:
! 3611: /* Clear each RX chain page. */
! 3612: for (i = 0; i < RX_PAGES; i++)
! 3613: bzero((char *)sc->rx_bd_chain[i], BNX_RX_CHAIN_PAGE_SZ);
! 3614:
! 3615: /* Check if we lost any mbufs in the process. */
! 3616: DBRUNIF((sc->rx_mbuf_alloc),
! 3617: printf("%s: Memory leak! Lost %d mbufs from rx chain!\n",
! 3618: sc->rx_mbuf_alloc));
! 3619:
! 3620: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 3621: }
! 3622:
! 3623: /****************************************************************************/
! 3624: /* Set media options. */
! 3625: /* */
! 3626: /* Returns: */
! 3627: /* 0 for success, positive value for failure. */
! 3628: /****************************************************************************/
! 3629: int
! 3630: bnx_ifmedia_upd(struct ifnet *ifp)
! 3631: {
! 3632: struct bnx_softc *sc;
! 3633: struct mii_data *mii;
! 3634: struct ifmedia *ifm;
! 3635: int rc = 0;
! 3636:
! 3637: sc = ifp->if_softc;
! 3638: ifm = &sc->bnx_ifmedia;
! 3639:
! 3640: /* DRC - ToDo: Add SerDes support. */
! 3641:
! 3642: mii = &sc->bnx_mii;
! 3643: sc->bnx_link = 0;
! 3644: if (mii->mii_instance) {
! 3645: struct mii_softc *miisc;
! 3646: LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
! 3647: mii_phy_reset(miisc);
! 3648: }
! 3649: mii_mediachg(mii);
! 3650:
! 3651: return(rc);
! 3652: }
! 3653:
! 3654: /****************************************************************************/
! 3655: /* Reports current media status. */
! 3656: /* */
! 3657: /* Returns: */
! 3658: /* Nothing. */
! 3659: /****************************************************************************/
! 3660: void
! 3661: bnx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
! 3662: {
! 3663: struct bnx_softc *sc;
! 3664: struct mii_data *mii;
! 3665: int s;
! 3666:
! 3667: sc = ifp->if_softc;
! 3668:
! 3669: s = splnet();
! 3670:
! 3671: mii = &sc->bnx_mii;
! 3672:
! 3673: /* DRC - ToDo: Add SerDes support. */
! 3674:
! 3675: mii_pollstat(mii);
! 3676: ifmr->ifm_active = mii->mii_media_active;
! 3677: ifmr->ifm_status = mii->mii_media_status;
! 3678:
! 3679: splx(s);
! 3680: }
! 3681:
! 3682: /****************************************************************************/
! 3683: /* Handles PHY generated interrupt events. */
! 3684: /* */
! 3685: /* Returns: */
! 3686: /* Nothing. */
! 3687: /****************************************************************************/
! 3688: void
! 3689: bnx_phy_intr(struct bnx_softc *sc)
! 3690: {
! 3691: u_int32_t new_link_state, old_link_state;
! 3692:
! 3693: new_link_state = sc->status_block->status_attn_bits &
! 3694: STATUS_ATTN_BITS_LINK_STATE;
! 3695: old_link_state = sc->status_block->status_attn_bits_ack &
! 3696: STATUS_ATTN_BITS_LINK_STATE;
! 3697:
! 3698: /* Handle any changes if the link state has changed. */
! 3699: if (new_link_state != old_link_state) {
! 3700: DBRUN(BNX_VERBOSE_INTR, bnx_dump_status_block(sc));
! 3701:
! 3702: sc->bnx_link = 0;
! 3703: timeout_del(&sc->bnx_timeout);
! 3704: bnx_tick(sc);
! 3705:
! 3706: /* Update the status_attn_bits_ack field in the status block. */
! 3707: if (new_link_state) {
! 3708: REG_WR(sc, BNX_PCICFG_STATUS_BIT_SET_CMD,
! 3709: STATUS_ATTN_BITS_LINK_STATE);
! 3710: DBPRINT(sc, BNX_INFO, "Link is now UP.\n");
! 3711: } else {
! 3712: REG_WR(sc, BNX_PCICFG_STATUS_BIT_CLEAR_CMD,
! 3713: STATUS_ATTN_BITS_LINK_STATE);
! 3714: DBPRINT(sc, BNX_INFO, "Link is now DOWN.\n");
! 3715: }
! 3716: }
! 3717:
! 3718: /* Acknowledge the link change interrupt. */
! 3719: REG_WR(sc, BNX_EMAC_STATUS, BNX_EMAC_STATUS_LINK_CHANGE);
! 3720: }
! 3721:
! 3722: /****************************************************************************/
! 3723: /* Handles received frame interrupt events. */
! 3724: /* */
! 3725: /* Returns: */
! 3726: /* Nothing. */
! 3727: /****************************************************************************/
! 3728: void
! 3729: bnx_rx_intr(struct bnx_softc *sc)
! 3730: {
! 3731: struct status_block *sblk = sc->status_block;
! 3732: struct ifnet *ifp = &sc->arpcom.ac_if;
! 3733: u_int16_t hw_cons, sw_cons, sw_chain_cons;
! 3734: u_int16_t sw_prod, sw_chain_prod;
! 3735: u_int32_t sw_prod_bseq;
! 3736: struct l2_fhdr *l2fhdr;
! 3737: int i;
! 3738:
! 3739: DBRUNIF(1, sc->rx_interrupts++);
! 3740:
! 3741: /* Prepare the RX chain pages to be accessed by the host CPU. */
! 3742: for (i = 0; i < RX_PAGES; i++)
! 3743: bus_dmamap_sync(sc->bnx_dmatag,
! 3744: sc->rx_bd_chain_map[i], 0,
! 3745: sc->rx_bd_chain_map[i]->dm_mapsize,
! 3746: BUS_DMASYNC_POSTWRITE);
! 3747:
! 3748: /* Get the hardware's view of the RX consumer index. */
! 3749: hw_cons = sc->hw_rx_cons = sblk->status_rx_quick_consumer_index0;
! 3750: if ((hw_cons & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
! 3751: hw_cons++;
! 3752:
! 3753: /* Get working copies of the driver's view of the RX indices. */
! 3754: sw_cons = sc->rx_cons;
! 3755: sw_prod = sc->rx_prod;
! 3756: sw_prod_bseq = sc->rx_prod_bseq;
! 3757:
! 3758: DBPRINT(sc, BNX_INFO_RECV, "%s(enter): sw_prod = 0x%04X, "
! 3759: "sw_cons = 0x%04X, sw_prod_bseq = 0x%08X\n",
! 3760: __FUNCTION__, sw_prod, sw_cons, sw_prod_bseq);
! 3761:
! 3762: /* Prevent speculative reads from getting ahead of the status block. */
! 3763: bus_space_barrier(sc->bnx_btag, sc->bnx_bhandle, 0, 0,
! 3764: BUS_SPACE_BARRIER_READ);
! 3765:
! 3766: DBRUNIF((sc->free_rx_bd < sc->rx_low_watermark),
! 3767: sc->rx_low_watermark = sc->free_rx_bd);
! 3768:
! 3769: /*
! 3770: * Scan through the receive chain as long
! 3771: * as there is work to do.
! 3772: */
! 3773: while (sw_cons != hw_cons) {
! 3774: struct mbuf *m;
! 3775: struct rx_bd *rxbd;
! 3776: unsigned int len;
! 3777: u_int32_t status;
! 3778:
! 3779: /* Convert the producer/consumer indices to an actual
! 3780: * rx_bd index.
! 3781: */
! 3782: sw_chain_cons = RX_CHAIN_IDX(sw_cons);
! 3783: sw_chain_prod = RX_CHAIN_IDX(sw_prod);
! 3784:
! 3785: /* Get the used rx_bd. */
! 3786: rxbd = &sc->rx_bd_chain[RX_PAGE(sw_chain_cons)][RX_IDX(sw_chain_cons)];
! 3787: sc->free_rx_bd++;
! 3788:
! 3789: DBRUN(BNX_VERBOSE_RECV, printf("%s(): ", __FUNCTION__);
! 3790: bnx_dump_rxbd(sc, sw_chain_cons, rxbd));
! 3791:
! 3792: /* The mbuf is stored with the last rx_bd entry of a packet. */
! 3793: if (sc->rx_mbuf_ptr[sw_chain_cons] != NULL) {
! 3794: /* Validate that this is the last rx_bd. */
! 3795: DBRUNIF((!(rxbd->rx_bd_flags & RX_BD_FLAGS_END)),
! 3796: printf("%s: Unexpected mbuf found in "
! 3797: "rx_bd[0x%04X]!\n", sw_chain_cons);
! 3798: bnx_breakpoint(sc));
! 3799:
! 3800: /* DRC - ToDo: If the received packet is small, say less
! 3801: * than 128 bytes, allocate a new mbuf here,
! 3802: * copy the data to that mbuf, and recycle
! 3803: * the mapped jumbo frame.
! 3804: */
! 3805:
! 3806: /* Unmap the mbuf from DMA space. */
! 3807: bus_dmamap_sync(sc->bnx_dmatag,
! 3808: sc->rx_mbuf_map[sw_chain_cons], 0,
! 3809: sc->rx_mbuf_map[sw_chain_cons]->dm_mapsize,
! 3810: BUS_DMASYNC_POSTREAD);
! 3811: bus_dmamap_unload(sc->bnx_dmatag,
! 3812: sc->rx_mbuf_map[sw_chain_cons]);
! 3813:
! 3814: /* Remove the mbuf from the driver's chain. */
! 3815: m = sc->rx_mbuf_ptr[sw_chain_cons];
! 3816: sc->rx_mbuf_ptr[sw_chain_cons] = NULL;
! 3817:
! 3818: /*
! 3819: * Frames received on the NetXteme II are prepended
! 3820: * with the l2_fhdr structure which provides status
! 3821: * information about the received frame (including
! 3822: * VLAN tags and checksum info) and are also
! 3823: * automatically adjusted to align the IP header
! 3824: * (i.e. two null bytes are inserted before the
! 3825: * Ethernet header).
! 3826: */
! 3827: l2fhdr = mtod(m, struct l2_fhdr *);
! 3828:
! 3829: len = l2fhdr->l2_fhdr_pkt_len;
! 3830: status = l2fhdr->l2_fhdr_status;
! 3831:
! 3832: DBRUNIF(DB_RANDOMTRUE(bnx_debug_l2fhdr_status_check),
! 3833: printf("Simulating l2_fhdr status error.\n");
! 3834: status = status | L2_FHDR_ERRORS_PHY_DECODE);
! 3835:
! 3836: /* Watch for unusual sized frames. */
! 3837: DBRUNIF(((len < BNX_MIN_MTU) ||
! 3838: (len > BNX_MAX_JUMBO_ETHER_MTU_VLAN)),
! 3839: printf("%s: Unusual frame size found. "
! 3840: "Min(%d), Actual(%d), Max(%d)\n", (int)BNX_MIN_MTU,
! 3841: len, (int) BNX_MAX_JUMBO_ETHER_MTU_VLAN);
! 3842:
! 3843: bnx_dump_mbuf(sc, m);
! 3844: bnx_breakpoint(sc));
! 3845:
! 3846: len -= ETHER_CRC_LEN;
! 3847:
! 3848: /* Check the received frame for errors. */
! 3849: if (status & (L2_FHDR_ERRORS_BAD_CRC |
! 3850: L2_FHDR_ERRORS_PHY_DECODE |
! 3851: L2_FHDR_ERRORS_ALIGNMENT |
! 3852: L2_FHDR_ERRORS_TOO_SHORT |
! 3853: L2_FHDR_ERRORS_GIANT_FRAME)) {
! 3854: ifp->if_ierrors++;
! 3855: DBRUNIF(1, sc->l2fhdr_status_errors++);
! 3856:
! 3857: /* Reuse the mbuf for a new frame. */
! 3858: if (bnx_get_buf(sc, m, &sw_prod,
! 3859: &sw_chain_prod, &sw_prod_bseq)) {
! 3860: DBRUNIF(1, bnx_breakpoint(sc));
! 3861: panic("%s: Can't reuse RX mbuf!\n",
! 3862: sc->bnx_dev.dv_xname);
! 3863: }
! 3864: goto bnx_rx_int_next_rx;
! 3865: }
! 3866:
! 3867: /*
! 3868: * Get a new mbuf for the rx_bd. If no new
! 3869: * mbufs are available then reuse the current mbuf,
! 3870: * log an ierror on the interface, and generate
! 3871: * an error in the system log.
! 3872: */
! 3873: if (bnx_get_buf(sc, NULL, &sw_prod, &sw_chain_prod,
! 3874: &sw_prod_bseq)) {
! 3875: DBRUN(BNX_WARN, BNX_PRINTF(sc, "Failed to allocate "
! 3876: "new mbuf, incoming frame dropped!\n"));
! 3877:
! 3878: ifp->if_ierrors++;
! 3879:
! 3880: /* Try and reuse the exisitng mbuf. */
! 3881: if (bnx_get_buf(sc, m, &sw_prod,
! 3882: &sw_chain_prod, &sw_prod_bseq)) {
! 3883: DBRUNIF(1, bnx_breakpoint(sc));
! 3884: panic("%s: Double mbuf allocation "
! 3885: "failure!", sc->bnx_dev.dv_xname);
! 3886: }
! 3887: goto bnx_rx_int_next_rx;
! 3888: }
! 3889:
! 3890: /* Skip over the l2_fhdr when passing the data up
! 3891: * the stack.
! 3892: */
! 3893: m_adj(m, sizeof(struct l2_fhdr) + ETHER_ALIGN);
! 3894:
! 3895: /* Adjust the pckt length to match the received data. */
! 3896: m->m_pkthdr.len = m->m_len = len;
! 3897:
! 3898: /* Send the packet to the appropriate interface. */
! 3899: m->m_pkthdr.rcvif = ifp;
! 3900:
! 3901: DBRUN(BNX_VERBOSE_RECV,
! 3902: struct ether_header *eh;
! 3903: eh = mtod(m, struct ether_header *);
! 3904: printf("%s: to: %6D, from: %6D, type: 0x%04X\n",
! 3905: __FUNCTION__, eh->ether_dhost, ":",
! 3906: eh->ether_shost, ":", htons(eh->ether_type)));
! 3907:
! 3908: /* Validate the checksum. */
! 3909:
! 3910: /* Check for an IP datagram. */
! 3911: if (status & L2_FHDR_STATUS_IP_DATAGRAM) {
! 3912: /* Check if the IP checksum is valid. */
! 3913: if ((l2fhdr->l2_fhdr_ip_xsum ^ 0xffff)
! 3914: == 0)
! 3915: m->m_pkthdr.csum_flags |=
! 3916: M_IPV4_CSUM_IN_OK;
! 3917: else
! 3918: DBPRINT(sc, BNX_WARN_SEND,
! 3919: "%s(): Invalid IP checksum "
! 3920: "= 0x%04X!\n",
! 3921: __FUNCTION__,
! 3922: l2fhdr->l2_fhdr_ip_xsum
! 3923: );
! 3924: }
! 3925:
! 3926: /* Check for a valid TCP/UDP frame. */
! 3927: if (status & (L2_FHDR_STATUS_TCP_SEGMENT |
! 3928: L2_FHDR_STATUS_UDP_DATAGRAM)) {
! 3929: /* Check for a good TCP/UDP checksum. */
! 3930: if ((status &
! 3931: (L2_FHDR_ERRORS_TCP_XSUM |
! 3932: L2_FHDR_ERRORS_UDP_XSUM)) == 0) {
! 3933: m->m_pkthdr.csum_flags |=
! 3934: M_TCP_CSUM_IN_OK |
! 3935: M_UDP_CSUM_IN_OK;
! 3936: } else {
! 3937: DBPRINT(sc, BNX_WARN_SEND,
! 3938: "%s(): Invalid TCP/UDP "
! 3939: "checksum = 0x%04X!\n",
! 3940: __FUNCTION__,
! 3941: l2fhdr->l2_fhdr_tcp_udp_xsum);
! 3942: }
! 3943: }
! 3944:
! 3945: /*
! 3946: * If we received a packet with a vlan tag,
! 3947: * attach that information to the packet.
! 3948: */
! 3949: if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) &&
! 3950: !(sc->rx_mode & BNX_EMAC_RX_MODE_KEEP_VLAN_TAG)) {
! 3951: #if NVLAN > 0
! 3952: struct ether_vlan_header vh;
! 3953:
! 3954: DBPRINT(sc, BNX_VERBOSE_SEND,
! 3955: "%s(): VLAN tag = 0x%04X\n",
! 3956: __FUNCTION__,
! 3957: l2fhdr->l2_fhdr_vlan_tag);
! 3958:
! 3959: if (m->m_pkthdr.len < ETHER_HDR_LEN) {
! 3960: m_freem(m);
! 3961: goto bnx_rx_int_next_rx;
! 3962: }
! 3963: m_copydata(m, 0, ETHER_HDR_LEN, (caddr_t)&vh);
! 3964: vh.evl_proto = vh.evl_encap_proto;
! 3965: vh.evl_tag = htons(l2fhdr->l2_fhdr_vlan_tag);
! 3966: vh.evl_encap_proto = htons(ETHERTYPE_VLAN);
! 3967: m_adj(m, ETHER_HDR_LEN);
! 3968: M_PREPEND(m, sizeof(vh), M_DONTWAIT);
! 3969: if (m == NULL)
! 3970: goto bnx_rx_int_next_rx;
! 3971: m_copyback(m, 0, sizeof(vh), &vh);
! 3972: #else
! 3973: m_freem(m);
! 3974: goto bnx_rx_int_next_rx;
! 3975: #endif
! 3976: }
! 3977:
! 3978: #if NBPFILTER > 0
! 3979: /*
! 3980: * Handle BPF listeners. Let the BPF
! 3981: * user see the packet.
! 3982: */
! 3983: if (ifp->if_bpf)
! 3984: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
! 3985: #endif
! 3986:
! 3987: /* Pass the mbuf off to the upper layers. */
! 3988: ifp->if_ipackets++;
! 3989: DBPRINT(sc, BNX_VERBOSE_RECV,
! 3990: "%s(): Passing received frame up.\n", __FUNCTION__);
! 3991: ether_input_mbuf(ifp, m);
! 3992: DBRUNIF(1, sc->rx_mbuf_alloc--);
! 3993:
! 3994: bnx_rx_int_next_rx:
! 3995: sw_prod = NEXT_RX_BD(sw_prod);
! 3996: }
! 3997:
! 3998: sw_cons = NEXT_RX_BD(sw_cons);
! 3999:
! 4000: /* Refresh hw_cons to see if there's new work */
! 4001: if (sw_cons == hw_cons) {
! 4002: hw_cons = sc->hw_rx_cons =
! 4003: sblk->status_rx_quick_consumer_index0;
! 4004: if ((hw_cons & USABLE_RX_BD_PER_PAGE) ==
! 4005: USABLE_RX_BD_PER_PAGE)
! 4006: hw_cons++;
! 4007: }
! 4008:
! 4009: /* Prevent speculative reads from getting ahead of
! 4010: * the status block.
! 4011: */
! 4012: bus_space_barrier(sc->bnx_btag, sc->bnx_bhandle, 0, 0,
! 4013: BUS_SPACE_BARRIER_READ);
! 4014: }
! 4015:
! 4016: for (i = 0; i < RX_PAGES; i++)
! 4017: bus_dmamap_sync(sc->bnx_dmatag,
! 4018: sc->rx_bd_chain_map[i], 0,
! 4019: sc->rx_bd_chain_map[i]->dm_mapsize,
! 4020: BUS_DMASYNC_PREWRITE);
! 4021:
! 4022: sc->rx_cons = sw_cons;
! 4023: sc->rx_prod = sw_prod;
! 4024: sc->rx_prod_bseq = sw_prod_bseq;
! 4025:
! 4026: REG_WR16(sc, MB_RX_CID_ADDR + BNX_L2CTX_HOST_BDIDX, sc->rx_prod);
! 4027: REG_WR(sc, MB_RX_CID_ADDR + BNX_L2CTX_HOST_BSEQ, sc->rx_prod_bseq);
! 4028:
! 4029: DBPRINT(sc, BNX_INFO_RECV, "%s(exit): rx_prod = 0x%04X, "
! 4030: "rx_cons = 0x%04X, rx_prod_bseq = 0x%08X\n",
! 4031: __FUNCTION__, sc->rx_prod, sc->rx_cons, sc->rx_prod_bseq);
! 4032: }
! 4033:
! 4034: /****************************************************************************/
! 4035: /* Handles transmit completion interrupt events. */
! 4036: /* */
! 4037: /* Returns: */
! 4038: /* Nothing. */
! 4039: /****************************************************************************/
! 4040: void
! 4041: bnx_tx_intr(struct bnx_softc *sc)
! 4042: {
! 4043: struct status_block *sblk = sc->status_block;
! 4044: struct ifnet *ifp = &sc->arpcom.ac_if;
! 4045: u_int16_t hw_tx_cons, sw_tx_cons, sw_tx_chain_cons;
! 4046:
! 4047: DBRUNIF(1, sc->tx_interrupts++);
! 4048:
! 4049: /* Get the hardware's view of the TX consumer index. */
! 4050: hw_tx_cons = sc->hw_tx_cons = sblk->status_tx_quick_consumer_index0;
! 4051:
! 4052: /* Skip to the next entry if this is a chain page pointer. */
! 4053: if ((hw_tx_cons & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
! 4054: hw_tx_cons++;
! 4055:
! 4056: sw_tx_cons = sc->tx_cons;
! 4057:
! 4058: /* Prevent speculative reads from getting ahead of the status block. */
! 4059: bus_space_barrier(sc->bnx_btag, sc->bnx_bhandle, 0, 0,
! 4060: BUS_SPACE_BARRIER_READ);
! 4061:
! 4062: /* Cycle through any completed TX chain page entries. */
! 4063: while (sw_tx_cons != hw_tx_cons) {
! 4064: #ifdef BNX_DEBUG
! 4065: struct tx_bd *txbd = NULL;
! 4066: #endif
! 4067: sw_tx_chain_cons = TX_CHAIN_IDX(sw_tx_cons);
! 4068:
! 4069: DBPRINT(sc, BNX_INFO_SEND, "%s(): hw_tx_cons = 0x%04X, "
! 4070: "sw_tx_cons = 0x%04X, sw_tx_chain_cons = 0x%04X\n",
! 4071: __FUNCTION__, hw_tx_cons, sw_tx_cons, sw_tx_chain_cons);
! 4072:
! 4073: DBRUNIF((sw_tx_chain_cons > MAX_TX_BD),
! 4074: printf("%s: TX chain consumer out of range! "
! 4075: " 0x%04X > 0x%04X\n", sw_tx_chain_cons, (int)MAX_TX_BD);
! 4076: bnx_breakpoint(sc));
! 4077:
! 4078: DBRUNIF(1, txbd = &sc->tx_bd_chain
! 4079: [TX_PAGE(sw_tx_chain_cons)][TX_IDX(sw_tx_chain_cons)]);
! 4080:
! 4081: DBRUNIF((txbd == NULL),
! 4082: printf("%s: Unexpected NULL tx_bd[0x%04X]!\n",
! 4083: sw_tx_chain_cons);
! 4084: bnx_breakpoint(sc));
! 4085:
! 4086: DBRUN(BNX_INFO_SEND, printf("%s: ", __FUNCTION__);
! 4087: bnx_dump_txbd(sc, sw_tx_chain_cons, txbd));
! 4088:
! 4089: /*
! 4090: * Free the associated mbuf. Remember
! 4091: * that only the last tx_bd of a packet
! 4092: * has an mbuf pointer and DMA map.
! 4093: */
! 4094: if (sc->tx_mbuf_ptr[sw_tx_chain_cons] != NULL) {
! 4095: /* Validate that this is the last tx_bd. */
! 4096: DBRUNIF((!(txbd->tx_bd_flags & TX_BD_FLAGS_END)),
! 4097: printf("%s: tx_bd END flag not set but "
! 4098: "txmbuf == NULL!\n");
! 4099: bnx_breakpoint(sc));
! 4100:
! 4101: DBRUN(BNX_INFO_SEND,
! 4102: printf("%s: Unloading map/freeing mbuf "
! 4103: "from tx_bd[0x%04X]\n",
! 4104: __FUNCTION__, sw_tx_chain_cons));
! 4105:
! 4106: /* Unmap the mbuf. */
! 4107: bus_dmamap_unload(sc->bnx_dmatag,
! 4108: sc->tx_mbuf_map[sw_tx_chain_cons]);
! 4109:
! 4110: /* Free the mbuf. */
! 4111: m_freem(sc->tx_mbuf_ptr[sw_tx_chain_cons]);
! 4112: sc->tx_mbuf_ptr[sw_tx_chain_cons] = NULL;
! 4113: DBRUNIF(1, sc->tx_mbuf_alloc--);
! 4114:
! 4115: ifp->if_opackets++;
! 4116: }
! 4117:
! 4118: sc->used_tx_bd--;
! 4119: sw_tx_cons = NEXT_TX_BD(sw_tx_cons);
! 4120:
! 4121: /* Refresh hw_cons to see if there's new work. */
! 4122: hw_tx_cons = sc->hw_tx_cons =
! 4123: sblk->status_tx_quick_consumer_index0;
! 4124: if ((hw_tx_cons & USABLE_TX_BD_PER_PAGE) ==
! 4125: USABLE_TX_BD_PER_PAGE)
! 4126: hw_tx_cons++;
! 4127:
! 4128: /* Prevent speculative reads from getting ahead of
! 4129: * the status block.
! 4130: */
! 4131: bus_space_barrier(sc->bnx_btag, sc->bnx_bhandle, 0, 0,
! 4132: BUS_SPACE_BARRIER_READ);
! 4133: }
! 4134:
! 4135: /* Clear the TX timeout timer. */
! 4136: ifp->if_timer = 0;
! 4137:
! 4138: /* Clear the tx hardware queue full flag. */
! 4139: if ((sc->used_tx_bd + BNX_TX_SLACK_SPACE) < USABLE_TX_BD) {
! 4140: DBRUNIF((ifp->if_flags & IFF_OACTIVE),
! 4141: printf("%s: TX chain is open for business! Used "
! 4142: "tx_bd = %d\n", sc->used_tx_bd));
! 4143: ifp->if_flags &= ~IFF_OACTIVE;
! 4144: }
! 4145:
! 4146: sc->tx_cons = sw_tx_cons;
! 4147: }
! 4148:
! 4149: /****************************************************************************/
! 4150: /* Disables interrupt generation. */
! 4151: /* */
! 4152: /* Returns: */
! 4153: /* Nothing. */
! 4154: /****************************************************************************/
! 4155: void
! 4156: bnx_disable_intr(struct bnx_softc *sc)
! 4157: {
! 4158: REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, BNX_PCICFG_INT_ACK_CMD_MASK_INT);
! 4159: REG_RD(sc, BNX_PCICFG_INT_ACK_CMD);
! 4160: }
! 4161:
! 4162: /****************************************************************************/
! 4163: /* Enables interrupt generation. */
! 4164: /* */
! 4165: /* Returns: */
! 4166: /* Nothing. */
! 4167: /****************************************************************************/
! 4168: void
! 4169: bnx_enable_intr(struct bnx_softc *sc)
! 4170: {
! 4171: u_int32_t val;
! 4172:
! 4173: REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, BNX_PCICFG_INT_ACK_CMD_INDEX_VALID |
! 4174: BNX_PCICFG_INT_ACK_CMD_MASK_INT | sc->last_status_idx);
! 4175:
! 4176: REG_WR(sc, BNX_PCICFG_INT_ACK_CMD, BNX_PCICFG_INT_ACK_CMD_INDEX_VALID |
! 4177: sc->last_status_idx);
! 4178:
! 4179: val = REG_RD(sc, BNX_HC_COMMAND);
! 4180: REG_WR(sc, BNX_HC_COMMAND, val | BNX_HC_COMMAND_COAL_NOW);
! 4181: }
! 4182:
! 4183: /****************************************************************************/
! 4184: /* Handles controller initialization. */
! 4185: /* */
! 4186: /* Returns: */
! 4187: /* Nothing. */
! 4188: /****************************************************************************/
! 4189: void
! 4190: bnx_init(void *xsc)
! 4191: {
! 4192: struct bnx_softc *sc = (struct bnx_softc *)xsc;
! 4193: struct ifnet *ifp = &sc->arpcom.ac_if;
! 4194: u_int32_t ether_mtu;
! 4195: int s;
! 4196:
! 4197: DBPRINT(sc, BNX_VERBOSE_RESET, "Entering %s()\n", __FUNCTION__);
! 4198:
! 4199: s = splnet();
! 4200:
! 4201: bnx_stop(sc);
! 4202:
! 4203: if (bnx_reset(sc, BNX_DRV_MSG_CODE_RESET)) {
! 4204: BNX_PRINTF(sc, "Controller reset failed!\n");
! 4205: goto bnx_init_exit;
! 4206: }
! 4207:
! 4208: if (bnx_chipinit(sc)) {
! 4209: BNX_PRINTF(sc, "Controller initialization failed!\n");
! 4210: goto bnx_init_exit;
! 4211: }
! 4212:
! 4213: if (bnx_blockinit(sc)) {
! 4214: BNX_PRINTF(sc, "Block initialization failed!\n");
! 4215: goto bnx_init_exit;
! 4216: }
! 4217:
! 4218: /* Load our MAC address. */
! 4219: bcopy(sc->arpcom.ac_enaddr, sc->eaddr, ETHER_ADDR_LEN);
! 4220: bnx_set_mac_addr(sc);
! 4221:
! 4222: /* Calculate and program the Ethernet MRU size. */
! 4223: ether_mtu = BNX_MAX_STD_ETHER_MTU_VLAN;
! 4224:
! 4225: DBPRINT(sc, BNX_INFO, "%s(): setting MRU = %d\n",
! 4226: __FUNCTION__, ether_mtu);
! 4227:
! 4228: /*
! 4229: * Program the MRU and enable Jumbo frame
! 4230: * support.
! 4231: */
! 4232: REG_WR(sc, BNX_EMAC_RX_MTU_SIZE, ether_mtu |
! 4233: BNX_EMAC_RX_MTU_SIZE_JUMBO_ENA);
! 4234:
! 4235: /* Calculate the RX Ethernet frame size for rx_bd's. */
! 4236: sc->max_frame_size = sizeof(struct l2_fhdr) + 2 + ether_mtu + 8;
! 4237:
! 4238: DBPRINT(sc, BNX_INFO, "%s(): mclbytes = %d, mbuf_alloc_size = %d, "
! 4239: "max_frame_size = %d\n", __FUNCTION__, (int)MCLBYTES,
! 4240: sc->mbuf_alloc_size, sc->max_frame_size);
! 4241:
! 4242: /* Program appropriate promiscuous/multicast filtering. */
! 4243: bnx_set_rx_mode(sc);
! 4244:
! 4245: /* Init RX buffer descriptor chain. */
! 4246: bnx_init_rx_chain(sc);
! 4247:
! 4248: /* Init TX buffer descriptor chain. */
! 4249: bnx_init_tx_chain(sc);
! 4250:
! 4251: /* Enable host interrupts. */
! 4252: bnx_enable_intr(sc);
! 4253:
! 4254: bnx_ifmedia_upd(ifp);
! 4255:
! 4256: ifp->if_flags |= IFF_RUNNING;
! 4257: ifp->if_flags &= ~IFF_OACTIVE;
! 4258:
! 4259: timeout_add(&sc->bnx_timeout, hz);
! 4260:
! 4261: bnx_init_exit:
! 4262: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 4263:
! 4264: splx(s);
! 4265:
! 4266: return;
! 4267: }
! 4268:
! 4269: void
! 4270: bnx_mgmt_init(struct bnx_softc *sc)
! 4271: {
! 4272: struct ifnet *ifp = &sc->arpcom.ac_if;
! 4273: u_int32_t val;
! 4274:
! 4275: /* Check if the driver is still running and bail out if it is. */
! 4276: if (ifp->if_flags & IFF_RUNNING)
! 4277: goto bnx_mgmt_init_exit;
! 4278:
! 4279: /* Initialize the on-boards CPUs */
! 4280: bnx_init_cpus(sc);
! 4281:
! 4282: val = (BCM_PAGE_BITS - 8) << 24;
! 4283: REG_WR(sc, BNX_RV2P_CONFIG, val);
! 4284:
! 4285: /* Enable all critical blocks in the MAC. */
! 4286: REG_WR(sc, BNX_MISC_ENABLE_SET_BITS,
! 4287: BNX_MISC_ENABLE_SET_BITS_RX_V2P_ENABLE |
! 4288: BNX_MISC_ENABLE_SET_BITS_RX_DMA_ENABLE |
! 4289: BNX_MISC_ENABLE_SET_BITS_COMPLETION_ENABLE);
! 4290: REG_RD(sc, BNX_MISC_ENABLE_SET_BITS);
! 4291: DELAY(20);
! 4292:
! 4293: bnx_ifmedia_upd(ifp);
! 4294:
! 4295: bnx_mgmt_init_exit:
! 4296: DBPRINT(sc, BNX_VERBOSE_RESET, "Exiting %s()\n", __FUNCTION__);
! 4297: }
! 4298:
! 4299: /****************************************************************************/
! 4300: /* Encapsultes an mbuf cluster into the tx_bd chain structure and makes the */
! 4301: /* memory visible to the controller. */
! 4302: /* */
! 4303: /* Returns: */
! 4304: /* 0 for success, positive value for failure. */
! 4305: /****************************************************************************/
! 4306: int
! 4307: bnx_tx_encap(struct bnx_softc *sc, struct mbuf **m_head)
! 4308: {
! 4309: bus_dmamap_t map;
! 4310: struct tx_bd *txbd = NULL;
! 4311: struct mbuf *m0;
! 4312: u_int16_t vlan_tag = 0, flags = 0;
! 4313: u_int16_t chain_prod, prod;
! 4314: #ifdef BNX_DEBUG
! 4315: u_int16_t debug_prod;
! 4316: #endif
! 4317: u_int32_t addr, prod_bseq;
! 4318: int i, error, rc = 0;
! 4319:
! 4320: m0 = *m_head;
! 4321: /* Transfer any checksum offload flags to the bd. */
! 4322: if (m0->m_pkthdr.csum_flags) {
! 4323: if (m0->m_pkthdr.csum_flags & M_IPV4_CSUM_OUT)
! 4324: flags |= TX_BD_FLAGS_IP_CKSUM;
! 4325: if (m0->m_pkthdr.csum_flags &
! 4326: (M_TCPV4_CSUM_OUT | M_UDPV4_CSUM_OUT))
! 4327: flags |= TX_BD_FLAGS_TCP_UDP_CKSUM;
! 4328: }
! 4329:
! 4330: #if NVLAN > 0
! 4331: /* Transfer any VLAN tags to the bd. */
! 4332: if ((m0->m_flags & (M_PROTO1|M_PKTHDR)) == (M_PROTO1|M_PKTHDR) &&
! 4333: m0->m_pkthdr.rcvif != NULL) {
! 4334: struct ifvlan *ifv = m0->m_pkthdr.rcvif->if_softc;
! 4335: flags |= TX_BD_FLAGS_VLAN_TAG;
! 4336: vlan_tag = ifv->ifv_tag;
! 4337: }
! 4338: #endif
! 4339:
! 4340: /* Map the mbuf into DMAable memory. */
! 4341: prod = sc->tx_prod;
! 4342: chain_prod = TX_CHAIN_IDX(prod);
! 4343: map = sc->tx_mbuf_map[chain_prod];
! 4344:
! 4345: /* Map the mbuf into our DMA address space. */
! 4346: error = bus_dmamap_load_mbuf(sc->bnx_dmatag, map, m0, BUS_DMA_NOWAIT);
! 4347: if (error != 0) {
! 4348: printf("%s: Error mapping mbuf into TX chain!\n",
! 4349: sc->bnx_dev.dv_xname);
! 4350: m_freem(m0);
! 4351: *m_head = NULL;
! 4352: return (error);
! 4353: }
! 4354:
! 4355: /*
! 4356: * The chip seems to require that at least 16 descriptors be kept
! 4357: * empty at all times. Make sure we honor that.
! 4358: * XXX Would it be faster to assume worst case scenario for
! 4359: * map->dm_nsegs and do this calculation higher up?
! 4360: */
! 4361: if (map->dm_nsegs > (USABLE_TX_BD - sc->used_tx_bd - BNX_TX_SLACK_SPACE)) {
! 4362: bus_dmamap_unload(sc->bnx_dmatag, map);
! 4363: return (ENOBUFS);
! 4364: }
! 4365:
! 4366: /* prod points to an empty tx_bd at this point. */
! 4367: prod_bseq = sc->tx_prod_bseq;
! 4368: #ifdef BNX_DEBUG
! 4369: debug_prod = chain_prod;
! 4370: #endif
! 4371:
! 4372: DBPRINT(sc, BNX_INFO_SEND,
! 4373: "%s(): Start: prod = 0x%04X, chain_prod = %04X, "
! 4374: "prod_bseq = 0x%08X\n",
! 4375: __FUNCTION__, *prod, chain_prod, prod_bseq);
! 4376:
! 4377: /*
! 4378: * Cycle through each mbuf segment that makes up
! 4379: * the outgoing frame, gathering the mapping info
! 4380: * for that segment and creating a tx_bd for the
! 4381: * mbuf.
! 4382: */
! 4383: for (i = 0; i < map->dm_nsegs ; i++) {
! 4384: chain_prod = TX_CHAIN_IDX(prod);
! 4385: txbd = &sc->tx_bd_chain[TX_PAGE(chain_prod)][TX_IDX(chain_prod)];
! 4386:
! 4387: addr = (u_int32_t)(map->dm_segs[i].ds_addr);
! 4388: txbd->tx_bd_haddr_lo = htole32(addr);
! 4389: addr = (u_int32_t)((u_int64_t)map->dm_segs[i].ds_addr >> 32);
! 4390: txbd->tx_bd_haddr_hi = htole32(addr);
! 4391: txbd->tx_bd_mss_nbytes = htole16(map->dm_segs[i].ds_len);
! 4392: txbd->tx_bd_vlan_tag = htole16(vlan_tag);
! 4393: txbd->tx_bd_flags = htole16(flags);
! 4394: prod_bseq += map->dm_segs[i].ds_len;
! 4395: if (i == 0)
! 4396: txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_START);
! 4397: prod = NEXT_TX_BD(prod);
! 4398: }
! 4399:
! 4400: /* Set the END flag on the last TX buffer descriptor. */
! 4401: txbd->tx_bd_flags |= htole16(TX_BD_FLAGS_END);
! 4402:
! 4403: DBRUN(BNX_INFO_SEND, bnx_dump_tx_chain(sc, debug_prod, nseg));
! 4404:
! 4405: DBPRINT(sc, BNX_INFO_SEND,
! 4406: "%s(): End: prod = 0x%04X, chain_prod = %04X, "
! 4407: "prod_bseq = 0x%08X\n",
! 4408: __FUNCTION__, prod, chain_prod, prod_bseq);
! 4409:
! 4410: /*
! 4411: * Ensure that the mbuf pointer for this
! 4412: * transmission is placed at the array
! 4413: * index of the last descriptor in this
! 4414: * chain. This is done because a single
! 4415: * map is used for all segments of the mbuf
! 4416: * and we don't want to unload the map before
! 4417: * all of the segments have been freed.
! 4418: */
! 4419: sc->tx_mbuf_ptr[chain_prod] = m0;
! 4420: sc->used_tx_bd += map->dm_nsegs;
! 4421:
! 4422: DBRUNIF((sc->used_tx_bd > sc->tx_hi_watermark),
! 4423: sc->tx_hi_watermark = sc->used_tx_bd);
! 4424:
! 4425: DBRUNIF(1, sc->tx_mbuf_alloc++);
! 4426:
! 4427: DBRUN(BNX_VERBOSE_SEND, bnx_dump_tx_mbuf_chain(sc, chain_prod,
! 4428: map_arg.maxsegs));
! 4429:
! 4430: /* prod points to the next free tx_bd at this point. */
! 4431: sc->tx_prod = prod;
! 4432: sc->tx_prod_bseq = prod_bseq;
! 4433:
! 4434: return (rc);
! 4435: }
! 4436:
! 4437: /****************************************************************************/
! 4438: /* Main transmit routine. */
! 4439: /* */
! 4440: /* Returns: */
! 4441: /* Nothing. */
! 4442: /****************************************************************************/
! 4443: void
! 4444: bnx_start(struct ifnet *ifp)
! 4445: {
! 4446: struct bnx_softc *sc = ifp->if_softc;
! 4447: struct mbuf *m_head = NULL;
! 4448: int count = 0;
! 4449: u_int16_t tx_prod, tx_chain_prod;
! 4450:
! 4451: /* If there's no link or the transmit queue is empty then just exit. */
! 4452: if (!sc->bnx_link || IFQ_IS_EMPTY(&ifp->if_snd)) {
! 4453: DBPRINT(sc, BNX_INFO_SEND,
! 4454: "%s(): No link or transmit queue empty.\n", __FUNCTION__);
! 4455: goto bnx_start_exit;
! 4456: }
! 4457:
! 4458: /* prod points to the next free tx_bd. */
! 4459: tx_prod = sc->tx_prod;
! 4460: tx_chain_prod = TX_CHAIN_IDX(tx_prod);
! 4461:
! 4462: DBPRINT(sc, BNX_INFO_SEND, "%s(): Start: tx_prod = 0x%04X, "
! 4463: "tx_chain_prod = %04X, tx_prod_bseq = 0x%08X\n",
! 4464: __FUNCTION__, tx_prod, tx_chain_prod, sc->tx_prod_bseq);
! 4465:
! 4466: /*
! 4467: * Keep adding entries while there is space in the ring. We keep
! 4468: * BNX_TX_SLACK_SPACE entries unused at all times.
! 4469: */
! 4470: while (sc->used_tx_bd < USABLE_TX_BD - BNX_TX_SLACK_SPACE) {
! 4471: /* Check for any frames to send. */
! 4472: IFQ_POLL(&ifp->if_snd, m_head);
! 4473: if (m_head == NULL)
! 4474: break;
! 4475:
! 4476: /*
! 4477: * Pack the data into the transmit ring. If we
! 4478: * don't have room, set the OACTIVE flag to wait
! 4479: * for the NIC to drain the chain.
! 4480: */
! 4481: if (bnx_tx_encap(sc, &m_head)) {
! 4482: ifp->if_flags |= IFF_OACTIVE;
! 4483: DBPRINT(sc, BNX_INFO_SEND, "TX chain is closed for "
! 4484: "business! Total tx_bd used = %d\n",
! 4485: sc->used_tx_bd);
! 4486: break;
! 4487: }
! 4488:
! 4489: IFQ_DEQUEUE(&ifp->if_snd, m_head);
! 4490: count++;
! 4491:
! 4492: #if NBPFILTER > 0
! 4493: /* Send a copy of the frame to any BPF listeners. */
! 4494: if (ifp->if_bpf)
! 4495: bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
! 4496: #endif
! 4497: }
! 4498:
! 4499: if (count == 0) {
! 4500: /* no packets were dequeued */
! 4501: DBPRINT(sc, BNX_VERBOSE_SEND,
! 4502: "%s(): No packets were dequeued\n", __FUNCTION__);
! 4503: goto bnx_start_exit;
! 4504: }
! 4505:
! 4506: /* Update the driver's counters. */
! 4507: tx_chain_prod = TX_CHAIN_IDX(sc->tx_prod);
! 4508:
! 4509: DBPRINT(sc, BNX_INFO_SEND, "%s(): End: tx_prod = 0x%04X, tx_chain_prod "
! 4510: "= 0x%04X, tx_prod_bseq = 0x%08X\n", __FUNCTION__, tx_prod,
! 4511: tx_chain_prod, sc->tx_prod_bseq);
! 4512:
! 4513: /* Start the transmit. */
! 4514: REG_WR16(sc, MB_TX_CID_ADDR + BNX_L2CTX_TX_HOST_BIDX, sc->tx_prod);
! 4515: REG_WR(sc, MB_TX_CID_ADDR + BNX_L2CTX_TX_HOST_BSEQ, sc->tx_prod_bseq);
! 4516:
! 4517: /* Set the tx timeout. */
! 4518: ifp->if_timer = BNX_TX_TIMEOUT;
! 4519:
! 4520: bnx_start_exit:
! 4521: return;
! 4522: }
! 4523:
! 4524: /****************************************************************************/
! 4525: /* Handles any IOCTL calls from the operating system. */
! 4526: /* */
! 4527: /* Returns: */
! 4528: /* 0 for success, positive value for failure. */
! 4529: /****************************************************************************/
! 4530: int
! 4531: bnx_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
! 4532: {
! 4533: struct bnx_softc *sc = ifp->if_softc;
! 4534: struct ifreq *ifr = (struct ifreq *) data;
! 4535: struct ifaddr *ifa = (struct ifaddr *)data;
! 4536: struct mii_data *mii;
! 4537: int s, error = 0;
! 4538:
! 4539: s = splnet();
! 4540:
! 4541: if ((error = ether_ioctl(ifp, &sc->arpcom, command, data)) > 0) {
! 4542: splx(s);
! 4543: return (error);
! 4544: }
! 4545:
! 4546: switch (command) {
! 4547: case SIOCSIFADDR:
! 4548: ifp->if_flags |= IFF_UP;
! 4549: if (!(ifp->if_flags & IFF_RUNNING))
! 4550: bnx_init(sc);
! 4551: #ifdef INET
! 4552: if (ifa->ifa_addr->sa_family == AF_INET)
! 4553: arp_ifinit(&sc->arpcom, ifa);
! 4554: #endif /* INET */
! 4555: break;
! 4556:
! 4557: case SIOCSIFMTU:
! 4558: if (ifr->ifr_mtu < ETHERMIN || ifr->ifr_mtu > ifp->if_hardmtu)
! 4559: error = EINVAL;
! 4560: else if (ifp->if_mtu != ifr->ifr_mtu)
! 4561: ifp->if_mtu = ifr->ifr_mtu;
! 4562: break;
! 4563:
! 4564: case SIOCSIFFLAGS:
! 4565: if (ifp->if_flags & IFF_UP) {
! 4566: if ((ifp->if_flags & IFF_RUNNING) &&
! 4567: ((ifp->if_flags ^ sc->bnx_if_flags) &
! 4568: (IFF_ALLMULTI | IFF_PROMISC)) != 0) {
! 4569: bnx_set_rx_mode(sc);
! 4570: } else {
! 4571: if (!(ifp->if_flags & IFF_RUNNING))
! 4572: bnx_init(sc);
! 4573: }
! 4574: } else {
! 4575: if (ifp->if_flags & IFF_RUNNING)
! 4576: bnx_stop(sc);
! 4577: }
! 4578: sc->bnx_if_flags = ifp->if_flags;
! 4579: break;
! 4580:
! 4581: case SIOCADDMULTI:
! 4582: case SIOCDELMULTI:
! 4583: error = (command == SIOCADDMULTI)
! 4584: ? ether_addmulti(ifr, &sc->arpcom)
! 4585: : ether_delmulti(ifr, &sc->arpcom);
! 4586:
! 4587: if (error == ENETRESET) {
! 4588: if (ifp->if_flags & IFF_RUNNING)
! 4589: bnx_set_rx_mode(sc);
! 4590: error = 0;
! 4591: }
! 4592: break;
! 4593:
! 4594: case SIOCSIFMEDIA:
! 4595: case SIOCGIFMEDIA:
! 4596: DBPRINT(sc, BNX_VERBOSE, "bnx_phy_flags = 0x%08X\n",
! 4597: sc->bnx_phy_flags);
! 4598:
! 4599: if (sc->bnx_phy_flags & BNX_PHY_SERDES_FLAG)
! 4600: error = ifmedia_ioctl(ifp, ifr,
! 4601: &sc->bnx_ifmedia, command);
! 4602: else {
! 4603: mii = &sc->bnx_mii;
! 4604: error = ifmedia_ioctl(ifp, ifr,
! 4605: &mii->mii_media, command);
! 4606: }
! 4607: break;
! 4608:
! 4609: default:
! 4610: error = ENOTTY;
! 4611: break;
! 4612: }
! 4613:
! 4614: splx(s);
! 4615:
! 4616: return (error);
! 4617: }
! 4618:
! 4619: /****************************************************************************/
! 4620: /* Transmit timeout handler. */
! 4621: /* */
! 4622: /* Returns: */
! 4623: /* Nothing. */
! 4624: /****************************************************************************/
! 4625: void
! 4626: bnx_watchdog(struct ifnet *ifp)
! 4627: {
! 4628: struct bnx_softc *sc = ifp->if_softc;
! 4629:
! 4630: DBRUN(BNX_WARN_SEND, bnx_dump_driver_state(sc);
! 4631: bnx_dump_status_block(sc));
! 4632:
! 4633: printf("%s: Watchdog timeout occurred, resetting!\n",
! 4634: ifp->if_xname);
! 4635:
! 4636: /* DBRUN(BNX_FATAL, bnx_breakpoint(sc)); */
! 4637:
! 4638: bnx_init(sc);
! 4639:
! 4640: ifp->if_oerrors++;
! 4641: }
! 4642:
! 4643: /*
! 4644: * Interrupt handler.
! 4645: */
! 4646: /****************************************************************************/
! 4647: /* Main interrupt entry point. Verifies that the controller generated the */
! 4648: /* interrupt and then calls a separate routine for handle the various */
! 4649: /* interrupt causes (PHY, TX, RX). */
! 4650: /* */
! 4651: /* Returns: */
! 4652: /* 0 for success, positive value for failure. */
! 4653: /****************************************************************************/
! 4654: int
! 4655: bnx_intr(void *xsc)
! 4656: {
! 4657: struct bnx_softc *sc;
! 4658: struct ifnet *ifp;
! 4659: u_int32_t status_attn_bits;
! 4660:
! 4661: sc = xsc;
! 4662: if ((sc->bnx_flags & BNX_ACTIVE_FLAG) == 0)
! 4663: return (0);
! 4664:
! 4665: ifp = &sc->arpcom.ac_if;
! 4666:
! 4667: DBRUNIF(1, sc->interrupts_generated++);
! 4668:
! 4669: bus_dmamap_sync(sc->bnx_dmatag, sc->status_map, 0,
! 4670: sc->status_map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
! 4671:
! 4672: /*
! 4673: * If the hardware status block index
! 4674: * matches the last value read by the
! 4675: * driver and we haven't asserted our
! 4676: * interrupt then there's nothing to do.
! 4677: */
! 4678: if ((sc->status_block->status_idx == sc->last_status_idx) &&
! 4679: (REG_RD(sc, BNX_PCICFG_MISC_STATUS) &
! 4680: BNX_PCICFG_MISC_STATUS_INTA_VALUE))
! 4681: return (0);
! 4682:
! 4683: /* Ack the interrupt and stop others from occuring. */
! 4684: REG_WR(sc, BNX_PCICFG_INT_ACK_CMD,
! 4685: BNX_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM |
! 4686: BNX_PCICFG_INT_ACK_CMD_MASK_INT);
! 4687:
! 4688: /* Keep processing data as long as there is work to do. */
! 4689: for (;;) {
! 4690: status_attn_bits = sc->status_block->status_attn_bits;
! 4691:
! 4692: DBRUNIF(DB_RANDOMTRUE(bnx_debug_unexpected_attention),
! 4693: printf("Simulating unexpected status attention bit set.");
! 4694: status_attn_bits = status_attn_bits |
! 4695: STATUS_ATTN_BITS_PARITY_ERROR);
! 4696:
! 4697: /* Was it a link change interrupt? */
! 4698: if ((status_attn_bits & STATUS_ATTN_BITS_LINK_STATE) !=
! 4699: (sc->status_block->status_attn_bits_ack &
! 4700: STATUS_ATTN_BITS_LINK_STATE))
! 4701: bnx_phy_intr(sc);
! 4702:
! 4703: /* If any other attention is asserted then the chip is toast. */
! 4704: if (((status_attn_bits & ~STATUS_ATTN_BITS_LINK_STATE) !=
! 4705: (sc->status_block->status_attn_bits_ack &
! 4706: ~STATUS_ATTN_BITS_LINK_STATE))) {
! 4707: DBRUN(1, sc->unexpected_attentions++);
! 4708:
! 4709: BNX_PRINTF(sc, "Fatal attention detected: 0x%08X\n",
! 4710: sc->status_block->status_attn_bits);
! 4711:
! 4712: DBRUN(BNX_FATAL,
! 4713: if (bnx_debug_unexpected_attention == 0)
! 4714: bnx_breakpoint(sc));
! 4715:
! 4716: bnx_init(sc);
! 4717: return (1);
! 4718: }
! 4719:
! 4720: /* Check for any completed RX frames. */
! 4721: if (sc->status_block->status_rx_quick_consumer_index0 !=
! 4722: sc->hw_rx_cons)
! 4723: bnx_rx_intr(sc);
! 4724:
! 4725: /* Check for any completed TX frames. */
! 4726: if (sc->status_block->status_tx_quick_consumer_index0 !=
! 4727: sc->hw_tx_cons)
! 4728: bnx_tx_intr(sc);
! 4729:
! 4730: /* Save the status block index value for use during the
! 4731: * next interrupt.
! 4732: */
! 4733: sc->last_status_idx = sc->status_block->status_idx;
! 4734:
! 4735: /* Prevent speculative reads from getting ahead of the
! 4736: * status block.
! 4737: */
! 4738: bus_space_barrier(sc->bnx_btag, sc->bnx_bhandle, 0, 0,
! 4739: BUS_SPACE_BARRIER_READ);
! 4740:
! 4741: /* If there's no work left then exit the isr. */
! 4742: if ((sc->status_block->status_rx_quick_consumer_index0 ==
! 4743: sc->hw_rx_cons) &&
! 4744: (sc->status_block->status_tx_quick_consumer_index0 ==
! 4745: sc->hw_tx_cons))
! 4746: break;
! 4747: }
! 4748:
! 4749: bus_dmamap_sync(sc->bnx_dmatag, sc->status_map, 0,
! 4750: sc->status_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
! 4751:
! 4752: /* Re-enable interrupts. */
! 4753: REG_WR(sc, BNX_PCICFG_INT_ACK_CMD,
! 4754: BNX_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx |
! 4755: BNX_PCICFG_INT_ACK_CMD_MASK_INT);
! 4756: REG_WR(sc, BNX_PCICFG_INT_ACK_CMD,
! 4757: BNX_PCICFG_INT_ACK_CMD_INDEX_VALID | sc->last_status_idx);
! 4758:
! 4759: /* Handle any frames that arrived while handling the interrupt. */
! 4760: if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
! 4761: bnx_start(ifp);
! 4762:
! 4763: return (1);
! 4764: }
! 4765:
! 4766: /****************************************************************************/
! 4767: /* Programs the various packet receive modes (broadcast and multicast). */
! 4768: /* */
! 4769: /* Returns: */
! 4770: /* Nothing. */
! 4771: /****************************************************************************/
! 4772: void
! 4773: bnx_set_rx_mode(struct bnx_softc *sc)
! 4774: {
! 4775: struct arpcom *ac = &sc->arpcom;
! 4776: struct ifnet *ifp = &ac->ac_if;
! 4777: struct ether_multi *enm;
! 4778: struct ether_multistep step;
! 4779: u_int32_t hashes[NUM_MC_HASH_REGISTERS] = { 0, 0, 0, 0, 0, 0, 0, 0 };
! 4780: u_int32_t rx_mode, sort_mode;
! 4781: int h, i;
! 4782:
! 4783: /* Initialize receive mode default settings. */
! 4784: rx_mode = sc->rx_mode & ~(BNX_EMAC_RX_MODE_PROMISCUOUS |
! 4785: BNX_EMAC_RX_MODE_KEEP_VLAN_TAG);
! 4786: sort_mode = 1 | BNX_RPM_SORT_USER0_BC_EN;
! 4787:
! 4788: /*
! 4789: * ASF/IPMI/UMP firmware requires that VLAN tag stripping
! 4790: * be enbled.
! 4791: */
! 4792: if (!(sc->bnx_flags & BNX_MFW_ENABLE_FLAG))
! 4793: rx_mode |= BNX_EMAC_RX_MODE_KEEP_VLAN_TAG;
! 4794:
! 4795: /*
! 4796: * Check for promiscuous, all multicast, or selected
! 4797: * multicast address filtering.
! 4798: */
! 4799: if (ifp->if_flags & IFF_PROMISC) {
! 4800: DBPRINT(sc, BNX_INFO, "Enabling promiscuous mode.\n");
! 4801:
! 4802: /* Enable promiscuous mode. */
! 4803: rx_mode |= BNX_EMAC_RX_MODE_PROMISCUOUS;
! 4804: sort_mode |= BNX_RPM_SORT_USER0_PROM_EN;
! 4805: } else if (ifp->if_flags & IFF_ALLMULTI) {
! 4806: allmulti:
! 4807: DBPRINT(sc, BNX_INFO, "Enabling all multicast mode.\n");
! 4808:
! 4809: /* Enable all multicast addresses. */
! 4810: for (i = 0; i < NUM_MC_HASH_REGISTERS; i++)
! 4811: REG_WR(sc, BNX_EMAC_MULTICAST_HASH0 + (i * 4),
! 4812: 0xffffffff);
! 4813: sort_mode |= BNX_RPM_SORT_USER0_MC_EN;
! 4814: } else {
! 4815: /* Accept one or more multicast(s). */
! 4816: DBPRINT(sc, BNX_INFO, "Enabling selective multicast mode.\n");
! 4817:
! 4818: ETHER_FIRST_MULTI(step, ac, enm);
! 4819: while (enm != NULL) {
! 4820: if (bcmp(enm->enm_addrlo, enm->enm_addrhi,
! 4821: ETHER_ADDR_LEN)) {
! 4822: ifp->if_flags |= IFF_ALLMULTI;
! 4823: goto allmulti;
! 4824: }
! 4825: h = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) &
! 4826: 0xFF;
! 4827: hashes[(h & 0xE0) >> 5] |= 1 << (h & 0x1F);
! 4828: ETHER_NEXT_MULTI(step, enm);
! 4829: }
! 4830:
! 4831: for (i = 0; i < NUM_MC_HASH_REGISTERS; i++)
! 4832: REG_WR(sc, BNX_EMAC_MULTICAST_HASH0 + (i * 4),
! 4833: hashes[i]);
! 4834:
! 4835: sort_mode |= BNX_RPM_SORT_USER0_MC_HSH_EN;
! 4836: }
! 4837:
! 4838: /* Only make changes if the recive mode has actually changed. */
! 4839: if (rx_mode != sc->rx_mode) {
! 4840: DBPRINT(sc, BNX_VERBOSE, "Enabling new receive mode: 0x%08X\n",
! 4841: rx_mode);
! 4842:
! 4843: sc->rx_mode = rx_mode;
! 4844: REG_WR(sc, BNX_EMAC_RX_MODE, rx_mode);
! 4845: }
! 4846:
! 4847: /* Disable and clear the exisitng sort before enabling a new sort. */
! 4848: REG_WR(sc, BNX_RPM_SORT_USER0, 0x0);
! 4849: REG_WR(sc, BNX_RPM_SORT_USER0, sort_mode);
! 4850: REG_WR(sc, BNX_RPM_SORT_USER0, sort_mode | BNX_RPM_SORT_USER0_ENA);
! 4851: }
! 4852:
! 4853: /****************************************************************************/
! 4854: /* Called periodically to updates statistics from the controllers */
! 4855: /* statistics block. */
! 4856: /* */
! 4857: /* Returns: */
! 4858: /* Nothing. */
! 4859: /****************************************************************************/
! 4860: void
! 4861: bnx_stats_update(struct bnx_softc *sc)
! 4862: {
! 4863: struct ifnet *ifp = &sc->arpcom.ac_if;
! 4864: struct statistics_block *stats;
! 4865:
! 4866: DBPRINT(sc, BNX_EXCESSIVE, "Entering %s()\n", __FUNCTION__);
! 4867:
! 4868: stats = (struct statistics_block *)sc->stats_block;
! 4869:
! 4870: /*
! 4871: * Update the interface statistics from the
! 4872: * hardware statistics.
! 4873: */
! 4874: ifp->if_collisions = (u_long)stats->stat_EtherStatsCollisions;
! 4875:
! 4876: ifp->if_ierrors = (u_long)stats->stat_EtherStatsUndersizePkts +
! 4877: (u_long)stats->stat_EtherStatsOverrsizePkts +
! 4878: (u_long)stats->stat_IfInMBUFDiscards +
! 4879: (u_long)stats->stat_Dot3StatsAlignmentErrors +
! 4880: (u_long)stats->stat_Dot3StatsFCSErrors;
! 4881:
! 4882: ifp->if_oerrors = (u_long)
! 4883: stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors +
! 4884: (u_long)stats->stat_Dot3StatsExcessiveCollisions +
! 4885: (u_long)stats->stat_Dot3StatsLateCollisions;
! 4886:
! 4887: /*
! 4888: * Certain controllers don't report
! 4889: * carrier sense errors correctly.
! 4890: * See errata E11_5708CA0_1165.
! 4891: */
! 4892: if (!(BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5706) &&
! 4893: !(BNX_CHIP_ID(sc) == BNX_CHIP_ID_5708_A0))
! 4894: ifp->if_oerrors += (u_long) stats->stat_Dot3StatsCarrierSenseErrors;
! 4895:
! 4896: /*
! 4897: * Update the sysctl statistics from the
! 4898: * hardware statistics.
! 4899: */
! 4900: sc->stat_IfHCInOctets = ((u_int64_t)stats->stat_IfHCInOctets_hi << 32) +
! 4901: (u_int64_t) stats->stat_IfHCInOctets_lo;
! 4902:
! 4903: sc->stat_IfHCInBadOctets =
! 4904: ((u_int64_t) stats->stat_IfHCInBadOctets_hi << 32) +
! 4905: (u_int64_t) stats->stat_IfHCInBadOctets_lo;
! 4906:
! 4907: sc->stat_IfHCOutOctets =
! 4908: ((u_int64_t) stats->stat_IfHCOutOctets_hi << 32) +
! 4909: (u_int64_t) stats->stat_IfHCOutOctets_lo;
! 4910:
! 4911: sc->stat_IfHCOutBadOctets =
! 4912: ((u_int64_t) stats->stat_IfHCOutBadOctets_hi << 32) +
! 4913: (u_int64_t) stats->stat_IfHCOutBadOctets_lo;
! 4914:
! 4915: sc->stat_IfHCInUcastPkts =
! 4916: ((u_int64_t) stats->stat_IfHCInUcastPkts_hi << 32) +
! 4917: (u_int64_t) stats->stat_IfHCInUcastPkts_lo;
! 4918:
! 4919: sc->stat_IfHCInMulticastPkts =
! 4920: ((u_int64_t) stats->stat_IfHCInMulticastPkts_hi << 32) +
! 4921: (u_int64_t) stats->stat_IfHCInMulticastPkts_lo;
! 4922:
! 4923: sc->stat_IfHCInBroadcastPkts =
! 4924: ((u_int64_t) stats->stat_IfHCInBroadcastPkts_hi << 32) +
! 4925: (u_int64_t) stats->stat_IfHCInBroadcastPkts_lo;
! 4926:
! 4927: sc->stat_IfHCOutUcastPkts =
! 4928: ((u_int64_t) stats->stat_IfHCOutUcastPkts_hi << 32) +
! 4929: (u_int64_t) stats->stat_IfHCOutUcastPkts_lo;
! 4930:
! 4931: sc->stat_IfHCOutMulticastPkts =
! 4932: ((u_int64_t) stats->stat_IfHCOutMulticastPkts_hi << 32) +
! 4933: (u_int64_t) stats->stat_IfHCOutMulticastPkts_lo;
! 4934:
! 4935: sc->stat_IfHCOutBroadcastPkts =
! 4936: ((u_int64_t) stats->stat_IfHCOutBroadcastPkts_hi << 32) +
! 4937: (u_int64_t) stats->stat_IfHCOutBroadcastPkts_lo;
! 4938:
! 4939: sc->stat_emac_tx_stat_dot3statsinternalmactransmiterrors =
! 4940: stats->stat_emac_tx_stat_dot3statsinternalmactransmiterrors;
! 4941:
! 4942: sc->stat_Dot3StatsCarrierSenseErrors =
! 4943: stats->stat_Dot3StatsCarrierSenseErrors;
! 4944:
! 4945: sc->stat_Dot3StatsFCSErrors = stats->stat_Dot3StatsFCSErrors;
! 4946:
! 4947: sc->stat_Dot3StatsAlignmentErrors =
! 4948: stats->stat_Dot3StatsAlignmentErrors;
! 4949:
! 4950: sc->stat_Dot3StatsSingleCollisionFrames =
! 4951: stats->stat_Dot3StatsSingleCollisionFrames;
! 4952:
! 4953: sc->stat_Dot3StatsMultipleCollisionFrames =
! 4954: stats->stat_Dot3StatsMultipleCollisionFrames;
! 4955:
! 4956: sc->stat_Dot3StatsDeferredTransmissions =
! 4957: stats->stat_Dot3StatsDeferredTransmissions;
! 4958:
! 4959: sc->stat_Dot3StatsExcessiveCollisions =
! 4960: stats->stat_Dot3StatsExcessiveCollisions;
! 4961:
! 4962: sc->stat_Dot3StatsLateCollisions = stats->stat_Dot3StatsLateCollisions;
! 4963:
! 4964: sc->stat_EtherStatsCollisions = stats->stat_EtherStatsCollisions;
! 4965:
! 4966: sc->stat_EtherStatsFragments = stats->stat_EtherStatsFragments;
! 4967:
! 4968: sc->stat_EtherStatsJabbers = stats->stat_EtherStatsJabbers;
! 4969:
! 4970: sc->stat_EtherStatsUndersizePkts = stats->stat_EtherStatsUndersizePkts;
! 4971:
! 4972: sc->stat_EtherStatsOverrsizePkts = stats->stat_EtherStatsOverrsizePkts;
! 4973:
! 4974: sc->stat_EtherStatsPktsRx64Octets =
! 4975: stats->stat_EtherStatsPktsRx64Octets;
! 4976:
! 4977: sc->stat_EtherStatsPktsRx65Octetsto127Octets =
! 4978: stats->stat_EtherStatsPktsRx65Octetsto127Octets;
! 4979:
! 4980: sc->stat_EtherStatsPktsRx128Octetsto255Octets =
! 4981: stats->stat_EtherStatsPktsRx128Octetsto255Octets;
! 4982:
! 4983: sc->stat_EtherStatsPktsRx256Octetsto511Octets =
! 4984: stats->stat_EtherStatsPktsRx256Octetsto511Octets;
! 4985:
! 4986: sc->stat_EtherStatsPktsRx512Octetsto1023Octets =
! 4987: stats->stat_EtherStatsPktsRx512Octetsto1023Octets;
! 4988:
! 4989: sc->stat_EtherStatsPktsRx1024Octetsto1522Octets =
! 4990: stats->stat_EtherStatsPktsRx1024Octetsto1522Octets;
! 4991:
! 4992: sc->stat_EtherStatsPktsRx1523Octetsto9022Octets =
! 4993: stats->stat_EtherStatsPktsRx1523Octetsto9022Octets;
! 4994:
! 4995: sc->stat_EtherStatsPktsTx64Octets =
! 4996: stats->stat_EtherStatsPktsTx64Octets;
! 4997:
! 4998: sc->stat_EtherStatsPktsTx65Octetsto127Octets =
! 4999: stats->stat_EtherStatsPktsTx65Octetsto127Octets;
! 5000:
! 5001: sc->stat_EtherStatsPktsTx128Octetsto255Octets =
! 5002: stats->stat_EtherStatsPktsTx128Octetsto255Octets;
! 5003:
! 5004: sc->stat_EtherStatsPktsTx256Octetsto511Octets =
! 5005: stats->stat_EtherStatsPktsTx256Octetsto511Octets;
! 5006:
! 5007: sc->stat_EtherStatsPktsTx512Octetsto1023Octets =
! 5008: stats->stat_EtherStatsPktsTx512Octetsto1023Octets;
! 5009:
! 5010: sc->stat_EtherStatsPktsTx1024Octetsto1522Octets =
! 5011: stats->stat_EtherStatsPktsTx1024Octetsto1522Octets;
! 5012:
! 5013: sc->stat_EtherStatsPktsTx1523Octetsto9022Octets =
! 5014: stats->stat_EtherStatsPktsTx1523Octetsto9022Octets;
! 5015:
! 5016: sc->stat_XonPauseFramesReceived = stats->stat_XonPauseFramesReceived;
! 5017:
! 5018: sc->stat_XoffPauseFramesReceived = stats->stat_XoffPauseFramesReceived;
! 5019:
! 5020: sc->stat_OutXonSent = stats->stat_OutXonSent;
! 5021:
! 5022: sc->stat_OutXoffSent = stats->stat_OutXoffSent;
! 5023:
! 5024: sc->stat_FlowControlDone = stats->stat_FlowControlDone;
! 5025:
! 5026: sc->stat_MacControlFramesReceived =
! 5027: stats->stat_MacControlFramesReceived;
! 5028:
! 5029: sc->stat_XoffStateEntered = stats->stat_XoffStateEntered;
! 5030:
! 5031: sc->stat_IfInFramesL2FilterDiscards =
! 5032: stats->stat_IfInFramesL2FilterDiscards;
! 5033:
! 5034: sc->stat_IfInRuleCheckerDiscards = stats->stat_IfInRuleCheckerDiscards;
! 5035:
! 5036: sc->stat_IfInFTQDiscards = stats->stat_IfInFTQDiscards;
! 5037:
! 5038: sc->stat_IfInMBUFDiscards = stats->stat_IfInMBUFDiscards;
! 5039:
! 5040: sc->stat_IfInRuleCheckerP4Hit = stats->stat_IfInRuleCheckerP4Hit;
! 5041:
! 5042: sc->stat_CatchupInRuleCheckerDiscards =
! 5043: stats->stat_CatchupInRuleCheckerDiscards;
! 5044:
! 5045: sc->stat_CatchupInFTQDiscards = stats->stat_CatchupInFTQDiscards;
! 5046:
! 5047: sc->stat_CatchupInMBUFDiscards = stats->stat_CatchupInMBUFDiscards;
! 5048:
! 5049: sc->stat_CatchupInRuleCheckerP4Hit =
! 5050: stats->stat_CatchupInRuleCheckerP4Hit;
! 5051:
! 5052: DBPRINT(sc, BNX_EXCESSIVE, "Exiting %s()\n", __FUNCTION__);
! 5053: }
! 5054:
! 5055: void
! 5056: bnx_tick(void *xsc)
! 5057: {
! 5058: struct bnx_softc *sc = xsc;
! 5059: struct ifnet *ifp = &sc->arpcom.ac_if;
! 5060: struct mii_data *mii = NULL;
! 5061: u_int32_t msg;
! 5062:
! 5063: /* Tell the firmware that the driver is still running. */
! 5064: #ifdef BNX_DEBUG
! 5065: msg = (u_int32_t)BNX_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE;
! 5066: #else
! 5067: msg = (u_int32_t)++sc->bnx_fw_drv_pulse_wr_seq;
! 5068: #endif
! 5069: REG_WR_IND(sc, sc->bnx_shmem_base + BNX_DRV_PULSE_MB, msg);
! 5070:
! 5071: /* Update the statistics from the hardware statistics block. */
! 5072: bnx_stats_update(sc);
! 5073:
! 5074: /* Schedule the next tick. */
! 5075: timeout_add(&sc->bnx_timeout, hz);
! 5076:
! 5077: /* If link is up already up then we're done. */
! 5078: if (sc->bnx_link)
! 5079: goto bnx_tick_exit;
! 5080:
! 5081: /* DRC - ToDo: Add SerDes support and check SerDes link here. */
! 5082:
! 5083: mii = &sc->bnx_mii;
! 5084: mii_tick(mii);
! 5085:
! 5086: /* Check if the link has come up. */
! 5087: if (!sc->bnx_link && mii->mii_media_status & IFM_ACTIVE &&
! 5088: IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
! 5089: sc->bnx_link++;
! 5090: /* Now that link is up, handle any outstanding TX traffic. */
! 5091: if (!IFQ_IS_EMPTY(&ifp->if_snd))
! 5092: bnx_start(ifp);
! 5093: }
! 5094:
! 5095: bnx_tick_exit:
! 5096: return;
! 5097: }
! 5098:
! 5099: /****************************************************************************/
! 5100: /* BNX Debug Routines */
! 5101: /****************************************************************************/
! 5102: #ifdef BNX_DEBUG
! 5103:
! 5104: /****************************************************************************/
! 5105: /* Prints out information about an mbuf. */
! 5106: /* */
! 5107: /* Returns: */
! 5108: /* Nothing. */
! 5109: /****************************************************************************/
! 5110: void
! 5111: bnx_dump_mbuf(struct bnx_softc *sc, struct mbuf *m)
! 5112: {
! 5113: struct mbuf *mp = m;
! 5114:
! 5115: if (m == NULL) {
! 5116: /* Index out of range. */
! 5117: printf("mbuf ptr is null!\n");
! 5118: return;
! 5119: }
! 5120:
! 5121: while (mp) {
! 5122: printf("mbuf: vaddr = %p, m_len = %d, m_flags = ",
! 5123: mp, mp->m_len);
! 5124:
! 5125: if (mp->m_flags & M_EXT)
! 5126: printf("M_EXT ");
! 5127: if (mp->m_flags & M_PKTHDR)
! 5128: printf("M_PKTHDR ");
! 5129: printf("\n");
! 5130:
! 5131: if (mp->m_flags & M_EXT)
! 5132: printf("- m_ext: vaddr = %p, ext_size = 0x%04X\n",
! 5133: mp, mp->m_ext.ext_size);
! 5134:
! 5135: mp = mp->m_next;
! 5136: }
! 5137: }
! 5138:
! 5139: /****************************************************************************/
! 5140: /* Prints out the mbufs in the TX mbuf chain. */
! 5141: /* */
! 5142: /* Returns: */
! 5143: /* Nothing. */
! 5144: /****************************************************************************/
! 5145: void
! 5146: bnx_dump_tx_mbuf_chain(struct bnx_softc *sc, int chain_prod, int count)
! 5147: {
! 5148: struct mbuf *m;
! 5149: int i;
! 5150:
! 5151: BNX_PRINTF(sc,
! 5152: "----------------------------"
! 5153: " tx mbuf data "
! 5154: "----------------------------\n");
! 5155:
! 5156: for (i = 0; i < count; i++) {
! 5157: m = sc->tx_mbuf_ptr[chain_prod];
! 5158: BNX_PRINTF(sc, "txmbuf[%d]\n", chain_prod);
! 5159: bnx_dump_mbuf(sc, m);
! 5160: chain_prod = TX_CHAIN_IDX(NEXT_TX_BD(chain_prod));
! 5161: }
! 5162:
! 5163: BNX_PRINTF(sc,
! 5164: "--------------------------------------------"
! 5165: "----------------------------\n");
! 5166: }
! 5167:
! 5168: /*
! 5169: * This routine prints the RX mbuf chain.
! 5170: */
! 5171: void
! 5172: bnx_dump_rx_mbuf_chain(struct bnx_softc *sc, int chain_prod, int count)
! 5173: {
! 5174: struct mbuf *m;
! 5175: int i;
! 5176:
! 5177: BNX_PRINTF(sc,
! 5178: "----------------------------"
! 5179: " rx mbuf data "
! 5180: "----------------------------\n");
! 5181:
! 5182: for (i = 0; i < count; i++) {
! 5183: m = sc->rx_mbuf_ptr[chain_prod];
! 5184: BNX_PRINTF(sc, "rxmbuf[0x%04X]\n", chain_prod);
! 5185: bnx_dump_mbuf(sc, m);
! 5186: chain_prod = RX_CHAIN_IDX(NEXT_RX_BD(chain_prod));
! 5187: }
! 5188:
! 5189:
! 5190: BNX_PRINTF(sc,
! 5191: "--------------------------------------------"
! 5192: "----------------------------\n");
! 5193: }
! 5194:
! 5195: void
! 5196: bnx_dump_txbd(struct bnx_softc *sc, int idx, struct tx_bd *txbd)
! 5197: {
! 5198: if (idx > MAX_TX_BD)
! 5199: /* Index out of range. */
! 5200: BNX_PRINTF(sc, "tx_bd[0x%04X]: Invalid tx_bd index!\n", idx);
! 5201: else if ((idx & USABLE_TX_BD_PER_PAGE) == USABLE_TX_BD_PER_PAGE)
! 5202: /* TX Chain page pointer. */
! 5203: BNX_PRINTF(sc, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, chain "
! 5204: "page pointer\n", idx, txbd->tx_bd_haddr_hi,
! 5205: txbd->tx_bd_haddr_lo);
! 5206: else
! 5207: /* Normal tx_bd entry. */
! 5208: BNX_PRINTF(sc, "tx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = "
! 5209: "0x%08X, vlan tag = 0x%4X, flags = 0x%08X\n", idx,
! 5210: txbd->tx_bd_haddr_hi, txbd->tx_bd_haddr_lo,
! 5211: txbd->tx_bd_mss_nbytes, txbd->tx_bd_vlan_tag,
! 5212: txbd->tx_bd_flags);
! 5213: }
! 5214:
! 5215: void
! 5216: bnx_dump_rxbd(struct bnx_softc *sc, int idx, struct rx_bd *rxbd)
! 5217: {
! 5218: if (idx > MAX_RX_BD)
! 5219: /* Index out of range. */
! 5220: BNX_PRINTF(sc, "rx_bd[0x%04X]: Invalid rx_bd index!\n", idx);
! 5221: else if ((idx & USABLE_RX_BD_PER_PAGE) == USABLE_RX_BD_PER_PAGE)
! 5222: /* TX Chain page pointer. */
! 5223: BNX_PRINTF(sc, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, chain page "
! 5224: "pointer\n", idx, rxbd->rx_bd_haddr_hi,
! 5225: rxbd->rx_bd_haddr_lo);
! 5226: else
! 5227: /* Normal tx_bd entry. */
! 5228: BNX_PRINTF(sc, "rx_bd[0x%04X]: haddr = 0x%08X:%08X, nbytes = "
! 5229: "0x%08X, flags = 0x%08X\n", idx,
! 5230: rxbd->rx_bd_haddr_hi, rxbd->rx_bd_haddr_lo,
! 5231: rxbd->rx_bd_len, rxbd->rx_bd_flags);
! 5232: }
! 5233:
! 5234: void
! 5235: bnx_dump_l2fhdr(struct bnx_softc *sc, int idx, struct l2_fhdr *l2fhdr)
! 5236: {
! 5237: BNX_PRINTF(sc, "l2_fhdr[0x%04X]: status = 0x%08X, "
! 5238: "pkt_len = 0x%04X, vlan = 0x%04x, ip_xsum = 0x%04X, "
! 5239: "tcp_udp_xsum = 0x%04X\n", idx,
! 5240: l2fhdr->l2_fhdr_status, l2fhdr->l2_fhdr_pkt_len,
! 5241: l2fhdr->l2_fhdr_vlan_tag, l2fhdr->l2_fhdr_ip_xsum,
! 5242: l2fhdr->l2_fhdr_tcp_udp_xsum);
! 5243: }
! 5244:
! 5245: /*
! 5246: * This routine prints the TX chain.
! 5247: */
! 5248: void
! 5249: bnx_dump_tx_chain(struct bnx_softc *sc, int tx_prod, int count)
! 5250: {
! 5251: struct tx_bd *txbd;
! 5252: int i;
! 5253:
! 5254: /* First some info about the tx_bd chain structure. */
! 5255: BNX_PRINTF(sc,
! 5256: "----------------------------"
! 5257: " tx_bd chain "
! 5258: "----------------------------\n");
! 5259:
! 5260: BNX_PRINTF(sc,
! 5261: "page size = 0x%08X, tx chain pages = 0x%08X\n",
! 5262: (u_int32_t)BCM_PAGE_SIZE, (u_int32_t) TX_PAGES);
! 5263:
! 5264: BNX_PRINTF(sc,
! 5265: "tx_bd per page = 0x%08X, usable tx_bd per page = 0x%08X\n",
! 5266: (u_int32_t)TOTAL_TX_BD_PER_PAGE, (u_int32_t)USABLE_TX_BD_PER_PAGE);
! 5267:
! 5268: BNX_PRINTF(sc, "total tx_bd = 0x%08X\n", (u_int32_t)TOTAL_TX_BD);
! 5269:
! 5270: BNX_PRINTF(sc, ""
! 5271: "-----------------------------"
! 5272: " tx_bd data "
! 5273: "-----------------------------\n");
! 5274:
! 5275: /* Now print out the tx_bd's themselves. */
! 5276: for (i = 0; i < count; i++) {
! 5277: txbd = &sc->tx_bd_chain[TX_PAGE(tx_prod)][TX_IDX(tx_prod)];
! 5278: bnx_dump_txbd(sc, tx_prod, txbd);
! 5279: tx_prod = TX_CHAIN_IDX(NEXT_TX_BD(tx_prod));
! 5280: }
! 5281:
! 5282: BNX_PRINTF(sc,
! 5283: "-----------------------------"
! 5284: "--------------"
! 5285: "-----------------------------\n");
! 5286: }
! 5287:
! 5288: /*
! 5289: * This routine prints the RX chain.
! 5290: */
! 5291: void
! 5292: bnx_dump_rx_chain(struct bnx_softc *sc, int rx_prod, int count)
! 5293: {
! 5294: struct rx_bd *rxbd;
! 5295: int i;
! 5296:
! 5297: /* First some info about the tx_bd chain structure. */
! 5298: BNX_PRINTF(sc,
! 5299: "----------------------------"
! 5300: " rx_bd chain "
! 5301: "----------------------------\n");
! 5302:
! 5303: BNX_PRINTF(sc, "----- RX_BD Chain -----\n");
! 5304:
! 5305: BNX_PRINTF(sc,
! 5306: "page size = 0x%08X, rx chain pages = 0x%08X\n",
! 5307: (u_int32_t)BCM_PAGE_SIZE, (u_int32_t)RX_PAGES);
! 5308:
! 5309: BNX_PRINTF(sc,
! 5310: "rx_bd per page = 0x%08X, usable rx_bd per page = 0x%08X\n",
! 5311: (u_int32_t)TOTAL_RX_BD_PER_PAGE, (u_int32_t)USABLE_RX_BD_PER_PAGE);
! 5312:
! 5313: BNX_PRINTF(sc, "total rx_bd = 0x%08X\n", (u_int32_t)TOTAL_RX_BD);
! 5314:
! 5315: BNX_PRINTF(sc,
! 5316: "----------------------------"
! 5317: " rx_bd data "
! 5318: "----------------------------\n");
! 5319:
! 5320: /* Now print out the rx_bd's themselves. */
! 5321: for (i = 0; i < count; i++) {
! 5322: rxbd = &sc->rx_bd_chain[RX_PAGE(rx_prod)][RX_IDX(rx_prod)];
! 5323: bnx_dump_rxbd(sc, rx_prod, rxbd);
! 5324: rx_prod = RX_CHAIN_IDX(NEXT_RX_BD(rx_prod));
! 5325: }
! 5326:
! 5327: BNX_PRINTF(sc,
! 5328: "----------------------------"
! 5329: "--------------"
! 5330: "----------------------------\n");
! 5331: }
! 5332:
! 5333: /*
! 5334: * This routine prints the status block.
! 5335: */
! 5336: void
! 5337: bnx_dump_status_block(struct bnx_softc *sc)
! 5338: {
! 5339: struct status_block *sblk;
! 5340:
! 5341: sblk = sc->status_block;
! 5342:
! 5343: BNX_PRINTF(sc, "----------------------------- Status Block "
! 5344: "-----------------------------\n");
! 5345:
! 5346: BNX_PRINTF(sc,
! 5347: "attn_bits = 0x%08X, attn_bits_ack = 0x%08X, index = 0x%04X\n",
! 5348: sblk->status_attn_bits, sblk->status_attn_bits_ack,
! 5349: sblk->status_idx);
! 5350:
! 5351: BNX_PRINTF(sc, "rx_cons0 = 0x%08X, tx_cons0 = 0x%08X\n",
! 5352: sblk->status_rx_quick_consumer_index0,
! 5353: sblk->status_tx_quick_consumer_index0);
! 5354:
! 5355: BNX_PRINTF(sc, "status_idx = 0x%04X\n", sblk->status_idx);
! 5356:
! 5357: /* Theses indices are not used for normal L2 drivers. */
! 5358: if (sblk->status_rx_quick_consumer_index1 ||
! 5359: sblk->status_tx_quick_consumer_index1)
! 5360: BNX_PRINTF(sc, "rx_cons1 = 0x%08X, tx_cons1 = 0x%08X\n",
! 5361: sblk->status_rx_quick_consumer_index1,
! 5362: sblk->status_tx_quick_consumer_index1);
! 5363:
! 5364: if (sblk->status_rx_quick_consumer_index2 ||
! 5365: sblk->status_tx_quick_consumer_index2)
! 5366: BNX_PRINTF(sc, "rx_cons2 = 0x%08X, tx_cons2 = 0x%08X\n",
! 5367: sblk->status_rx_quick_consumer_index2,
! 5368: sblk->status_tx_quick_consumer_index2);
! 5369:
! 5370: if (sblk->status_rx_quick_consumer_index3 ||
! 5371: sblk->status_tx_quick_consumer_index3)
! 5372: BNX_PRINTF(sc, "rx_cons3 = 0x%08X, tx_cons3 = 0x%08X\n",
! 5373: sblk->status_rx_quick_consumer_index3,
! 5374: sblk->status_tx_quick_consumer_index3);
! 5375:
! 5376: if (sblk->status_rx_quick_consumer_index4 ||
! 5377: sblk->status_rx_quick_consumer_index5)
! 5378: BNX_PRINTF(sc, "rx_cons4 = 0x%08X, rx_cons5 = 0x%08X\n",
! 5379: sblk->status_rx_quick_consumer_index4,
! 5380: sblk->status_rx_quick_consumer_index5);
! 5381:
! 5382: if (sblk->status_rx_quick_consumer_index6 ||
! 5383: sblk->status_rx_quick_consumer_index7)
! 5384: BNX_PRINTF(sc, "rx_cons6 = 0x%08X, rx_cons7 = 0x%08X\n",
! 5385: sblk->status_rx_quick_consumer_index6,
! 5386: sblk->status_rx_quick_consumer_index7);
! 5387:
! 5388: if (sblk->status_rx_quick_consumer_index8 ||
! 5389: sblk->status_rx_quick_consumer_index9)
! 5390: BNX_PRINTF(sc, "rx_cons8 = 0x%08X, rx_cons9 = 0x%08X\n",
! 5391: sblk->status_rx_quick_consumer_index8,
! 5392: sblk->status_rx_quick_consumer_index9);
! 5393:
! 5394: if (sblk->status_rx_quick_consumer_index10 ||
! 5395: sblk->status_rx_quick_consumer_index11)
! 5396: BNX_PRINTF(sc, "rx_cons10 = 0x%08X, rx_cons11 = 0x%08X\n",
! 5397: sblk->status_rx_quick_consumer_index10,
! 5398: sblk->status_rx_quick_consumer_index11);
! 5399:
! 5400: if (sblk->status_rx_quick_consumer_index12 ||
! 5401: sblk->status_rx_quick_consumer_index13)
! 5402: BNX_PRINTF(sc, "rx_cons12 = 0x%08X, rx_cons13 = 0x%08X\n",
! 5403: sblk->status_rx_quick_consumer_index12,
! 5404: sblk->status_rx_quick_consumer_index13);
! 5405:
! 5406: if (sblk->status_rx_quick_consumer_index14 ||
! 5407: sblk->status_rx_quick_consumer_index15)
! 5408: BNX_PRINTF(sc, "rx_cons14 = 0x%08X, rx_cons15 = 0x%08X\n",
! 5409: sblk->status_rx_quick_consumer_index14,
! 5410: sblk->status_rx_quick_consumer_index15);
! 5411:
! 5412: if (sblk->status_completion_producer_index ||
! 5413: sblk->status_cmd_consumer_index)
! 5414: BNX_PRINTF(sc, "com_prod = 0x%08X, cmd_cons = 0x%08X\n",
! 5415: sblk->status_completion_producer_index,
! 5416: sblk->status_cmd_consumer_index);
! 5417:
! 5418: BNX_PRINTF(sc, "-------------------------------------------"
! 5419: "-----------------------------\n");
! 5420: }
! 5421:
! 5422: /*
! 5423: * This routine prints the statistics block.
! 5424: */
! 5425: void
! 5426: bnx_dump_stats_block(struct bnx_softc *sc)
! 5427: {
! 5428: struct statistics_block *sblk;
! 5429:
! 5430: sblk = sc->stats_block;
! 5431:
! 5432: BNX_PRINTF(sc, ""
! 5433: "-----------------------------"
! 5434: " Stats Block "
! 5435: "-----------------------------\n");
! 5436:
! 5437: BNX_PRINTF(sc, "IfHcInOctets = 0x%08X:%08X, "
! 5438: "IfHcInBadOctets = 0x%08X:%08X\n",
! 5439: sblk->stat_IfHCInOctets_hi, sblk->stat_IfHCInOctets_lo,
! 5440: sblk->stat_IfHCInBadOctets_hi, sblk->stat_IfHCInBadOctets_lo);
! 5441:
! 5442: BNX_PRINTF(sc, "IfHcOutOctets = 0x%08X:%08X, "
! 5443: "IfHcOutBadOctets = 0x%08X:%08X\n",
! 5444: sblk->stat_IfHCOutOctets_hi, sblk->stat_IfHCOutOctets_lo,
! 5445: sblk->stat_IfHCOutBadOctets_hi, sblk->stat_IfHCOutBadOctets_lo);
! 5446:
! 5447: BNX_PRINTF(sc, "IfHcInUcastPkts = 0x%08X:%08X, "
! 5448: "IfHcInMulticastPkts = 0x%08X:%08X\n",
! 5449: sblk->stat_IfHCInUcastPkts_hi, sblk->stat_IfHCInUcastPkts_lo,
! 5450: sblk->stat_IfHCInMulticastPkts_hi,
! 5451: sblk->stat_IfHCInMulticastPkts_lo);
! 5452:
! 5453: BNX_PRINTF(sc, "IfHcInBroadcastPkts = 0x%08X:%08X, "
! 5454: "IfHcOutUcastPkts = 0x%08X:%08X\n",
! 5455: sblk->stat_IfHCInBroadcastPkts_hi,
! 5456: sblk->stat_IfHCInBroadcastPkts_lo,
! 5457: sblk->stat_IfHCOutUcastPkts_hi,
! 5458: sblk->stat_IfHCOutUcastPkts_lo);
! 5459:
! 5460: BNX_PRINTF(sc, "IfHcOutMulticastPkts = 0x%08X:%08X, "
! 5461: "IfHcOutBroadcastPkts = 0x%08X:%08X\n",
! 5462: sblk->stat_IfHCOutMulticastPkts_hi,
! 5463: sblk->stat_IfHCOutMulticastPkts_lo,
! 5464: sblk->stat_IfHCOutBroadcastPkts_hi,
! 5465: sblk->stat_IfHCOutBroadcastPkts_lo);
! 5466:
! 5467: if (sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors)
! 5468: BNX_PRINTF(sc, "0x%08X : "
! 5469: "emac_tx_stat_dot3statsinternalmactransmiterrors\n",
! 5470: sblk->stat_emac_tx_stat_dot3statsinternalmactransmiterrors);
! 5471:
! 5472: if (sblk->stat_Dot3StatsCarrierSenseErrors)
! 5473: BNX_PRINTF(sc, "0x%08X : Dot3StatsCarrierSenseErrors\n",
! 5474: sblk->stat_Dot3StatsCarrierSenseErrors);
! 5475:
! 5476: if (sblk->stat_Dot3StatsFCSErrors)
! 5477: BNX_PRINTF(sc, "0x%08X : Dot3StatsFCSErrors\n",
! 5478: sblk->stat_Dot3StatsFCSErrors);
! 5479:
! 5480: if (sblk->stat_Dot3StatsAlignmentErrors)
! 5481: BNX_PRINTF(sc, "0x%08X : Dot3StatsAlignmentErrors\n",
! 5482: sblk->stat_Dot3StatsAlignmentErrors);
! 5483:
! 5484: if (sblk->stat_Dot3StatsSingleCollisionFrames)
! 5485: BNX_PRINTF(sc, "0x%08X : Dot3StatsSingleCollisionFrames\n",
! 5486: sblk->stat_Dot3StatsSingleCollisionFrames);
! 5487:
! 5488: if (sblk->stat_Dot3StatsMultipleCollisionFrames)
! 5489: BNX_PRINTF(sc, "0x%08X : Dot3StatsMultipleCollisionFrames\n",
! 5490: sblk->stat_Dot3StatsMultipleCollisionFrames);
! 5491:
! 5492: if (sblk->stat_Dot3StatsDeferredTransmissions)
! 5493: BNX_PRINTF(sc, "0x%08X : Dot3StatsDeferredTransmissions\n",
! 5494: sblk->stat_Dot3StatsDeferredTransmissions);
! 5495:
! 5496: if (sblk->stat_Dot3StatsExcessiveCollisions)
! 5497: BNX_PRINTF(sc, "0x%08X : Dot3StatsExcessiveCollisions\n",
! 5498: sblk->stat_Dot3StatsExcessiveCollisions);
! 5499:
! 5500: if (sblk->stat_Dot3StatsLateCollisions)
! 5501: BNX_PRINTF(sc, "0x%08X : Dot3StatsLateCollisions\n",
! 5502: sblk->stat_Dot3StatsLateCollisions);
! 5503:
! 5504: if (sblk->stat_EtherStatsCollisions)
! 5505: BNX_PRINTF(sc, "0x%08X : EtherStatsCollisions\n",
! 5506: sblk->stat_EtherStatsCollisions);
! 5507:
! 5508: if (sblk->stat_EtherStatsFragments)
! 5509: BNX_PRINTF(sc, "0x%08X : EtherStatsFragments\n",
! 5510: sblk->stat_EtherStatsFragments);
! 5511:
! 5512: if (sblk->stat_EtherStatsJabbers)
! 5513: BNX_PRINTF(sc, "0x%08X : EtherStatsJabbers\n",
! 5514: sblk->stat_EtherStatsJabbers);
! 5515:
! 5516: if (sblk->stat_EtherStatsUndersizePkts)
! 5517: BNX_PRINTF(sc, "0x%08X : EtherStatsUndersizePkts\n",
! 5518: sblk->stat_EtherStatsUndersizePkts);
! 5519:
! 5520: if (sblk->stat_EtherStatsOverrsizePkts)
! 5521: BNX_PRINTF(sc, "0x%08X : EtherStatsOverrsizePkts\n",
! 5522: sblk->stat_EtherStatsOverrsizePkts);
! 5523:
! 5524: if (sblk->stat_EtherStatsPktsRx64Octets)
! 5525: BNX_PRINTF(sc, "0x%08X : EtherStatsPktsRx64Octets\n",
! 5526: sblk->stat_EtherStatsPktsRx64Octets);
! 5527:
! 5528: if (sblk->stat_EtherStatsPktsRx65Octetsto127Octets)
! 5529: BNX_PRINTF(sc, "0x%08X : EtherStatsPktsRx65Octetsto127Octets\n",
! 5530: sblk->stat_EtherStatsPktsRx65Octetsto127Octets);
! 5531:
! 5532: if (sblk->stat_EtherStatsPktsRx128Octetsto255Octets)
! 5533: BNX_PRINTF(sc, "0x%08X : "
! 5534: "EtherStatsPktsRx128Octetsto255Octets\n",
! 5535: sblk->stat_EtherStatsPktsRx128Octetsto255Octets);
! 5536:
! 5537: if (sblk->stat_EtherStatsPktsRx256Octetsto511Octets)
! 5538: BNX_PRINTF(sc, "0x%08X : "
! 5539: "EtherStatsPktsRx256Octetsto511Octets\n",
! 5540: sblk->stat_EtherStatsPktsRx256Octetsto511Octets);
! 5541:
! 5542: if (sblk->stat_EtherStatsPktsRx512Octetsto1023Octets)
! 5543: BNX_PRINTF(sc, "0x%08X : "
! 5544: "EtherStatsPktsRx512Octetsto1023Octets\n",
! 5545: sblk->stat_EtherStatsPktsRx512Octetsto1023Octets);
! 5546:
! 5547: if (sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets)
! 5548: BNX_PRINTF(sc, "0x%08X : "
! 5549: "EtherStatsPktsRx1024Octetsto1522Octets\n",
! 5550: sblk->stat_EtherStatsPktsRx1024Octetsto1522Octets);
! 5551:
! 5552: if (sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets)
! 5553: BNX_PRINTF(sc, "0x%08X : "
! 5554: "EtherStatsPktsRx1523Octetsto9022Octets\n",
! 5555: sblk->stat_EtherStatsPktsRx1523Octetsto9022Octets);
! 5556:
! 5557: if (sblk->stat_EtherStatsPktsTx64Octets)
! 5558: BNX_PRINTF(sc, "0x%08X : EtherStatsPktsTx64Octets\n",
! 5559: sblk->stat_EtherStatsPktsTx64Octets);
! 5560:
! 5561: if (sblk->stat_EtherStatsPktsTx65Octetsto127Octets)
! 5562: BNX_PRINTF(sc, "0x%08X : EtherStatsPktsTx65Octetsto127Octets\n",
! 5563: sblk->stat_EtherStatsPktsTx65Octetsto127Octets);
! 5564:
! 5565: if (sblk->stat_EtherStatsPktsTx128Octetsto255Octets)
! 5566: BNX_PRINTF(sc, "0x%08X : "
! 5567: "EtherStatsPktsTx128Octetsto255Octets\n",
! 5568: sblk->stat_EtherStatsPktsTx128Octetsto255Octets);
! 5569:
! 5570: if (sblk->stat_EtherStatsPktsTx256Octetsto511Octets)
! 5571: BNX_PRINTF(sc, "0x%08X : "
! 5572: "EtherStatsPktsTx256Octetsto511Octets\n",
! 5573: sblk->stat_EtherStatsPktsTx256Octetsto511Octets);
! 5574:
! 5575: if (sblk->stat_EtherStatsPktsTx512Octetsto1023Octets)
! 5576: BNX_PRINTF(sc, "0x%08X : "
! 5577: "EtherStatsPktsTx512Octetsto1023Octets\n",
! 5578: sblk->stat_EtherStatsPktsTx512Octetsto1023Octets);
! 5579:
! 5580: if (sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets)
! 5581: BNX_PRINTF(sc, "0x%08X : "
! 5582: "EtherStatsPktsTx1024Octetsto1522Octets\n",
! 5583: sblk->stat_EtherStatsPktsTx1024Octetsto1522Octets);
! 5584:
! 5585: if (sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets)
! 5586: BNX_PRINTF(sc, "0x%08X : "
! 5587: "EtherStatsPktsTx1523Octetsto9022Octets\n",
! 5588: sblk->stat_EtherStatsPktsTx1523Octetsto9022Octets);
! 5589:
! 5590: if (sblk->stat_XonPauseFramesReceived)
! 5591: BNX_PRINTF(sc, "0x%08X : XonPauseFramesReceived\n",
! 5592: sblk->stat_XonPauseFramesReceived);
! 5593:
! 5594: if (sblk->stat_XoffPauseFramesReceived)
! 5595: BNX_PRINTF(sc, "0x%08X : XoffPauseFramesReceived\n",
! 5596: sblk->stat_XoffPauseFramesReceived);
! 5597:
! 5598: if (sblk->stat_OutXonSent)
! 5599: BNX_PRINTF(sc, "0x%08X : OutXonSent\n",
! 5600: sblk->stat_OutXonSent);
! 5601:
! 5602: if (sblk->stat_OutXoffSent)
! 5603: BNX_PRINTF(sc, "0x%08X : OutXoffSent\n",
! 5604: sblk->stat_OutXoffSent);
! 5605:
! 5606: if (sblk->stat_FlowControlDone)
! 5607: BNX_PRINTF(sc, "0x%08X : FlowControlDone\n",
! 5608: sblk->stat_FlowControlDone);
! 5609:
! 5610: if (sblk->stat_MacControlFramesReceived)
! 5611: BNX_PRINTF(sc, "0x%08X : MacControlFramesReceived\n",
! 5612: sblk->stat_MacControlFramesReceived);
! 5613:
! 5614: if (sblk->stat_XoffStateEntered)
! 5615: BNX_PRINTF(sc, "0x%08X : XoffStateEntered\n",
! 5616: sblk->stat_XoffStateEntered);
! 5617:
! 5618: if (sblk->stat_IfInFramesL2FilterDiscards)
! 5619: BNX_PRINTF(sc, "0x%08X : IfInFramesL2FilterDiscards\n",
! 5620: sblk->stat_IfInFramesL2FilterDiscards);
! 5621:
! 5622: if (sblk->stat_IfInRuleCheckerDiscards)
! 5623: BNX_PRINTF(sc, "0x%08X : IfInRuleCheckerDiscards\n",
! 5624: sblk->stat_IfInRuleCheckerDiscards);
! 5625:
! 5626: if (sblk->stat_IfInFTQDiscards)
! 5627: BNX_PRINTF(sc, "0x%08X : IfInFTQDiscards\n",
! 5628: sblk->stat_IfInFTQDiscards);
! 5629:
! 5630: if (sblk->stat_IfInMBUFDiscards)
! 5631: BNX_PRINTF(sc, "0x%08X : IfInMBUFDiscards\n",
! 5632: sblk->stat_IfInMBUFDiscards);
! 5633:
! 5634: if (sblk->stat_IfInRuleCheckerP4Hit)
! 5635: BNX_PRINTF(sc, "0x%08X : IfInRuleCheckerP4Hit\n",
! 5636: sblk->stat_IfInRuleCheckerP4Hit);
! 5637:
! 5638: if (sblk->stat_CatchupInRuleCheckerDiscards)
! 5639: BNX_PRINTF(sc, "0x%08X : CatchupInRuleCheckerDiscards\n",
! 5640: sblk->stat_CatchupInRuleCheckerDiscards);
! 5641:
! 5642: if (sblk->stat_CatchupInFTQDiscards)
! 5643: BNX_PRINTF(sc, "0x%08X : CatchupInFTQDiscards\n",
! 5644: sblk->stat_CatchupInFTQDiscards);
! 5645:
! 5646: if (sblk->stat_CatchupInMBUFDiscards)
! 5647: BNX_PRINTF(sc, "0x%08X : CatchupInMBUFDiscards\n",
! 5648: sblk->stat_CatchupInMBUFDiscards);
! 5649:
! 5650: if (sblk->stat_CatchupInRuleCheckerP4Hit)
! 5651: BNX_PRINTF(sc, "0x%08X : CatchupInRuleCheckerP4Hit\n",
! 5652: sblk->stat_CatchupInRuleCheckerP4Hit);
! 5653:
! 5654: BNX_PRINTF(sc,
! 5655: "-----------------------------"
! 5656: "--------------"
! 5657: "-----------------------------\n");
! 5658: }
! 5659:
! 5660: void
! 5661: bnx_dump_driver_state(struct bnx_softc *sc)
! 5662: {
! 5663: BNX_PRINTF(sc,
! 5664: "-----------------------------"
! 5665: " Driver State "
! 5666: "-----------------------------\n");
! 5667:
! 5668: BNX_PRINTF(sc, "%p - (sc) driver softc structure virtual "
! 5669: "address\n", sc);
! 5670:
! 5671: BNX_PRINTF(sc, "%p - (sc->status_block) status block virtual address\n",
! 5672: sc->status_block);
! 5673:
! 5674: BNX_PRINTF(sc, "%p - (sc->stats_block) statistics block virtual "
! 5675: "address\n", sc->stats_block);
! 5676:
! 5677: BNX_PRINTF(sc, "%p - (sc->tx_bd_chain) tx_bd chain virtual "
! 5678: "adddress\n", sc->tx_bd_chain);
! 5679:
! 5680: BNX_PRINTF(sc, "%p - (sc->rx_bd_chain) rx_bd chain virtual address\n",
! 5681: sc->rx_bd_chain);
! 5682:
! 5683: BNX_PRINTF(sc, "%p - (sc->tx_mbuf_ptr) tx mbuf chain virtual address\n",
! 5684: sc->tx_mbuf_ptr);
! 5685:
! 5686: BNX_PRINTF(sc, "%p - (sc->rx_mbuf_ptr) rx mbuf chain virtual address\n",
! 5687: sc->rx_mbuf_ptr);
! 5688:
! 5689: BNX_PRINTF(sc,
! 5690: " 0x%08X - (sc->interrupts_generated) h/w intrs\n",
! 5691: sc->interrupts_generated);
! 5692:
! 5693: BNX_PRINTF(sc,
! 5694: " 0x%08X - (sc->rx_interrupts) rx interrupts handled\n",
! 5695: sc->rx_interrupts);
! 5696:
! 5697: BNX_PRINTF(sc,
! 5698: " 0x%08X - (sc->tx_interrupts) tx interrupts handled\n",
! 5699: sc->tx_interrupts);
! 5700:
! 5701: BNX_PRINTF(sc,
! 5702: " 0x%08X - (sc->last_status_idx) status block index\n",
! 5703: sc->last_status_idx);
! 5704:
! 5705: BNX_PRINTF(sc, " 0x%08X - (sc->tx_prod) tx producer index\n",
! 5706: sc->tx_prod);
! 5707:
! 5708: BNX_PRINTF(sc, " 0x%08X - (sc->tx_cons) tx consumer index\n",
! 5709: sc->tx_cons);
! 5710:
! 5711: BNX_PRINTF(sc,
! 5712: " 0x%08X - (sc->tx_prod_bseq) tx producer bseq index\n",
! 5713: sc->tx_prod_bseq);
! 5714:
! 5715: BNX_PRINTF(sc, " 0x%08X - (sc->rx_prod) rx producer index\n",
! 5716: sc->rx_prod);
! 5717:
! 5718: BNX_PRINTF(sc, " 0x%08X - (sc->rx_cons) rx consumer index\n",
! 5719: sc->rx_cons);
! 5720:
! 5721: BNX_PRINTF(sc,
! 5722: " 0x%08X - (sc->rx_prod_bseq) rx producer bseq index\n",
! 5723: sc->rx_prod_bseq);
! 5724:
! 5725: BNX_PRINTF(sc,
! 5726: " 0x%08X - (sc->rx_mbuf_alloc) rx mbufs allocated\n",
! 5727: sc->rx_mbuf_alloc);
! 5728:
! 5729: BNX_PRINTF(sc, " 0x%08X - (sc->free_rx_bd) free rx_bd's\n",
! 5730: sc->free_rx_bd);
! 5731:
! 5732: BNX_PRINTF(sc,
! 5733: "0x%08X/%08X - (sc->rx_low_watermark) rx low watermark\n",
! 5734: sc->rx_low_watermark, (u_int32_t) USABLE_RX_BD);
! 5735:
! 5736: BNX_PRINTF(sc,
! 5737: " 0x%08X - (sc->txmbuf_alloc) tx mbufs allocated\n",
! 5738: sc->tx_mbuf_alloc);
! 5739:
! 5740: BNX_PRINTF(sc,
! 5741: " 0x%08X - (sc->rx_mbuf_alloc) rx mbufs allocated\n",
! 5742: sc->rx_mbuf_alloc);
! 5743:
! 5744: BNX_PRINTF(sc, " 0x%08X - (sc->used_tx_bd) used tx_bd's\n",
! 5745: sc->used_tx_bd);
! 5746:
! 5747: BNX_PRINTF(sc, "0x%08X/%08X - (sc->tx_hi_watermark) tx hi watermark\n",
! 5748: sc->tx_hi_watermark, (u_int32_t) USABLE_TX_BD);
! 5749:
! 5750: BNX_PRINTF(sc,
! 5751: " 0x%08X - (sc->mbuf_alloc_failed) failed mbuf alloc\n",
! 5752: sc->mbuf_alloc_failed);
! 5753:
! 5754: BNX_PRINTF(sc, "-------------------------------------------"
! 5755: "-----------------------------\n");
! 5756: }
! 5757:
! 5758: void
! 5759: bnx_dump_hw_state(struct bnx_softc *sc)
! 5760: {
! 5761: u_int32_t val1;
! 5762: int i;
! 5763:
! 5764: BNX_PRINTF(sc,
! 5765: "----------------------------"
! 5766: " Hardware State "
! 5767: "----------------------------\n");
! 5768:
! 5769: BNX_PRINTF(sc, "0x%08X : bootcode version\n", sc->bnx_fw_ver);
! 5770:
! 5771: val1 = REG_RD(sc, BNX_MISC_ENABLE_STATUS_BITS);
! 5772: BNX_PRINTF(sc, "0x%08X : (0x%04X) misc_enable_status_bits\n",
! 5773: val1, BNX_MISC_ENABLE_STATUS_BITS);
! 5774:
! 5775: val1 = REG_RD(sc, BNX_DMA_STATUS);
! 5776: BNX_PRINTF(sc, "0x%08X : (0x%04X) dma_status\n", val1, BNX_DMA_STATUS);
! 5777:
! 5778: val1 = REG_RD(sc, BNX_CTX_STATUS);
! 5779: BNX_PRINTF(sc, "0x%08X : (0x%04X) ctx_status\n", val1, BNX_CTX_STATUS);
! 5780:
! 5781: val1 = REG_RD(sc, BNX_EMAC_STATUS);
! 5782: BNX_PRINTF(sc, "0x%08X : (0x%04X) emac_status\n", val1,
! 5783: BNX_EMAC_STATUS);
! 5784:
! 5785: val1 = REG_RD(sc, BNX_RPM_STATUS);
! 5786: BNX_PRINTF(sc, "0x%08X : (0x%04X) rpm_status\n", val1, BNX_RPM_STATUS);
! 5787:
! 5788: val1 = REG_RD(sc, BNX_TBDR_STATUS);
! 5789: BNX_PRINTF(sc, "0x%08X : (0x%04X) tbdr_status\n", val1,
! 5790: BNX_TBDR_STATUS);
! 5791:
! 5792: val1 = REG_RD(sc, BNX_TDMA_STATUS);
! 5793: BNX_PRINTF(sc, "0x%08X : (0x%04X) tdma_status\n", val1,
! 5794: BNX_TDMA_STATUS);
! 5795:
! 5796: val1 = REG_RD(sc, BNX_HC_STATUS);
! 5797: BNX_PRINTF(sc, "0x%08X : (0x%04X) hc_status\n", val1, BNX_HC_STATUS);
! 5798:
! 5799: BNX_PRINTF(sc,
! 5800: "----------------------------"
! 5801: "----------------"
! 5802: "----------------------------\n");
! 5803:
! 5804: BNX_PRINTF(sc,
! 5805: "----------------------------"
! 5806: " Register Dump "
! 5807: "----------------------------\n");
! 5808:
! 5809: for (i = 0x400; i < 0x8000; i += 0x10)
! 5810: BNX_PRINTF(sc, "0x%04X: 0x%08X 0x%08X 0x%08X 0x%08X\n",
! 5811: i, REG_RD(sc, i), REG_RD(sc, i + 0x4),
! 5812: REG_RD(sc, i + 0x8), REG_RD(sc, i + 0xC));
! 5813:
! 5814: BNX_PRINTF(sc,
! 5815: "----------------------------"
! 5816: "----------------"
! 5817: "----------------------------\n");
! 5818: }
! 5819:
! 5820: void
! 5821: bnx_breakpoint(struct bnx_softc *sc)
! 5822: {
! 5823: /* Unreachable code to shut the compiler up about unused functions. */
! 5824: if (0) {
! 5825: bnx_dump_txbd(sc, 0, NULL);
! 5826: bnx_dump_rxbd(sc, 0, NULL);
! 5827: bnx_dump_tx_mbuf_chain(sc, 0, USABLE_TX_BD);
! 5828: bnx_dump_rx_mbuf_chain(sc, 0, USABLE_RX_BD);
! 5829: bnx_dump_l2fhdr(sc, 0, NULL);
! 5830: bnx_dump_tx_chain(sc, 0, USABLE_TX_BD);
! 5831: bnx_dump_rx_chain(sc, 0, USABLE_RX_BD);
! 5832: bnx_dump_status_block(sc);
! 5833: bnx_dump_stats_block(sc);
! 5834: bnx_dump_driver_state(sc);
! 5835: bnx_dump_hw_state(sc);
! 5836: }
! 5837:
! 5838: bnx_dump_driver_state(sc);
! 5839: /* Print the important status block fields. */
! 5840: bnx_dump_status_block(sc);
! 5841:
! 5842: #if 0
! 5843: /* Call the debugger. */
! 5844: breakpoint();
! 5845: #endif
! 5846:
! 5847: return;
! 5848: }
! 5849: #endif
CVSweb