[BACK]Return to if_bnx.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

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