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