Annotation of qemu/roms/ipxe/src/drivers/net/bnx2.c, revision 1.1

1.1     ! root        1: /* bnx2.c: Broadcom NX2 network driver.
        !             2:  *
        !             3:  * Copyright (c) 2004, 2005, 2006 Broadcom Corporation
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify
        !             6:  * it under the terms of the GNU General Public License as published by
        !             7:  * the Free Software Foundation.
        !             8:  *
        !             9:  * Written by: Michael Chan  ([email protected])
        !            10:  *
        !            11:  * Etherboot port by Ryan Jackson ([email protected]), based on driver
        !            12:  * version 1.4.40 from linux 2.6.17
        !            13:  */
        !            14: 
        !            15: FILE_LICENCE ( GPL_ANY );
        !            16: 
        !            17: #include "etherboot.h"
        !            18: #include "nic.h"
        !            19: #include <errno.h>
        !            20: #include <ipxe/pci.h>
        !            21: #include <ipxe/ethernet.h>
        !            22: #include "string.h"
        !            23: #include <mii.h>
        !            24: #include "bnx2.h"
        !            25: #include "bnx2_fw.h"
        !            26: 
        !            27: #if 0
        !            28: /* Dummy defines for error handling */
        !            29: #define EBUSY  1
        !            30: #define ENODEV 2
        !            31: #define EINVAL 3
        !            32: #define ENOMEM 4
        !            33: #define EIO    5
        !            34: #endif
        !            35: 
        !            36: /* The bnx2 seems to be picky about the alignment of the receive buffers
        !            37:  * and possibly the status block.
        !            38:  */
        !            39: static struct bss {
        !            40:        struct tx_bd tx_desc_ring[TX_DESC_CNT];
        !            41:        struct rx_bd rx_desc_ring[RX_DESC_CNT];
        !            42:        unsigned char rx_buf[RX_BUF_CNT][RX_BUF_SIZE];
        !            43:        struct status_block status_blk;
        !            44:        struct statistics_block stats_blk;
        !            45: } bnx2_bss;
        !            46: 
        !            47: static struct bnx2 bnx2;
        !            48: 
        !            49: static struct flash_spec flash_table[] =
        !            50: {
        !            51:        /* Slow EEPROM */
        !            52:        {0x00000000, 0x40830380, 0x009f0081, 0xa184a053, 0xaf000400,
        !            53:         1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
        !            54:         SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
        !            55:         "EEPROM - slow"},
        !            56:        /* Expansion entry 0001 */
        !            57:        {0x08000002, 0x4b808201, 0x00050081, 0x03840253, 0xaf020406,
        !            58:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !            59:         SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
        !            60:         "Entry 0001"},
        !            61:        /* Saifun SA25F010 (non-buffered flash) */
        !            62:        /* strap, cfg1, & write1 need updates */
        !            63:        {0x04000001, 0x47808201, 0x00050081, 0x03840253, 0xaf020406,
        !            64:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !            65:         SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*2,
        !            66:         "Non-buffered flash (128kB)"},
        !            67:        /* Saifun SA25F020 (non-buffered flash) */
        !            68:        /* strap, cfg1, & write1 need updates */
        !            69:        {0x0c000003, 0x4f808201, 0x00050081, 0x03840253, 0xaf020406,
        !            70:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !            71:         SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE*4,
        !            72:         "Non-buffered flash (256kB)"},
        !            73:        /* Expansion entry 0100 */
        !            74:        {0x11000000, 0x53808201, 0x00050081, 0x03840253, 0xaf020406,
        !            75:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !            76:         SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
        !            77:         "Entry 0100"},
        !            78:        /* Entry 0101: ST M45PE10 (non-buffered flash, TetonII B0) */
        !            79:        {0x19000002, 0x5b808201, 0x000500db, 0x03840253, 0xaf020406,        
        !            80:         0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
        !            81:         ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*2,
        !            82:         "Entry 0101: ST M45PE10 (128kB non-bufferred)"},
        !            83:        /* Entry 0110: ST M45PE20 (non-buffered flash)*/
        !            84:        {0x15000001, 0x57808201, 0x000500db, 0x03840253, 0xaf020406,
        !            85:         0, ST_MICRO_FLASH_PAGE_BITS, ST_MICRO_FLASH_PAGE_SIZE,
        !            86:         ST_MICRO_FLASH_BYTE_ADDR_MASK, ST_MICRO_FLASH_BASE_TOTAL_SIZE*4,
        !            87:         "Entry 0110: ST M45PE20 (256kB non-bufferred)"},
        !            88:        /* Saifun SA25F005 (non-buffered flash) */
        !            89:        /* strap, cfg1, & write1 need updates */
        !            90:        {0x1d000003, 0x5f808201, 0x00050081, 0x03840253, 0xaf020406,
        !            91:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !            92:         SAIFUN_FLASH_BYTE_ADDR_MASK, SAIFUN_FLASH_BASE_TOTAL_SIZE,
        !            93:         "Non-buffered flash (64kB)"},
        !            94:        /* Fast EEPROM */
        !            95:        {0x22000000, 0x62808380, 0x009f0081, 0xa184a053, 0xaf000400,
        !            96:         1, SEEPROM_PAGE_BITS, SEEPROM_PAGE_SIZE,
        !            97:         SEEPROM_BYTE_ADDR_MASK, SEEPROM_TOTAL_SIZE,
        !            98:         "EEPROM - fast"},
        !            99:        /* Expansion entry 1001 */
        !           100:        {0x2a000002, 0x6b808201, 0x00050081, 0x03840253, 0xaf020406,
        !           101:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !           102:         SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
        !           103:         "Entry 1001"},
        !           104:        /* Expansion entry 1010 */
        !           105:        {0x26000001, 0x67808201, 0x00050081, 0x03840253, 0xaf020406,
        !           106:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !           107:         SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
        !           108:         "Entry 1010"},
        !           109:        /* ATMEL AT45DB011B (buffered flash) */
        !           110:        {0x2e000003, 0x6e808273, 0x00570081, 0x68848353, 0xaf000400,
        !           111:         1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
        !           112:         BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE,
        !           113:         "Buffered flash (128kB)"},
        !           114:        /* Expansion entry 1100 */
        !           115:        {0x33000000, 0x73808201, 0x00050081, 0x03840253, 0xaf020406,
        !           116:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !           117:         SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
        !           118:         "Entry 1100"},
        !           119:        /* Expansion entry 1101 */
        !           120:        {0x3b000002, 0x7b808201, 0x00050081, 0x03840253, 0xaf020406,
        !           121:         0, SAIFUN_FLASH_PAGE_BITS, SAIFUN_FLASH_PAGE_SIZE,
        !           122:         SAIFUN_FLASH_BYTE_ADDR_MASK, 0,
        !           123:         "Entry 1101"},
        !           124:        /* Ateml Expansion entry 1110 */
        !           125:        {0x37000001, 0x76808273, 0x00570081, 0x68848353, 0xaf000400,
        !           126:         1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
        !           127:         BUFFERED_FLASH_BYTE_ADDR_MASK, 0,
        !           128:         "Entry 1110 (Atmel)"},
        !           129:        /* ATMEL AT45DB021B (buffered flash) */
        !           130:        {0x3f000003, 0x7e808273, 0x00570081, 0x68848353, 0xaf000400,
        !           131:         1, BUFFERED_FLASH_PAGE_BITS, BUFFERED_FLASH_PAGE_SIZE,
        !           132:         BUFFERED_FLASH_BYTE_ADDR_MASK, BUFFERED_FLASH_TOTAL_SIZE*2,
        !           133:         "Buffered flash (256kB)"},
        !           134: };
        !           135: 
        !           136: static u32
        !           137: bnx2_reg_rd_ind(struct bnx2 *bp, u32 offset)
        !           138: {
        !           139:        REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
        !           140:        return (REG_RD(bp, BNX2_PCICFG_REG_WINDOW));
        !           141: }
        !           142: 
        !           143: static void
        !           144: bnx2_reg_wr_ind(struct bnx2 *bp, u32 offset, u32 val)
        !           145: {
        !           146:        REG_WR(bp, BNX2_PCICFG_REG_WINDOW_ADDRESS, offset);
        !           147:        REG_WR(bp, BNX2_PCICFG_REG_WINDOW, val);
        !           148: }
        !           149: 
        !           150: static void
        !           151: bnx2_ctx_wr(struct bnx2 *bp, u32 cid_addr, u32 offset, u32 val)
        !           152: {
        !           153:        offset += cid_addr;
        !           154:        REG_WR(bp, BNX2_CTX_DATA_ADR, offset);
        !           155:        REG_WR(bp, BNX2_CTX_DATA, val);
        !           156: }
        !           157: 
        !           158: static int
        !           159: bnx2_read_phy(struct bnx2 *bp, u32 reg, u32 *val)
        !           160: {
        !           161:        u32 val1;
        !           162:        int i, ret;
        !           163: 
        !           164:        if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
        !           165:                val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           166:                val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
        !           167: 
        !           168:                REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
        !           169:                REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           170: 
        !           171:                udelay(40);
        !           172:        }
        !           173: 
        !           174:        val1 = (bp->phy_addr << 21) | (reg << 16) |
        !           175:                BNX2_EMAC_MDIO_COMM_COMMAND_READ | BNX2_EMAC_MDIO_COMM_DISEXT |
        !           176:                BNX2_EMAC_MDIO_COMM_START_BUSY;
        !           177:        REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
        !           178: 
        !           179:        for (i = 0; i < 50; i++) {
        !           180:                udelay(10);
        !           181: 
        !           182:                val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
        !           183:                if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
        !           184:                        udelay(5);
        !           185: 
        !           186:                        val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
        !           187:                        val1 &= BNX2_EMAC_MDIO_COMM_DATA;
        !           188: 
        !           189:                        break;
        !           190:                }
        !           191:        }
        !           192: 
        !           193:        if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY) {
        !           194:                *val = 0x0;
        !           195:                ret = -EBUSY;
        !           196:        }
        !           197:        else {
        !           198:                *val = val1;
        !           199:                ret = 0;
        !           200:        }
        !           201: 
        !           202:        if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
        !           203:                val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           204:                val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
        !           205: 
        !           206:                REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
        !           207:                REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           208: 
        !           209:                udelay(40);
        !           210:        }
        !           211: 
        !           212:        return ret;
        !           213: }
        !           214: 
        !           215: static int
        !           216: bnx2_write_phy(struct bnx2 *bp, u32 reg, u32 val)
        !           217: {
        !           218:        u32 val1;
        !           219:        int i, ret;
        !           220: 
        !           221:        if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
        !           222:                val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           223:                val1 &= ~BNX2_EMAC_MDIO_MODE_AUTO_POLL;
        !           224: 
        !           225:                REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
        !           226:                REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           227: 
        !           228:                udelay(40);
        !           229:        }
        !           230: 
        !           231:        val1 = (bp->phy_addr << 21) | (reg << 16) | val |
        !           232:                BNX2_EMAC_MDIO_COMM_COMMAND_WRITE |
        !           233:                BNX2_EMAC_MDIO_COMM_START_BUSY | BNX2_EMAC_MDIO_COMM_DISEXT;
        !           234:        REG_WR(bp, BNX2_EMAC_MDIO_COMM, val1);
        !           235:     
        !           236:        for (i = 0; i < 50; i++) {
        !           237:                udelay(10);
        !           238: 
        !           239:                val1 = REG_RD(bp, BNX2_EMAC_MDIO_COMM);
        !           240:                if (!(val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)) {
        !           241:                        udelay(5);
        !           242:                        break;
        !           243:                }
        !           244:        }
        !           245: 
        !           246:        if (val1 & BNX2_EMAC_MDIO_COMM_START_BUSY)
        !           247:                ret = -EBUSY;
        !           248:        else
        !           249:                ret = 0;
        !           250: 
        !           251:        if (bp->phy_flags & PHY_INT_MODE_AUTO_POLLING_FLAG) {
        !           252:                val1 = REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           253:                val1 |= BNX2_EMAC_MDIO_MODE_AUTO_POLL;
        !           254: 
        !           255:                REG_WR(bp, BNX2_EMAC_MDIO_MODE, val1);
        !           256:                REG_RD(bp, BNX2_EMAC_MDIO_MODE);
        !           257: 
        !           258:                udelay(40);
        !           259:        }
        !           260: 
        !           261:        return ret;
        !           262: }
        !           263: 
        !           264: static void
        !           265: bnx2_disable_int(struct bnx2 *bp)
        !           266: {
        !           267:        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
        !           268:               BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
        !           269:        REG_RD(bp, BNX2_PCICFG_INT_ACK_CMD);
        !           270: 
        !           271: }
        !           272: 
        !           273: static int
        !           274: bnx2_alloc_mem(struct bnx2 *bp)
        !           275: {
        !           276:        bp->tx_desc_ring = bnx2_bss.tx_desc_ring;
        !           277:        bp->tx_desc_mapping = virt_to_bus(bp->tx_desc_ring);
        !           278: 
        !           279:        bp->rx_desc_ring = bnx2_bss.rx_desc_ring;
        !           280:        memset(bp->rx_desc_ring, 0, sizeof(struct rx_bd) * RX_DESC_CNT);
        !           281:        bp->rx_desc_mapping = virt_to_bus(bp->rx_desc_ring);
        !           282: 
        !           283:        memset(&bnx2_bss.status_blk, 0, sizeof(struct status_block));
        !           284:        bp->status_blk = &bnx2_bss.status_blk;
        !           285:        bp->status_blk_mapping = virt_to_bus(&bnx2_bss.status_blk);
        !           286: 
        !           287:        bp->stats_blk = &bnx2_bss.stats_blk;
        !           288:        memset(&bnx2_bss.stats_blk, 0, sizeof(struct statistics_block));
        !           289:        bp->stats_blk_mapping = virt_to_bus(&bnx2_bss.stats_blk);
        !           290: 
        !           291:        return 0;
        !           292: }
        !           293: 
        !           294: static void
        !           295: bnx2_report_fw_link(struct bnx2 *bp)
        !           296: {
        !           297:        u32 fw_link_status = 0;
        !           298: 
        !           299:        if (bp->link_up) {
        !           300:                u32 bmsr;
        !           301: 
        !           302:                switch (bp->line_speed) {
        !           303:                case SPEED_10:
        !           304:                        if (bp->duplex == DUPLEX_HALF)
        !           305:                                fw_link_status = BNX2_LINK_STATUS_10HALF;
        !           306:                        else
        !           307:                                fw_link_status = BNX2_LINK_STATUS_10FULL;
        !           308:                        break;
        !           309:                case SPEED_100:
        !           310:                        if (bp->duplex == DUPLEX_HALF)
        !           311:                                fw_link_status = BNX2_LINK_STATUS_100HALF;
        !           312:                        else
        !           313:                                fw_link_status = BNX2_LINK_STATUS_100FULL;
        !           314:                        break;
        !           315:                case SPEED_1000:
        !           316:                        if (bp->duplex == DUPLEX_HALF)
        !           317:                                fw_link_status = BNX2_LINK_STATUS_1000HALF;
        !           318:                        else
        !           319:                                fw_link_status = BNX2_LINK_STATUS_1000FULL;
        !           320:                        break;
        !           321:                case SPEED_2500:
        !           322:                        if (bp->duplex == DUPLEX_HALF)
        !           323:                                fw_link_status = BNX2_LINK_STATUS_2500HALF;
        !           324:                        else
        !           325:                                fw_link_status = BNX2_LINK_STATUS_2500FULL;
        !           326:                        break;
        !           327:                }
        !           328: 
        !           329:                fw_link_status |= BNX2_LINK_STATUS_LINK_UP;
        !           330: 
        !           331:                if (bp->autoneg) {
        !           332:                        fw_link_status |= BNX2_LINK_STATUS_AN_ENABLED;
        !           333: 
        !           334:                        bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           335:                        bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           336: 
        !           337:                        if (!(bmsr & BMSR_ANEGCOMPLETE) ||
        !           338:                            bp->phy_flags & PHY_PARALLEL_DETECT_FLAG)
        !           339:                                fw_link_status |= BNX2_LINK_STATUS_PARALLEL_DET;
        !           340:                        else
        !           341:                                fw_link_status |= BNX2_LINK_STATUS_AN_COMPLETE;
        !           342:                }
        !           343:        }
        !           344:        else
        !           345:                fw_link_status = BNX2_LINK_STATUS_LINK_DOWN;
        !           346: 
        !           347:        REG_WR_IND(bp, bp->shmem_base + BNX2_LINK_STATUS, fw_link_status);
        !           348: }
        !           349: 
        !           350: static void
        !           351: bnx2_report_link(struct bnx2 *bp)
        !           352: {
        !           353:        if (bp->link_up) {
        !           354:                printf("NIC Link is Up, ");
        !           355: 
        !           356:                printf("%d Mbps ", bp->line_speed);
        !           357: 
        !           358:                if (bp->duplex == DUPLEX_FULL)
        !           359:                        printf("full duplex");
        !           360:                else
        !           361:                        printf("half duplex");
        !           362: 
        !           363:                if (bp->flow_ctrl) {
        !           364:                        if (bp->flow_ctrl & FLOW_CTRL_RX) {
        !           365:                                printf(", receive ");
        !           366:                                if (bp->flow_ctrl & FLOW_CTRL_TX)
        !           367:                                        printf("& transmit ");
        !           368:                        }
        !           369:                        else {
        !           370:                                printf(", transmit ");
        !           371:                        }
        !           372:                        printf("flow control ON");
        !           373:                }
        !           374:                printf("\n");
        !           375:        }
        !           376:        else {
        !           377:                printf("NIC Link is Down\n");
        !           378:        }
        !           379: 
        !           380:        bnx2_report_fw_link(bp);
        !           381: }
        !           382: 
        !           383: static void
        !           384: bnx2_resolve_flow_ctrl(struct bnx2 *bp)
        !           385: {
        !           386:        u32 local_adv, remote_adv;
        !           387: 
        !           388:        bp->flow_ctrl = 0;
        !           389:        if ((bp->autoneg & (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) != 
        !           390:                (AUTONEG_SPEED | AUTONEG_FLOW_CTRL)) {
        !           391: 
        !           392:                if (bp->duplex == DUPLEX_FULL) {
        !           393:                        bp->flow_ctrl = bp->req_flow_ctrl;
        !           394:                }
        !           395:                return;
        !           396:        }
        !           397: 
        !           398:        if (bp->duplex != DUPLEX_FULL) {
        !           399:                return;
        !           400:        }
        !           401: 
        !           402:        if ((bp->phy_flags & PHY_SERDES_FLAG) &&
        !           403:            (CHIP_NUM(bp) == CHIP_NUM_5708)) {
        !           404:                u32 val;
        !           405: 
        !           406:                bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
        !           407:                if (val & BCM5708S_1000X_STAT1_TX_PAUSE)
        !           408:                        bp->flow_ctrl |= FLOW_CTRL_TX;
        !           409:                if (val & BCM5708S_1000X_STAT1_RX_PAUSE)
        !           410:                        bp->flow_ctrl |= FLOW_CTRL_RX;
        !           411:                return;
        !           412:        }
        !           413: 
        !           414:        bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
        !           415:        bnx2_read_phy(bp, MII_LPA, &remote_adv);
        !           416: 
        !           417:        if (bp->phy_flags & PHY_SERDES_FLAG) {
        !           418:                u32 new_local_adv = 0;
        !           419:                u32 new_remote_adv = 0;
        !           420: 
        !           421:                if (local_adv & ADVERTISE_1000XPAUSE)
        !           422:                        new_local_adv |= ADVERTISE_PAUSE_CAP;
        !           423:                if (local_adv & ADVERTISE_1000XPSE_ASYM)
        !           424:                        new_local_adv |= ADVERTISE_PAUSE_ASYM;
        !           425:                if (remote_adv & ADVERTISE_1000XPAUSE)
        !           426:                        new_remote_adv |= ADVERTISE_PAUSE_CAP;
        !           427:                if (remote_adv & ADVERTISE_1000XPSE_ASYM)
        !           428:                        new_remote_adv |= ADVERTISE_PAUSE_ASYM;
        !           429: 
        !           430:                local_adv = new_local_adv;
        !           431:                remote_adv = new_remote_adv;
        !           432:        }
        !           433: 
        !           434:        /* See Table 28B-3 of 802.3ab-1999 spec. */
        !           435:        if (local_adv & ADVERTISE_PAUSE_CAP) {
        !           436:                if(local_adv & ADVERTISE_PAUSE_ASYM) {
        !           437:                        if (remote_adv & ADVERTISE_PAUSE_CAP) {
        !           438:                                bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
        !           439:                        }
        !           440:                        else if (remote_adv & ADVERTISE_PAUSE_ASYM) {
        !           441:                                bp->flow_ctrl = FLOW_CTRL_RX;
        !           442:                        }
        !           443:                }
        !           444:                else {
        !           445:                        if (remote_adv & ADVERTISE_PAUSE_CAP) {
        !           446:                                bp->flow_ctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
        !           447:                        }
        !           448:                }
        !           449:        }
        !           450:        else if (local_adv & ADVERTISE_PAUSE_ASYM) {
        !           451:                if ((remote_adv & ADVERTISE_PAUSE_CAP) &&
        !           452:                        (remote_adv & ADVERTISE_PAUSE_ASYM)) {
        !           453: 
        !           454:                        bp->flow_ctrl = FLOW_CTRL_TX;
        !           455:                }
        !           456:        }
        !           457: }
        !           458: 
        !           459: static int
        !           460: bnx2_5708s_linkup(struct bnx2 *bp)
        !           461: {
        !           462:        u32 val;
        !           463: 
        !           464:        bp->link_up = 1;
        !           465:        bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val);
        !           466:        switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) {
        !           467:                case BCM5708S_1000X_STAT1_SPEED_10:
        !           468:                        bp->line_speed = SPEED_10;
        !           469:                        break;
        !           470:                case BCM5708S_1000X_STAT1_SPEED_100:
        !           471:                        bp->line_speed = SPEED_100;
        !           472:                        break;
        !           473:                case BCM5708S_1000X_STAT1_SPEED_1G:
        !           474:                        bp->line_speed = SPEED_1000;
        !           475:                        break;
        !           476:                case BCM5708S_1000X_STAT1_SPEED_2G5:
        !           477:                        bp->line_speed = SPEED_2500;
        !           478:                        break;
        !           479:        }
        !           480:        if (val & BCM5708S_1000X_STAT1_FD)
        !           481:                bp->duplex = DUPLEX_FULL;
        !           482:        else
        !           483:                bp->duplex = DUPLEX_HALF;
        !           484: 
        !           485:        return 0;
        !           486: }
        !           487: 
        !           488: static int
        !           489: bnx2_5706s_linkup(struct bnx2 *bp)
        !           490: {
        !           491:        u32 bmcr, local_adv, remote_adv, common;
        !           492: 
        !           493:        bp->link_up = 1;
        !           494:        bp->line_speed = SPEED_1000;
        !           495: 
        !           496:        bnx2_read_phy(bp, MII_BMCR, &bmcr);
        !           497:        if (bmcr & BMCR_FULLDPLX) {
        !           498:                bp->duplex = DUPLEX_FULL;
        !           499:        }
        !           500:        else {
        !           501:                bp->duplex = DUPLEX_HALF;
        !           502:        }
        !           503: 
        !           504:        if (!(bmcr & BMCR_ANENABLE)) {
        !           505:                return 0;
        !           506:        }
        !           507: 
        !           508:        bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
        !           509:        bnx2_read_phy(bp, MII_LPA, &remote_adv);
        !           510: 
        !           511:        common = local_adv & remote_adv;
        !           512:        if (common & (ADVERTISE_1000XHALF | ADVERTISE_1000XFULL)) {
        !           513: 
        !           514:                if (common & ADVERTISE_1000XFULL) {
        !           515:                        bp->duplex = DUPLEX_FULL;
        !           516:                }
        !           517:                else {
        !           518:                        bp->duplex = DUPLEX_HALF;
        !           519:                }
        !           520:        }
        !           521: 
        !           522:        return 0;
        !           523: }
        !           524: 
        !           525: static int
        !           526: bnx2_copper_linkup(struct bnx2 *bp)
        !           527: {
        !           528:        u32 bmcr;
        !           529: 
        !           530:        bnx2_read_phy(bp, MII_BMCR, &bmcr);
        !           531:        if (bmcr & BMCR_ANENABLE) {
        !           532:                u32 local_adv, remote_adv, common;
        !           533: 
        !           534:                bnx2_read_phy(bp, MII_CTRL1000, &local_adv);
        !           535:                bnx2_read_phy(bp, MII_STAT1000, &remote_adv);
        !           536: 
        !           537:                common = local_adv & (remote_adv >> 2);
        !           538:                if (common & ADVERTISE_1000FULL) {
        !           539:                        bp->line_speed = SPEED_1000;
        !           540:                        bp->duplex = DUPLEX_FULL;
        !           541:                }
        !           542:                else if (common & ADVERTISE_1000HALF) {
        !           543:                        bp->line_speed = SPEED_1000;
        !           544:                        bp->duplex = DUPLEX_HALF;
        !           545:                }
        !           546:                else {
        !           547:                        bnx2_read_phy(bp, MII_ADVERTISE, &local_adv);
        !           548:                        bnx2_read_phy(bp, MII_LPA, &remote_adv);
        !           549: 
        !           550:                        common = local_adv & remote_adv;
        !           551:                        if (common & ADVERTISE_100FULL) {
        !           552:                                bp->line_speed = SPEED_100;
        !           553:                                bp->duplex = DUPLEX_FULL;
        !           554:                        }
        !           555:                        else if (common & ADVERTISE_100HALF) {
        !           556:                                bp->line_speed = SPEED_100;
        !           557:                                bp->duplex = DUPLEX_HALF;
        !           558:                        }
        !           559:                        else if (common & ADVERTISE_10FULL) {
        !           560:                                bp->line_speed = SPEED_10;
        !           561:                                bp->duplex = DUPLEX_FULL;
        !           562:                        }
        !           563:                        else if (common & ADVERTISE_10HALF) {
        !           564:                                bp->line_speed = SPEED_10;
        !           565:                                bp->duplex = DUPLEX_HALF;
        !           566:                        }
        !           567:                        else {
        !           568:                                bp->line_speed = 0;
        !           569:                                bp->link_up = 0;
        !           570:                        }
        !           571:                }
        !           572:        }
        !           573:        else {
        !           574:                if (bmcr & BMCR_SPEED100) {
        !           575:                        bp->line_speed = SPEED_100;
        !           576:                }
        !           577:                else {
        !           578:                        bp->line_speed = SPEED_10;
        !           579:                }
        !           580:                if (bmcr & BMCR_FULLDPLX) {
        !           581:                        bp->duplex = DUPLEX_FULL;
        !           582:                }
        !           583:                else {
        !           584:                        bp->duplex = DUPLEX_HALF;
        !           585:                }
        !           586:        }
        !           587: 
        !           588:        return 0;
        !           589: }
        !           590: 
        !           591: static int
        !           592: bnx2_set_mac_link(struct bnx2 *bp)
        !           593: {
        !           594:        u32 val;
        !           595: 
        !           596:        REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x2620);
        !           597:        if (bp->link_up && (bp->line_speed == SPEED_1000) &&
        !           598:                (bp->duplex == DUPLEX_HALF)) {
        !           599:                REG_WR(bp, BNX2_EMAC_TX_LENGTHS, 0x26ff);
        !           600:        }
        !           601: 
        !           602:        /* Configure the EMAC mode register. */
        !           603:        val = REG_RD(bp, BNX2_EMAC_MODE);
        !           604: 
        !           605:        val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX |
        !           606:                BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK |
        !           607:                BNX2_EMAC_MODE_25G);
        !           608: 
        !           609:        if (bp->link_up) {
        !           610:                switch (bp->line_speed) {
        !           611:                        case SPEED_10:
        !           612:                                if (CHIP_NUM(bp) == CHIP_NUM_5708) {
        !           613:                                        val |= BNX2_EMAC_MODE_PORT_MII_10;
        !           614:                                        break;
        !           615:                                }
        !           616:                                /* fall through */
        !           617:                        case SPEED_100:
        !           618:                                val |= BNX2_EMAC_MODE_PORT_MII;
        !           619:                                break;
        !           620:                        case SPEED_2500:
        !           621:                                val |= BNX2_EMAC_MODE_25G;
        !           622:                                /* fall through */
        !           623:                        case SPEED_1000:
        !           624:                                val |= BNX2_EMAC_MODE_PORT_GMII;
        !           625:                                break;
        !           626:                }
        !           627:        }
        !           628:        else {
        !           629:                val |= BNX2_EMAC_MODE_PORT_GMII;
        !           630:        }
        !           631: 
        !           632:        /* Set the MAC to operate in the appropriate duplex mode. */
        !           633:        if (bp->duplex == DUPLEX_HALF)
        !           634:                val |= BNX2_EMAC_MODE_HALF_DUPLEX;
        !           635:        REG_WR(bp, BNX2_EMAC_MODE, val);
        !           636: 
        !           637:        /* Enable/disable rx PAUSE. */
        !           638:        bp->rx_mode &= ~BNX2_EMAC_RX_MODE_FLOW_EN;
        !           639: 
        !           640:        if (bp->flow_ctrl & FLOW_CTRL_RX)
        !           641:                bp->rx_mode |= BNX2_EMAC_RX_MODE_FLOW_EN;
        !           642:        REG_WR(bp, BNX2_EMAC_RX_MODE, bp->rx_mode);
        !           643: 
        !           644:        /* Enable/disable tx PAUSE. */
        !           645:        val = REG_RD(bp, BNX2_EMAC_TX_MODE);
        !           646:        val &= ~BNX2_EMAC_TX_MODE_FLOW_EN;
        !           647: 
        !           648:        if (bp->flow_ctrl & FLOW_CTRL_TX)
        !           649:                val |= BNX2_EMAC_TX_MODE_FLOW_EN;
        !           650:        REG_WR(bp, BNX2_EMAC_TX_MODE, val);
        !           651: 
        !           652:        /* Acknowledge the interrupt. */
        !           653:        REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
        !           654: 
        !           655:        return 0;
        !           656: }
        !           657: 
        !           658: static int
        !           659: bnx2_set_link(struct bnx2 *bp)
        !           660: {
        !           661:        u32 bmsr;
        !           662:        u8 link_up;
        !           663: 
        !           664:        if (bp->loopback == MAC_LOOPBACK) {
        !           665:                bp->link_up = 1;
        !           666:                return 0;
        !           667:        }
        !           668: 
        !           669:        link_up = bp->link_up;
        !           670: 
        !           671:        bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           672:        bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           673: 
        !           674:        if ((bp->phy_flags & PHY_SERDES_FLAG) &&
        !           675:            (CHIP_NUM(bp) == CHIP_NUM_5706)) {
        !           676:                u32 val;
        !           677: 
        !           678:                val = REG_RD(bp, BNX2_EMAC_STATUS);
        !           679:                if (val & BNX2_EMAC_STATUS_LINK)
        !           680:                        bmsr |= BMSR_LSTATUS;
        !           681:                else
        !           682:                        bmsr &= ~BMSR_LSTATUS;
        !           683:        }
        !           684: 
        !           685:        if (bmsr & BMSR_LSTATUS) {
        !           686:                bp->link_up = 1;
        !           687: 
        !           688:                if (bp->phy_flags & PHY_SERDES_FLAG) {
        !           689:                        if (CHIP_NUM(bp) == CHIP_NUM_5706)
        !           690:                                bnx2_5706s_linkup(bp);
        !           691:                        else if (CHIP_NUM(bp) == CHIP_NUM_5708)
        !           692:                                bnx2_5708s_linkup(bp);
        !           693:                }
        !           694:                else {
        !           695:                        bnx2_copper_linkup(bp);
        !           696:                }
        !           697:                bnx2_resolve_flow_ctrl(bp);
        !           698:        }
        !           699:        else {
        !           700:                if ((bp->phy_flags & PHY_SERDES_FLAG) &&
        !           701:                        (bp->autoneg & AUTONEG_SPEED)) {
        !           702: 
        !           703:                        u32 bmcr;
        !           704: 
        !           705:                        bnx2_read_phy(bp, MII_BMCR, &bmcr);
        !           706:                        if (!(bmcr & BMCR_ANENABLE)) {
        !           707:                                bnx2_write_phy(bp, MII_BMCR, bmcr |
        !           708:                                        BMCR_ANENABLE);
        !           709:                        }
        !           710:                }
        !           711:                bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
        !           712:                bp->link_up = 0;
        !           713:        }
        !           714: 
        !           715:        if (bp->link_up != link_up) {
        !           716:                bnx2_report_link(bp);
        !           717:        }
        !           718: 
        !           719:        bnx2_set_mac_link(bp);
        !           720: 
        !           721:        return 0;
        !           722: }
        !           723: 
        !           724: static int
        !           725: bnx2_reset_phy(struct bnx2 *bp)
        !           726: {
        !           727:        int i;
        !           728:        u32 reg;
        !           729: 
        !           730:         bnx2_write_phy(bp, MII_BMCR, BMCR_RESET);
        !           731: 
        !           732: #define PHY_RESET_MAX_WAIT 100
        !           733:        for (i = 0; i < PHY_RESET_MAX_WAIT; i++) {
        !           734:                udelay(10);
        !           735: 
        !           736:                bnx2_read_phy(bp, MII_BMCR, &reg);
        !           737:                if (!(reg & BMCR_RESET)) {
        !           738:                        udelay(20);
        !           739:                        break;
        !           740:                }
        !           741:        }
        !           742:        if (i == PHY_RESET_MAX_WAIT) {
        !           743:                return -EBUSY;
        !           744:        }
        !           745:        return 0;
        !           746: }
        !           747: 
        !           748: static u32
        !           749: bnx2_phy_get_pause_adv(struct bnx2 *bp)
        !           750: {
        !           751:        u32 adv = 0;
        !           752: 
        !           753:        if ((bp->req_flow_ctrl & (FLOW_CTRL_RX | FLOW_CTRL_TX)) ==
        !           754:                (FLOW_CTRL_RX | FLOW_CTRL_TX)) {
        !           755: 
        !           756:                if (bp->phy_flags & PHY_SERDES_FLAG) {
        !           757:                        adv = ADVERTISE_1000XPAUSE;
        !           758:                }
        !           759:                else {
        !           760:                        adv = ADVERTISE_PAUSE_CAP;
        !           761:                }
        !           762:        }
        !           763:        else if (bp->req_flow_ctrl & FLOW_CTRL_TX) {
        !           764:                if (bp->phy_flags & PHY_SERDES_FLAG) {
        !           765:                        adv = ADVERTISE_1000XPSE_ASYM;
        !           766:                }
        !           767:                else {
        !           768:                        adv = ADVERTISE_PAUSE_ASYM;
        !           769:                }
        !           770:        }
        !           771:        else if (bp->req_flow_ctrl & FLOW_CTRL_RX) {
        !           772:                if (bp->phy_flags & PHY_SERDES_FLAG) {
        !           773:                        adv = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
        !           774:                }
        !           775:                else {
        !           776:                        adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
        !           777:                }
        !           778:        }
        !           779:        return adv;
        !           780: }
        !           781: 
        !           782: static int
        !           783: bnx2_setup_serdes_phy(struct bnx2 *bp)
        !           784: {
        !           785:        u32 adv, bmcr, up1;
        !           786:        u32 new_adv = 0;
        !           787: 
        !           788:        if (!(bp->autoneg & AUTONEG_SPEED)) {
        !           789:                u32 new_bmcr;
        !           790:                int force_link_down = 0;
        !           791: 
        !           792:                if (CHIP_NUM(bp) == CHIP_NUM_5708) {
        !           793:                        bnx2_read_phy(bp, BCM5708S_UP1, &up1);
        !           794:                        if (up1 & BCM5708S_UP1_2G5) {
        !           795:                                up1 &= ~BCM5708S_UP1_2G5;
        !           796:                                bnx2_write_phy(bp, BCM5708S_UP1, up1);
        !           797:                                force_link_down = 1;
        !           798:                        }
        !           799:                }
        !           800: 
        !           801:                bnx2_read_phy(bp, MII_ADVERTISE, &adv);
        !           802:                adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF);
        !           803: 
        !           804:                bnx2_read_phy(bp, MII_BMCR, &bmcr);
        !           805:                new_bmcr = bmcr & ~BMCR_ANENABLE;
        !           806:                new_bmcr |= BMCR_SPEED1000;
        !           807:                if (bp->req_duplex == DUPLEX_FULL) {
        !           808:                        adv |= ADVERTISE_1000XFULL;
        !           809:                        new_bmcr |= BMCR_FULLDPLX;
        !           810:                }
        !           811:                else {
        !           812:                        adv |= ADVERTISE_1000XHALF;
        !           813:                        new_bmcr &= ~BMCR_FULLDPLX;
        !           814:                }
        !           815:                if ((new_bmcr != bmcr) || (force_link_down)) {
        !           816:                        /* Force a link down visible on the other side */
        !           817:                        if (bp->link_up) {
        !           818:                                bnx2_write_phy(bp, MII_ADVERTISE, adv &
        !           819:                                               ~(ADVERTISE_1000XFULL |
        !           820:                                                 ADVERTISE_1000XHALF));
        !           821:                                bnx2_write_phy(bp, MII_BMCR, bmcr |
        !           822:                                        BMCR_ANRESTART | BMCR_ANENABLE);
        !           823: 
        !           824:                                bp->link_up = 0;
        !           825:                                bnx2_write_phy(bp, MII_BMCR, new_bmcr);
        !           826:                        }
        !           827:                        bnx2_write_phy(bp, MII_ADVERTISE, adv);
        !           828:                        bnx2_write_phy(bp, MII_BMCR, new_bmcr);
        !           829:                }
        !           830:                return 0;
        !           831:        }
        !           832: 
        !           833:        if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
        !           834:                bnx2_read_phy(bp, BCM5708S_UP1, &up1);
        !           835:                up1 |= BCM5708S_UP1_2G5;
        !           836:                bnx2_write_phy(bp, BCM5708S_UP1, up1);
        !           837:        }
        !           838: 
        !           839:        if (bp->advertising & ADVERTISED_1000baseT_Full)
        !           840:                new_adv |= ADVERTISE_1000XFULL;
        !           841: 
        !           842:        new_adv |= bnx2_phy_get_pause_adv(bp);
        !           843: 
        !           844:        bnx2_read_phy(bp, MII_ADVERTISE, &adv);
        !           845:        bnx2_read_phy(bp, MII_BMCR, &bmcr);
        !           846: 
        !           847:        bp->serdes_an_pending = 0;
        !           848:        if ((adv != new_adv) || ((bmcr & BMCR_ANENABLE) == 0)) {
        !           849:                /* Force a link down visible on the other side */
        !           850:                if (bp->link_up) {
        !           851:                        int i;
        !           852: 
        !           853:                        bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
        !           854:                        for (i = 0; i < 110; i++) {
        !           855:                                udelay(100);
        !           856:                        }
        !           857:                }
        !           858: 
        !           859:                bnx2_write_phy(bp, MII_ADVERTISE, new_adv);
        !           860:                bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART |
        !           861:                        BMCR_ANENABLE);
        !           862: #if 0
        !           863:                if (CHIP_NUM(bp) == CHIP_NUM_5706) {
        !           864:                        /* Speed up link-up time when the link partner
        !           865:                         * does not autonegotiate which is very common
        !           866:                         * in blade servers. Some blade servers use
        !           867:                         * IPMI for kerboard input and it's important
        !           868:                         * to minimize link disruptions. Autoneg. involves
        !           869:                         * exchanging base pages plus 3 next pages and
        !           870:                         * normally completes in about 120 msec.
        !           871:                         */
        !           872:                        bp->current_interval = SERDES_AN_TIMEOUT;
        !           873:                        bp->serdes_an_pending = 1;
        !           874:                        mod_timer(&bp->timer, jiffies + bp->current_interval);
        !           875:                }
        !           876: #endif
        !           877:        }
        !           878: 
        !           879:        return 0;
        !           880: }
        !           881: 
        !           882: #define ETHTOOL_ALL_FIBRE_SPEED                                                \
        !           883:        (ADVERTISED_1000baseT_Full)
        !           884: 
        !           885: #define ETHTOOL_ALL_COPPER_SPEED                                       \
        !           886:        (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |            \
        !           887:        ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |           \
        !           888:        ADVERTISED_1000baseT_Full)
        !           889: 
        !           890: #define PHY_ALL_10_100_SPEED (ADVERTISE_10HALF | ADVERTISE_10FULL | \
        !           891:        ADVERTISE_100HALF | ADVERTISE_100FULL | ADVERTISE_CSMA)
        !           892:        
        !           893: #define PHY_ALL_1000_SPEED (ADVERTISE_1000HALF | ADVERTISE_1000FULL)
        !           894: 
        !           895: static int
        !           896: bnx2_setup_copper_phy(struct bnx2 *bp)
        !           897: {
        !           898:        u32 bmcr;
        !           899:        u32 new_bmcr;
        !           900: 
        !           901:        bnx2_read_phy(bp, MII_BMCR, &bmcr);
        !           902: 
        !           903:        if (bp->autoneg & AUTONEG_SPEED) {
        !           904:                u32 adv_reg, adv1000_reg;
        !           905:                u32 new_adv_reg = 0;
        !           906:                u32 new_adv1000_reg = 0;
        !           907: 
        !           908:                bnx2_read_phy(bp, MII_ADVERTISE, &adv_reg);
        !           909:                adv_reg &= (PHY_ALL_10_100_SPEED | ADVERTISE_PAUSE_CAP |
        !           910:                        ADVERTISE_PAUSE_ASYM);
        !           911: 
        !           912:                bnx2_read_phy(bp, MII_CTRL1000, &adv1000_reg);
        !           913:                adv1000_reg &= PHY_ALL_1000_SPEED;
        !           914: 
        !           915:                if (bp->advertising & ADVERTISED_10baseT_Half)
        !           916:                        new_adv_reg |= ADVERTISE_10HALF;
        !           917:                if (bp->advertising & ADVERTISED_10baseT_Full)
        !           918:                        new_adv_reg |= ADVERTISE_10FULL;
        !           919:                if (bp->advertising & ADVERTISED_100baseT_Half)
        !           920:                        new_adv_reg |= ADVERTISE_100HALF;
        !           921:                if (bp->advertising & ADVERTISED_100baseT_Full)
        !           922:                        new_adv_reg |= ADVERTISE_100FULL;
        !           923:                if (bp->advertising & ADVERTISED_1000baseT_Full)
        !           924:                        new_adv1000_reg |= ADVERTISE_1000FULL;
        !           925:                
        !           926:                new_adv_reg |= ADVERTISE_CSMA;
        !           927: 
        !           928:                new_adv_reg |= bnx2_phy_get_pause_adv(bp);
        !           929: 
        !           930:                if ((adv1000_reg != new_adv1000_reg) ||
        !           931:                        (adv_reg != new_adv_reg) ||
        !           932:                        ((bmcr & BMCR_ANENABLE) == 0)) {
        !           933: 
        !           934:                        bnx2_write_phy(bp, MII_ADVERTISE, new_adv_reg);
        !           935:                        bnx2_write_phy(bp, MII_CTRL1000, new_adv1000_reg);
        !           936:                        bnx2_write_phy(bp, MII_BMCR, BMCR_ANRESTART |
        !           937:                                BMCR_ANENABLE);
        !           938:                }
        !           939:                else if (bp->link_up) {
        !           940:                        /* Flow ctrl may have changed from auto to forced */
        !           941:                        /* or vice-versa. */
        !           942: 
        !           943:                        bnx2_resolve_flow_ctrl(bp);
        !           944:                        bnx2_set_mac_link(bp);
        !           945:                }
        !           946:                return 0;
        !           947:        }
        !           948: 
        !           949:        new_bmcr = 0;
        !           950:        if (bp->req_line_speed == SPEED_100) {
        !           951:                new_bmcr |= BMCR_SPEED100;
        !           952:        }
        !           953:        if (bp->req_duplex == DUPLEX_FULL) {
        !           954:                new_bmcr |= BMCR_FULLDPLX;
        !           955:        }
        !           956:        if (new_bmcr != bmcr) {
        !           957:                u32 bmsr;
        !           958:                int i = 0;
        !           959: 
        !           960:                bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           961:                bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           962:                
        !           963:                if (bmsr & BMSR_LSTATUS) {
        !           964:                        /* Force link down */
        !           965:                        bnx2_write_phy(bp, MII_BMCR, BMCR_LOOPBACK);
        !           966:                        do {
        !           967:                                udelay(100);
        !           968:                                bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           969:                                bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !           970:                                i++;
        !           971:                        } while ((bmsr & BMSR_LSTATUS) && (i < 620));
        !           972:                }
        !           973: 
        !           974:                bnx2_write_phy(bp, MII_BMCR, new_bmcr);
        !           975: 
        !           976:                /* Normally, the new speed is setup after the link has
        !           977:                 * gone down and up again. In some cases, link will not go
        !           978:                 * down so we need to set up the new speed here.
        !           979:                 */
        !           980:                if (bmsr & BMSR_LSTATUS) {
        !           981:                        bp->line_speed = bp->req_line_speed;
        !           982:                        bp->duplex = bp->req_duplex;
        !           983:                        bnx2_resolve_flow_ctrl(bp);
        !           984:                        bnx2_set_mac_link(bp);
        !           985:                }
        !           986:        }
        !           987:        return 0;
        !           988: }
        !           989: 
        !           990: static int
        !           991: bnx2_setup_phy(struct bnx2 *bp)
        !           992: {
        !           993:        if (bp->loopback == MAC_LOOPBACK)
        !           994:                return 0;
        !           995: 
        !           996:        if (bp->phy_flags & PHY_SERDES_FLAG) {
        !           997:                return (bnx2_setup_serdes_phy(bp));
        !           998:        }
        !           999:        else {
        !          1000:                return (bnx2_setup_copper_phy(bp));
        !          1001:        }
        !          1002: }
        !          1003: 
        !          1004: static int
        !          1005: bnx2_init_5708s_phy(struct bnx2 *bp)
        !          1006: {
        !          1007:        u32 val;
        !          1008: 
        !          1009:        bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3);
        !          1010:        bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE);
        !          1011:        bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
        !          1012: 
        !          1013:        bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val);
        !          1014:        val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN;
        !          1015:        bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val);
        !          1016: 
        !          1017:        bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val);
        !          1018:        val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN;
        !          1019:        bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val);
        !          1020: 
        !          1021:        if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) {
        !          1022:                bnx2_read_phy(bp, BCM5708S_UP1, &val);
        !          1023:                val |= BCM5708S_UP1_2G5;
        !          1024:                bnx2_write_phy(bp, BCM5708S_UP1, val);
        !          1025:        }
        !          1026: 
        !          1027:        if ((CHIP_ID(bp) == CHIP_ID_5708_A0) ||
        !          1028:            (CHIP_ID(bp) == CHIP_ID_5708_B0) ||
        !          1029:            (CHIP_ID(bp) == CHIP_ID_5708_B1)) {
        !          1030:                /* increase tx signal amplitude */
        !          1031:                bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
        !          1032:                               BCM5708S_BLK_ADDR_TX_MISC);
        !          1033:                bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val);
        !          1034:                val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM;
        !          1035:                bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val);
        !          1036:                bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG);
        !          1037:        }
        !          1038: 
        !          1039:        val = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG) &
        !          1040:              BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK;
        !          1041: 
        !          1042:        if (val) {
        !          1043:                u32 is_backplane;
        !          1044: 
        !          1045:                is_backplane = REG_RD_IND(bp, bp->shmem_base +
        !          1046:                                          BNX2_SHARED_HW_CFG_CONFIG);
        !          1047:                if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) {
        !          1048:                        bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
        !          1049:                                       BCM5708S_BLK_ADDR_TX_MISC);
        !          1050:                        bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val);
        !          1051:                        bnx2_write_phy(bp, BCM5708S_BLK_ADDR,
        !          1052:                                       BCM5708S_BLK_ADDR_DIG);
        !          1053:                }
        !          1054:        }
        !          1055:        return 0;
        !          1056: }
        !          1057: 
        !          1058: static int
        !          1059: bnx2_init_5706s_phy(struct bnx2 *bp)
        !          1060: {
        !          1061:        u32 val;
        !          1062: 
        !          1063:        bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG;
        !          1064: 
        !          1065:        if (CHIP_NUM(bp) == CHIP_NUM_5706) {
        !          1066:                REG_WR(bp, BNX2_MISC_UNUSED0, 0x300);
        !          1067:        }
        !          1068: 
        !          1069: 
        !          1070:        bnx2_write_phy(bp, 0x18, 0x7);
        !          1071:        bnx2_read_phy(bp, 0x18, &val);
        !          1072:        bnx2_write_phy(bp, 0x18, val & ~0x4007);
        !          1073: 
        !          1074:        bnx2_write_phy(bp, 0x1c, 0x6c00);
        !          1075:        bnx2_read_phy(bp, 0x1c, &val);
        !          1076:        bnx2_write_phy(bp, 0x1c, (val & 0x3fd) | 0xec00);
        !          1077: 
        !          1078:        return 0;
        !          1079: }
        !          1080: 
        !          1081: static int
        !          1082: bnx2_init_copper_phy(struct bnx2 *bp)
        !          1083: {
        !          1084:        u32 val;
        !          1085: 
        !          1086:        bp->phy_flags |= PHY_CRC_FIX_FLAG;
        !          1087: 
        !          1088:        if (bp->phy_flags & PHY_CRC_FIX_FLAG) {
        !          1089:                bnx2_write_phy(bp, 0x18, 0x0c00);
        !          1090:                bnx2_write_phy(bp, 0x17, 0x000a);
        !          1091:                bnx2_write_phy(bp, 0x15, 0x310b);
        !          1092:                bnx2_write_phy(bp, 0x17, 0x201f);
        !          1093:                bnx2_write_phy(bp, 0x15, 0x9506);
        !          1094:                bnx2_write_phy(bp, 0x17, 0x401f);
        !          1095:                bnx2_write_phy(bp, 0x15, 0x14e2);
        !          1096:                bnx2_write_phy(bp, 0x18, 0x0400);
        !          1097:        }
        !          1098: 
        !          1099:        bnx2_write_phy(bp, 0x18, 0x7);
        !          1100:        bnx2_read_phy(bp, 0x18, &val);
        !          1101:        bnx2_write_phy(bp, 0x18, val & ~0x4007);
        !          1102: 
        !          1103:        bnx2_read_phy(bp, 0x10, &val);
        !          1104:        bnx2_write_phy(bp, 0x10, val & ~0x1);
        !          1105: 
        !          1106:        /* ethernet@wirespeed */
        !          1107:        bnx2_write_phy(bp, 0x18, 0x7007);
        !          1108:        bnx2_read_phy(bp, 0x18, &val);
        !          1109:        bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4));
        !          1110:        return 0;
        !          1111: }
        !          1112: 
        !          1113: static int
        !          1114: bnx2_init_phy(struct bnx2 *bp)
        !          1115: {
        !          1116:        u32 val;
        !          1117:        int rc = 0;
        !          1118: 
        !          1119:        bp->phy_flags &= ~PHY_INT_MODE_MASK_FLAG;
        !          1120:        bp->phy_flags |= PHY_INT_MODE_LINK_READY_FLAG;
        !          1121: 
        !          1122:         REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
        !          1123: 
        !          1124:        bnx2_reset_phy(bp);
        !          1125: 
        !          1126:        bnx2_read_phy(bp, MII_PHYSID1, &val);
        !          1127:        bp->phy_id = val << 16;
        !          1128:        bnx2_read_phy(bp, MII_PHYSID2, &val);
        !          1129:        bp->phy_id |= val & 0xffff;
        !          1130: 
        !          1131:        if (bp->phy_flags & PHY_SERDES_FLAG) {
        !          1132:                if (CHIP_NUM(bp) == CHIP_NUM_5706)
        !          1133:                        rc = bnx2_init_5706s_phy(bp);
        !          1134:                else if (CHIP_NUM(bp) == CHIP_NUM_5708)
        !          1135:                        rc = bnx2_init_5708s_phy(bp);
        !          1136:        }
        !          1137:        else {
        !          1138:                rc = bnx2_init_copper_phy(bp);
        !          1139:        }
        !          1140: 
        !          1141:        bnx2_setup_phy(bp);
        !          1142: 
        !          1143:        return rc;
        !          1144: }
        !          1145: 
        !          1146: static int
        !          1147: bnx2_fw_sync(struct bnx2 *bp, u32 msg_data, int silent)
        !          1148: {
        !          1149:        int i;
        !          1150:        u32 val;
        !          1151: 
        !          1152:        bp->fw_wr_seq++;
        !          1153:        msg_data |= bp->fw_wr_seq;
        !          1154: 
        !          1155:        REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
        !          1156: 
        !          1157:        /* wait for an acknowledgement. */
        !          1158:        for (i = 0; i < (FW_ACK_TIME_OUT_MS / 50); i++) {
        !          1159:                mdelay(50);
        !          1160: 
        !          1161:                val = REG_RD_IND(bp, bp->shmem_base + BNX2_FW_MB);
        !          1162: 
        !          1163:                if ((val & BNX2_FW_MSG_ACK) == (msg_data & BNX2_DRV_MSG_SEQ))
        !          1164:                        break;
        !          1165:        }
        !          1166:        if ((msg_data & BNX2_DRV_MSG_DATA) == BNX2_DRV_MSG_DATA_WAIT0)
        !          1167:                return 0;
        !          1168: 
        !          1169:        /* If we timed out, inform the firmware that this is the case. */
        !          1170:        if ((val & BNX2_FW_MSG_ACK) != (msg_data & BNX2_DRV_MSG_SEQ)) {
        !          1171:                if (!silent)
        !          1172:                  printf("fw sync timeout, reset code = %x\n", (unsigned int) msg_data);
        !          1173: 
        !          1174:                msg_data &= ~BNX2_DRV_MSG_CODE;
        !          1175:                msg_data |= BNX2_DRV_MSG_CODE_FW_TIMEOUT;
        !          1176: 
        !          1177:                REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_MB, msg_data);
        !          1178: 
        !          1179:                return -EBUSY;
        !          1180:        }
        !          1181: 
        !          1182:        if ((val & BNX2_FW_MSG_STATUS_MASK) != BNX2_FW_MSG_STATUS_OK)
        !          1183:                return -EIO;
        !          1184: 
        !          1185:        return 0;
        !          1186: }
        !          1187: 
        !          1188: static void
        !          1189: bnx2_init_context(struct bnx2 *bp)
        !          1190: {
        !          1191:        u32 vcid;
        !          1192: 
        !          1193:        vcid = 96;
        !          1194:        while (vcid) {
        !          1195:                u32 vcid_addr, pcid_addr, offset;
        !          1196: 
        !          1197:                vcid--;
        !          1198: 
        !          1199:                if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
        !          1200:                        u32 new_vcid;
        !          1201: 
        !          1202:                        vcid_addr = GET_PCID_ADDR(vcid);
        !          1203:                        if (vcid & 0x8) {
        !          1204:                                new_vcid = 0x60 + (vcid & 0xf0) + (vcid & 0x7);
        !          1205:                        }
        !          1206:                        else {
        !          1207:                                new_vcid = vcid;
        !          1208:                        }
        !          1209:                        pcid_addr = GET_PCID_ADDR(new_vcid);
        !          1210:                }
        !          1211:                else {
        !          1212:                        vcid_addr = GET_CID_ADDR(vcid);
        !          1213:                        pcid_addr = vcid_addr;
        !          1214:                }
        !          1215: 
        !          1216:                REG_WR(bp, BNX2_CTX_VIRT_ADDR, 0x00);
        !          1217:                REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
        !          1218: 
        !          1219:                /* Zero out the context. */
        !          1220:                for (offset = 0; offset < PHY_CTX_SIZE; offset += 4) {
        !          1221:                        CTX_WR(bp, 0x00, offset, 0);
        !          1222:                }
        !          1223: 
        !          1224:                REG_WR(bp, BNX2_CTX_VIRT_ADDR, vcid_addr);
        !          1225:                REG_WR(bp, BNX2_CTX_PAGE_TBL, pcid_addr);
        !          1226:        }
        !          1227: }
        !          1228: 
        !          1229: static int
        !          1230: bnx2_alloc_bad_rbuf(struct bnx2 *bp)
        !          1231: {
        !          1232:        u16 good_mbuf[512];
        !          1233:        u32 good_mbuf_cnt;
        !          1234:        u32 val;
        !          1235: 
        !          1236:        REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
        !          1237:                BNX2_MISC_ENABLE_SET_BITS_RX_MBUF_ENABLE);
        !          1238: 
        !          1239:        good_mbuf_cnt = 0;
        !          1240: 
        !          1241:        /* Allocate a bunch of mbufs and save the good ones in an array. */
        !          1242:        val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
        !          1243:        while (val & BNX2_RBUF_STATUS1_FREE_COUNT) {
        !          1244:                REG_WR_IND(bp, BNX2_RBUF_COMMAND, BNX2_RBUF_COMMAND_ALLOC_REQ);
        !          1245: 
        !          1246:                val = REG_RD_IND(bp, BNX2_RBUF_FW_BUF_ALLOC);
        !          1247: 
        !          1248:                val &= BNX2_RBUF_FW_BUF_ALLOC_VALUE;
        !          1249: 
        !          1250:                /* The addresses with Bit 9 set are bad memory blocks. */
        !          1251:                if (!(val & (1 << 9))) {
        !          1252:                        good_mbuf[good_mbuf_cnt] = (u16) val;
        !          1253:                        good_mbuf_cnt++;
        !          1254:                }
        !          1255: 
        !          1256:                val = REG_RD_IND(bp, BNX2_RBUF_STATUS1);
        !          1257:        }
        !          1258: 
        !          1259:        /* Free the good ones back to the mbuf pool thus discarding
        !          1260:         * all the bad ones. */
        !          1261:        while (good_mbuf_cnt) {
        !          1262:                good_mbuf_cnt--;
        !          1263: 
        !          1264:                val = good_mbuf[good_mbuf_cnt];
        !          1265:                val = (val << 9) | val | 1;
        !          1266: 
        !          1267:                REG_WR_IND(bp, BNX2_RBUF_FW_BUF_FREE, val);
        !          1268:        }
        !          1269:        return 0;
        !          1270: }
        !          1271: 
        !          1272: static void
        !          1273: bnx2_set_mac_addr(struct bnx2 *bp) 
        !          1274: {
        !          1275:        u32 val;
        !          1276:        u8 *mac_addr = bp->nic->node_addr;
        !          1277: 
        !          1278:        val = (mac_addr[0] << 8) | mac_addr[1];
        !          1279: 
        !          1280:        REG_WR(bp, BNX2_EMAC_MAC_MATCH0, val);
        !          1281: 
        !          1282:        val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | 
        !          1283:                (mac_addr[4] << 8) | mac_addr[5];
        !          1284: 
        !          1285:        REG_WR(bp, BNX2_EMAC_MAC_MATCH1, val);
        !          1286: }
        !          1287: 
        !          1288: static void
        !          1289: bnx2_set_rx_mode(struct nic *nic __unused)
        !          1290: {
        !          1291:        struct bnx2 *bp = &bnx2;
        !          1292:        u32 rx_mode, sort_mode;
        !          1293:        int i;
        !          1294: 
        !          1295:        rx_mode = bp->rx_mode & ~(BNX2_EMAC_RX_MODE_PROMISCUOUS |
        !          1296:                                  BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG);
        !          1297:        sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN;
        !          1298: 
        !          1299:        if (!(bp->flags & ASF_ENABLE_FLAG)) {
        !          1300:                rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG;
        !          1301:        }
        !          1302: 
        !          1303:        /* Accept all multicasts */
        !          1304:        for (i = 0; i < NUM_MC_HASH_REGISTERS; i++) {
        !          1305:                REG_WR(bp, BNX2_EMAC_MULTICAST_HASH0 + (i * 4),
        !          1306:                       0xffffffff);
        !          1307:                }
        !          1308:        sort_mode |= BNX2_RPM_SORT_USER0_MC_EN;
        !          1309: 
        !          1310:        if (rx_mode != bp->rx_mode) {
        !          1311:                bp->rx_mode = rx_mode;
        !          1312:                REG_WR(bp, BNX2_EMAC_RX_MODE, rx_mode);
        !          1313:        }
        !          1314: 
        !          1315:        REG_WR(bp, BNX2_RPM_SORT_USER0, 0x0);
        !          1316:        REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode);
        !          1317:        REG_WR(bp, BNX2_RPM_SORT_USER0, sort_mode | BNX2_RPM_SORT_USER0_ENA);
        !          1318: }
        !          1319: 
        !          1320: static void
        !          1321: load_rv2p_fw(struct bnx2 *bp, u32 *rv2p_code, u32 rv2p_code_len, u32 rv2p_proc)
        !          1322: {
        !          1323:        unsigned int i;
        !          1324:        u32 val;
        !          1325: 
        !          1326: 
        !          1327:        for (i = 0; i < rv2p_code_len; i += 8) {
        !          1328:                REG_WR(bp, BNX2_RV2P_INSTR_HIGH, *rv2p_code);
        !          1329:                rv2p_code++;
        !          1330:                REG_WR(bp, BNX2_RV2P_INSTR_LOW, *rv2p_code);
        !          1331:                rv2p_code++;
        !          1332: 
        !          1333:                if (rv2p_proc == RV2P_PROC1) {
        !          1334:                        val = (i / 8) | BNX2_RV2P_PROC1_ADDR_CMD_RDWR;
        !          1335:                        REG_WR(bp, BNX2_RV2P_PROC1_ADDR_CMD, val);
        !          1336:                }
        !          1337:                else {
        !          1338:                        val = (i / 8) | BNX2_RV2P_PROC2_ADDR_CMD_RDWR;
        !          1339:                        REG_WR(bp, BNX2_RV2P_PROC2_ADDR_CMD, val);
        !          1340:                }
        !          1341:        }
        !          1342: 
        !          1343:        /* Reset the processor, un-stall is done later. */
        !          1344:        if (rv2p_proc == RV2P_PROC1) {
        !          1345:                REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC1_RESET);
        !          1346:        }
        !          1347:        else {
        !          1348:                REG_WR(bp, BNX2_RV2P_COMMAND, BNX2_RV2P_COMMAND_PROC2_RESET);
        !          1349:        }
        !          1350: }
        !          1351: 
        !          1352: static void
        !          1353: load_cpu_fw(struct bnx2 *bp, struct cpu_reg *cpu_reg, struct fw_info *fw)
        !          1354: {
        !          1355:        u32 offset;
        !          1356:        u32 val;
        !          1357: 
        !          1358:        /* Halt the CPU. */
        !          1359:        val = REG_RD_IND(bp, cpu_reg->mode);
        !          1360:        val |= cpu_reg->mode_value_halt;
        !          1361:        REG_WR_IND(bp, cpu_reg->mode, val);
        !          1362:        REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
        !          1363: 
        !          1364:        /* Load the Text area. */
        !          1365:        offset = cpu_reg->spad_base + (fw->text_addr - cpu_reg->mips_view_base);
        !          1366:        if (fw->text) {
        !          1367:                unsigned int j;
        !          1368: 
        !          1369:                for (j = 0; j < (fw->text_len / 4); j++, offset += 4) {
        !          1370:                        REG_WR_IND(bp, offset, fw->text[j]);
        !          1371:                }
        !          1372:        }
        !          1373: 
        !          1374:        /* Load the Data area. */
        !          1375:        offset = cpu_reg->spad_base + (fw->data_addr - cpu_reg->mips_view_base);
        !          1376:        if (fw->data) {
        !          1377:                unsigned int j;
        !          1378: 
        !          1379:                for (j = 0; j < (fw->data_len / 4); j++, offset += 4) {
        !          1380:                        REG_WR_IND(bp, offset, fw->data[j]);
        !          1381:                }
        !          1382:        }
        !          1383: 
        !          1384:        /* Load the SBSS area. */
        !          1385:        offset = cpu_reg->spad_base + (fw->sbss_addr - cpu_reg->mips_view_base);
        !          1386:        if (fw->sbss) {
        !          1387:                unsigned int j;
        !          1388: 
        !          1389:                for (j = 0; j < (fw->sbss_len / 4); j++, offset += 4) {
        !          1390:                        REG_WR_IND(bp, offset, fw->sbss[j]);
        !          1391:                }
        !          1392:        }
        !          1393: 
        !          1394:        /* Load the BSS area. */
        !          1395:        offset = cpu_reg->spad_base + (fw->bss_addr - cpu_reg->mips_view_base);
        !          1396:        if (fw->bss) {
        !          1397:                unsigned int j;
        !          1398: 
        !          1399:                for (j = 0; j < (fw->bss_len/4); j++, offset += 4) {
        !          1400:                        REG_WR_IND(bp, offset, fw->bss[j]);
        !          1401:                }
        !          1402:        }
        !          1403: 
        !          1404:        /* Load the Read-Only area. */
        !          1405:        offset = cpu_reg->spad_base +
        !          1406:                (fw->rodata_addr - cpu_reg->mips_view_base);
        !          1407:        if (fw->rodata) {
        !          1408:                unsigned int j;
        !          1409: 
        !          1410:                for (j = 0; j < (fw->rodata_len / 4); j++, offset += 4) {
        !          1411:                        REG_WR_IND(bp, offset, fw->rodata[j]);
        !          1412:                }
        !          1413:        }
        !          1414: 
        !          1415:        /* Clear the pre-fetch instruction. */
        !          1416:        REG_WR_IND(bp, cpu_reg->inst, 0);
        !          1417:        REG_WR_IND(bp, cpu_reg->pc, fw->start_addr);
        !          1418: 
        !          1419:        /* Start the CPU. */
        !          1420:        val = REG_RD_IND(bp, cpu_reg->mode);
        !          1421:        val &= ~cpu_reg->mode_value_halt;
        !          1422:        REG_WR_IND(bp, cpu_reg->state, cpu_reg->state_value_clear);
        !          1423:        REG_WR_IND(bp, cpu_reg->mode, val);
        !          1424: }
        !          1425: 
        !          1426: static void
        !          1427: bnx2_init_cpus(struct bnx2 *bp)
        !          1428: {
        !          1429:        struct cpu_reg cpu_reg;
        !          1430:        struct fw_info fw;
        !          1431: 
        !          1432:        /* Unfortunately, it looks like we need to load the firmware
        !          1433:         * before the card will work properly.  That means this driver
        !          1434:         * will be huge by Etherboot standards (approx. 50K compressed).
        !          1435:         */
        !          1436: 
        !          1437:        /* Initialize the RV2P processor. */
        !          1438:        load_rv2p_fw(bp, bnx2_rv2p_proc1, sizeof(bnx2_rv2p_proc1), RV2P_PROC1);
        !          1439:        load_rv2p_fw(bp, bnx2_rv2p_proc2, sizeof(bnx2_rv2p_proc2), RV2P_PROC2);
        !          1440: 
        !          1441:        /* Initialize the RX Processor. */
        !          1442:        cpu_reg.mode = BNX2_RXP_CPU_MODE;
        !          1443:        cpu_reg.mode_value_halt = BNX2_RXP_CPU_MODE_SOFT_HALT;
        !          1444:        cpu_reg.mode_value_sstep = BNX2_RXP_CPU_MODE_STEP_ENA;
        !          1445:        cpu_reg.state = BNX2_RXP_CPU_STATE;
        !          1446:        cpu_reg.state_value_clear = 0xffffff;
        !          1447:        cpu_reg.gpr0 = BNX2_RXP_CPU_REG_FILE;
        !          1448:        cpu_reg.evmask = BNX2_RXP_CPU_EVENT_MASK;
        !          1449:        cpu_reg.pc = BNX2_RXP_CPU_PROGRAM_COUNTER;
        !          1450:        cpu_reg.inst = BNX2_RXP_CPU_INSTRUCTION;
        !          1451:        cpu_reg.bp = BNX2_RXP_CPU_HW_BREAKPOINT;
        !          1452:        cpu_reg.spad_base = BNX2_RXP_SCRATCH;
        !          1453:        cpu_reg.mips_view_base = 0x8000000;
        !          1454: 
        !          1455:        fw.ver_major = bnx2_RXP_b06FwReleaseMajor;
        !          1456:        fw.ver_minor = bnx2_RXP_b06FwReleaseMinor;
        !          1457:        fw.ver_fix = bnx2_RXP_b06FwReleaseFix;
        !          1458:        fw.start_addr = bnx2_RXP_b06FwStartAddr;
        !          1459: 
        !          1460:        fw.text_addr = bnx2_RXP_b06FwTextAddr;
        !          1461:        fw.text_len = bnx2_RXP_b06FwTextLen;
        !          1462:        fw.text_index = 0;
        !          1463:        fw.text = bnx2_RXP_b06FwText;
        !          1464: 
        !          1465:        fw.data_addr = bnx2_RXP_b06FwDataAddr;
        !          1466:        fw.data_len = bnx2_RXP_b06FwDataLen;
        !          1467:        fw.data_index = 0;
        !          1468:        fw.data = bnx2_RXP_b06FwData;
        !          1469: 
        !          1470:        fw.sbss_addr = bnx2_RXP_b06FwSbssAddr;
        !          1471:        fw.sbss_len = bnx2_RXP_b06FwSbssLen;
        !          1472:        fw.sbss_index = 0;
        !          1473:        fw.sbss = bnx2_RXP_b06FwSbss;
        !          1474: 
        !          1475:        fw.bss_addr = bnx2_RXP_b06FwBssAddr;
        !          1476:        fw.bss_len = bnx2_RXP_b06FwBssLen;
        !          1477:        fw.bss_index = 0;
        !          1478:        fw.bss = bnx2_RXP_b06FwBss;
        !          1479: 
        !          1480:        fw.rodata_addr = bnx2_RXP_b06FwRodataAddr;
        !          1481:        fw.rodata_len = bnx2_RXP_b06FwRodataLen;
        !          1482:        fw.rodata_index = 0;
        !          1483:        fw.rodata = bnx2_RXP_b06FwRodata;
        !          1484: 
        !          1485:        load_cpu_fw(bp, &cpu_reg, &fw);
        !          1486: 
        !          1487:        /* Initialize the TX Processor. */
        !          1488:        cpu_reg.mode = BNX2_TXP_CPU_MODE;
        !          1489:        cpu_reg.mode_value_halt = BNX2_TXP_CPU_MODE_SOFT_HALT;
        !          1490:        cpu_reg.mode_value_sstep = BNX2_TXP_CPU_MODE_STEP_ENA;
        !          1491:        cpu_reg.state = BNX2_TXP_CPU_STATE;
        !          1492:        cpu_reg.state_value_clear = 0xffffff;
        !          1493:        cpu_reg.gpr0 = BNX2_TXP_CPU_REG_FILE;
        !          1494:        cpu_reg.evmask = BNX2_TXP_CPU_EVENT_MASK;
        !          1495:        cpu_reg.pc = BNX2_TXP_CPU_PROGRAM_COUNTER;
        !          1496:        cpu_reg.inst = BNX2_TXP_CPU_INSTRUCTION;
        !          1497:        cpu_reg.bp = BNX2_TXP_CPU_HW_BREAKPOINT;
        !          1498:        cpu_reg.spad_base = BNX2_TXP_SCRATCH;
        !          1499:        cpu_reg.mips_view_base = 0x8000000;
        !          1500:     
        !          1501:        fw.ver_major = bnx2_TXP_b06FwReleaseMajor;
        !          1502:        fw.ver_minor = bnx2_TXP_b06FwReleaseMinor;
        !          1503:        fw.ver_fix = bnx2_TXP_b06FwReleaseFix;
        !          1504:        fw.start_addr = bnx2_TXP_b06FwStartAddr;
        !          1505: 
        !          1506:        fw.text_addr = bnx2_TXP_b06FwTextAddr;
        !          1507:        fw.text_len = bnx2_TXP_b06FwTextLen;
        !          1508:        fw.text_index = 0;
        !          1509:        fw.text = bnx2_TXP_b06FwText;
        !          1510: 
        !          1511:        fw.data_addr = bnx2_TXP_b06FwDataAddr;
        !          1512:        fw.data_len = bnx2_TXP_b06FwDataLen;
        !          1513:        fw.data_index = 0;
        !          1514:        fw.data = bnx2_TXP_b06FwData;
        !          1515: 
        !          1516:        fw.sbss_addr = bnx2_TXP_b06FwSbssAddr;
        !          1517:        fw.sbss_len = bnx2_TXP_b06FwSbssLen;
        !          1518:        fw.sbss_index = 0;
        !          1519:        fw.sbss = bnx2_TXP_b06FwSbss;
        !          1520: 
        !          1521:        fw.bss_addr = bnx2_TXP_b06FwBssAddr;
        !          1522:        fw.bss_len = bnx2_TXP_b06FwBssLen;
        !          1523:        fw.bss_index = 0;
        !          1524:        fw.bss = bnx2_TXP_b06FwBss;
        !          1525: 
        !          1526:        fw.rodata_addr = bnx2_TXP_b06FwRodataAddr;
        !          1527:        fw.rodata_len = bnx2_TXP_b06FwRodataLen;
        !          1528:        fw.rodata_index = 0;
        !          1529:        fw.rodata = bnx2_TXP_b06FwRodata;
        !          1530: 
        !          1531:        load_cpu_fw(bp, &cpu_reg, &fw);
        !          1532: 
        !          1533:        /* Initialize the TX Patch-up Processor. */
        !          1534:        cpu_reg.mode = BNX2_TPAT_CPU_MODE;
        !          1535:        cpu_reg.mode_value_halt = BNX2_TPAT_CPU_MODE_SOFT_HALT;
        !          1536:        cpu_reg.mode_value_sstep = BNX2_TPAT_CPU_MODE_STEP_ENA;
        !          1537:        cpu_reg.state = BNX2_TPAT_CPU_STATE;
        !          1538:        cpu_reg.state_value_clear = 0xffffff;
        !          1539:        cpu_reg.gpr0 = BNX2_TPAT_CPU_REG_FILE;
        !          1540:        cpu_reg.evmask = BNX2_TPAT_CPU_EVENT_MASK;
        !          1541:        cpu_reg.pc = BNX2_TPAT_CPU_PROGRAM_COUNTER;
        !          1542:        cpu_reg.inst = BNX2_TPAT_CPU_INSTRUCTION;
        !          1543:        cpu_reg.bp = BNX2_TPAT_CPU_HW_BREAKPOINT;
        !          1544:        cpu_reg.spad_base = BNX2_TPAT_SCRATCH;
        !          1545:        cpu_reg.mips_view_base = 0x8000000;
        !          1546:     
        !          1547:        fw.ver_major = bnx2_TPAT_b06FwReleaseMajor;
        !          1548:        fw.ver_minor = bnx2_TPAT_b06FwReleaseMinor;
        !          1549:        fw.ver_fix = bnx2_TPAT_b06FwReleaseFix;
        !          1550:        fw.start_addr = bnx2_TPAT_b06FwStartAddr;
        !          1551: 
        !          1552:        fw.text_addr = bnx2_TPAT_b06FwTextAddr;
        !          1553:        fw.text_len = bnx2_TPAT_b06FwTextLen;
        !          1554:        fw.text_index = 0;
        !          1555:        fw.text = bnx2_TPAT_b06FwText;
        !          1556: 
        !          1557:        fw.data_addr = bnx2_TPAT_b06FwDataAddr;
        !          1558:        fw.data_len = bnx2_TPAT_b06FwDataLen;
        !          1559:        fw.data_index = 0;
        !          1560:        fw.data = bnx2_TPAT_b06FwData;
        !          1561: 
        !          1562:        fw.sbss_addr = bnx2_TPAT_b06FwSbssAddr;
        !          1563:        fw.sbss_len = bnx2_TPAT_b06FwSbssLen;
        !          1564:        fw.sbss_index = 0;
        !          1565:        fw.sbss = bnx2_TPAT_b06FwSbss;
        !          1566: 
        !          1567:        fw.bss_addr = bnx2_TPAT_b06FwBssAddr;
        !          1568:        fw.bss_len = bnx2_TPAT_b06FwBssLen;
        !          1569:        fw.bss_index = 0;
        !          1570:        fw.bss = bnx2_TPAT_b06FwBss;
        !          1571: 
        !          1572:        fw.rodata_addr = bnx2_TPAT_b06FwRodataAddr;
        !          1573:        fw.rodata_len = bnx2_TPAT_b06FwRodataLen;
        !          1574:        fw.rodata_index = 0;
        !          1575:        fw.rodata = bnx2_TPAT_b06FwRodata;
        !          1576: 
        !          1577:        load_cpu_fw(bp, &cpu_reg, &fw);
        !          1578: 
        !          1579:        /* Initialize the Completion Processor. */
        !          1580:        cpu_reg.mode = BNX2_COM_CPU_MODE;
        !          1581:        cpu_reg.mode_value_halt = BNX2_COM_CPU_MODE_SOFT_HALT;
        !          1582:        cpu_reg.mode_value_sstep = BNX2_COM_CPU_MODE_STEP_ENA;
        !          1583:        cpu_reg.state = BNX2_COM_CPU_STATE;
        !          1584:        cpu_reg.state_value_clear = 0xffffff;
        !          1585:        cpu_reg.gpr0 = BNX2_COM_CPU_REG_FILE;
        !          1586:        cpu_reg.evmask = BNX2_COM_CPU_EVENT_MASK;
        !          1587:        cpu_reg.pc = BNX2_COM_CPU_PROGRAM_COUNTER;
        !          1588:        cpu_reg.inst = BNX2_COM_CPU_INSTRUCTION;
        !          1589:        cpu_reg.bp = BNX2_COM_CPU_HW_BREAKPOINT;
        !          1590:        cpu_reg.spad_base = BNX2_COM_SCRATCH;
        !          1591:        cpu_reg.mips_view_base = 0x8000000;
        !          1592:     
        !          1593:        fw.ver_major = bnx2_COM_b06FwReleaseMajor;
        !          1594:        fw.ver_minor = bnx2_COM_b06FwReleaseMinor;
        !          1595:        fw.ver_fix = bnx2_COM_b06FwReleaseFix;
        !          1596:        fw.start_addr = bnx2_COM_b06FwStartAddr;
        !          1597: 
        !          1598:        fw.text_addr = bnx2_COM_b06FwTextAddr;
        !          1599:        fw.text_len = bnx2_COM_b06FwTextLen;
        !          1600:        fw.text_index = 0;
        !          1601:        fw.text = bnx2_COM_b06FwText;
        !          1602: 
        !          1603:        fw.data_addr = bnx2_COM_b06FwDataAddr;
        !          1604:        fw.data_len = bnx2_COM_b06FwDataLen;
        !          1605:        fw.data_index = 0;
        !          1606:        fw.data = bnx2_COM_b06FwData;
        !          1607: 
        !          1608:        fw.sbss_addr = bnx2_COM_b06FwSbssAddr;
        !          1609:        fw.sbss_len = bnx2_COM_b06FwSbssLen;
        !          1610:        fw.sbss_index = 0;
        !          1611:        fw.sbss = bnx2_COM_b06FwSbss;
        !          1612: 
        !          1613:        fw.bss_addr = bnx2_COM_b06FwBssAddr;
        !          1614:        fw.bss_len = bnx2_COM_b06FwBssLen;
        !          1615:        fw.bss_index = 0;
        !          1616:        fw.bss = bnx2_COM_b06FwBss;
        !          1617: 
        !          1618:        fw.rodata_addr = bnx2_COM_b06FwRodataAddr;
        !          1619:        fw.rodata_len = bnx2_COM_b06FwRodataLen;
        !          1620:        fw.rodata_index = 0;
        !          1621:        fw.rodata = bnx2_COM_b06FwRodata;
        !          1622: 
        !          1623:        load_cpu_fw(bp, &cpu_reg, &fw);
        !          1624: 
        !          1625: }
        !          1626: 
        !          1627: static int
        !          1628: bnx2_set_power_state_0(struct bnx2 *bp)
        !          1629: {
        !          1630:        u16 pmcsr;
        !          1631:        u32 val;
        !          1632: 
        !          1633:        pci_read_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL, &pmcsr);
        !          1634: 
        !          1635:        pci_write_config_word(bp->pdev, bp->pm_cap + PCI_PM_CTRL,
        !          1636:                (pmcsr & ~PCI_PM_CTRL_STATE_MASK) |
        !          1637:                PCI_PM_CTRL_PME_STATUS);
        !          1638: 
        !          1639:        if (pmcsr & PCI_PM_CTRL_STATE_MASK)
        !          1640:                /* delay required during transition out of D3hot */
        !          1641:                mdelay(20);
        !          1642: 
        !          1643:        val = REG_RD(bp, BNX2_EMAC_MODE);
        !          1644:        val |= BNX2_EMAC_MODE_MPKT_RCVD | BNX2_EMAC_MODE_ACPI_RCVD;
        !          1645:        val &= ~BNX2_EMAC_MODE_MPKT;
        !          1646:        REG_WR(bp, BNX2_EMAC_MODE, val);
        !          1647: 
        !          1648:        val = REG_RD(bp, BNX2_RPM_CONFIG);
        !          1649:        val &= ~BNX2_RPM_CONFIG_ACPI_ENA;
        !          1650:        REG_WR(bp, BNX2_RPM_CONFIG, val);
        !          1651:                
        !          1652:        return 0;
        !          1653: }
        !          1654: 
        !          1655: static void
        !          1656: bnx2_enable_nvram_access(struct bnx2 *bp)
        !          1657: {
        !          1658:        u32 val;
        !          1659: 
        !          1660:        val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
        !          1661:        /* Enable both bits, even on read. */
        !          1662:        REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, 
        !          1663:               val | BNX2_NVM_ACCESS_ENABLE_EN | BNX2_NVM_ACCESS_ENABLE_WR_EN);
        !          1664: }
        !          1665: 
        !          1666: static void
        !          1667: bnx2_disable_nvram_access(struct bnx2 *bp)
        !          1668: {
        !          1669:        u32 val;
        !          1670: 
        !          1671:        val = REG_RD(bp, BNX2_NVM_ACCESS_ENABLE);
        !          1672:        /* Disable both bits, even after read. */
        !          1673:        REG_WR(bp, BNX2_NVM_ACCESS_ENABLE, 
        !          1674:                val & ~(BNX2_NVM_ACCESS_ENABLE_EN |
        !          1675:                        BNX2_NVM_ACCESS_ENABLE_WR_EN));
        !          1676: }
        !          1677: 
        !          1678: static int
        !          1679: bnx2_init_nvram(struct bnx2 *bp)
        !          1680: {
        !          1681:        u32 val;
        !          1682:        int j, entry_count, rc;
        !          1683:        struct flash_spec *flash;
        !          1684: 
        !          1685:        /* Determine the selected interface. */
        !          1686:        val = REG_RD(bp, BNX2_NVM_CFG1);
        !          1687: 
        !          1688:        entry_count = sizeof(flash_table) / sizeof(struct flash_spec);
        !          1689: 
        !          1690:        rc = 0;
        !          1691:        if (val & 0x40000000) {
        !          1692:                /* Flash interface has been reconfigured */
        !          1693:                for (j = 0, flash = &flash_table[0]; j < entry_count;
        !          1694:                     j++, flash++) {
        !          1695:                        if ((val & FLASH_BACKUP_STRAP_MASK) ==
        !          1696:                            (flash->config1 & FLASH_BACKUP_STRAP_MASK)) {
        !          1697:                                bp->flash_info = flash;
        !          1698:                                break;
        !          1699:                        }
        !          1700:                }
        !          1701:        }
        !          1702:        else {
        !          1703:                u32 mask;
        !          1704:                /* Not yet been reconfigured */
        !          1705: 
        !          1706:                if (val & (1 << 23))
        !          1707:                        mask = FLASH_BACKUP_STRAP_MASK;
        !          1708:                else
        !          1709:                        mask = FLASH_STRAP_MASK;
        !          1710: 
        !          1711:                for (j = 0, flash = &flash_table[0]; j < entry_count;
        !          1712:                        j++, flash++) {
        !          1713: 
        !          1714:                        if ((val & mask) == (flash->strapping & mask)) {
        !          1715:                                bp->flash_info = flash;
        !          1716: 
        !          1717:                                /* Enable access to flash interface */
        !          1718:                                bnx2_enable_nvram_access(bp);
        !          1719: 
        !          1720:                                /* Reconfigure the flash interface */
        !          1721:                                REG_WR(bp, BNX2_NVM_CFG1, flash->config1);
        !          1722:                                REG_WR(bp, BNX2_NVM_CFG2, flash->config2);
        !          1723:                                REG_WR(bp, BNX2_NVM_CFG3, flash->config3);
        !          1724:                                REG_WR(bp, BNX2_NVM_WRITE1, flash->write1);
        !          1725: 
        !          1726:                                /* Disable access to flash interface */
        !          1727:                                bnx2_disable_nvram_access(bp);
        !          1728: 
        !          1729:                                break;
        !          1730:                        }
        !          1731:                }
        !          1732:        } /* if (val & 0x40000000) */
        !          1733: 
        !          1734:        if (j == entry_count) {
        !          1735:                bp->flash_info = NULL;
        !          1736:                printf("Unknown flash/EEPROM type.\n");
        !          1737:                return -ENODEV;
        !          1738:        }
        !          1739: 
        !          1740:        val = REG_RD_IND(bp, bp->shmem_base + BNX2_SHARED_HW_CFG_CONFIG2);
        !          1741:        val &= BNX2_SHARED_HW_CFG2_NVM_SIZE_MASK;
        !          1742:        if (val) {
        !          1743:                bp->flash_size = val;
        !          1744:        }
        !          1745:        else {
        !          1746:                bp->flash_size = bp->flash_info->total_size;
        !          1747:        }
        !          1748: 
        !          1749:        return rc;
        !          1750: }
        !          1751: 
        !          1752: static int
        !          1753: bnx2_reset_chip(struct bnx2 *bp, u32 reset_code)
        !          1754: {
        !          1755:        u32 val;
        !          1756:        int i, rc = 0;
        !          1757: 
        !          1758:        /* Wait for the current PCI transaction to complete before
        !          1759:         * issuing a reset. */
        !          1760:        REG_WR(bp, BNX2_MISC_ENABLE_CLR_BITS,
        !          1761:               BNX2_MISC_ENABLE_CLR_BITS_TX_DMA_ENABLE |
        !          1762:               BNX2_MISC_ENABLE_CLR_BITS_DMA_ENGINE_ENABLE |
        !          1763:               BNX2_MISC_ENABLE_CLR_BITS_RX_DMA_ENABLE |
        !          1764:               BNX2_MISC_ENABLE_CLR_BITS_HOST_COALESCE_ENABLE);
        !          1765:        val = REG_RD(bp, BNX2_MISC_ENABLE_CLR_BITS);
        !          1766:        udelay(5);
        !          1767: 
        !          1768: 
        !          1769:        /* Wait for the firmware to tell us it is ok to issue a reset. */
        !          1770:        bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT0 | reset_code, 1);
        !          1771: 
        !          1772:        /* Deposit a driver reset signature so the firmware knows that
        !          1773:         * this is a soft reset. */
        !          1774:        REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_RESET_SIGNATURE,
        !          1775:                   BNX2_DRV_RESET_SIGNATURE_MAGIC);
        !          1776: 
        !          1777:        /* Do a dummy read to force the chip to complete all current transaction
        !          1778:         * before we issue a reset. */
        !          1779:        val = REG_RD(bp, BNX2_MISC_ID);
        !          1780: 
        !          1781:        val = BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
        !          1782:              BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
        !          1783:              BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP;
        !          1784: 
        !          1785:        /* Chip reset. */
        !          1786:        REG_WR(bp, BNX2_PCICFG_MISC_CONFIG, val);
        !          1787: 
        !          1788:        if ((CHIP_ID(bp) == CHIP_ID_5706_A0) ||
        !          1789:            (CHIP_ID(bp) == CHIP_ID_5706_A1))
        !          1790:                mdelay(15);
        !          1791: 
        !          1792:        /* Reset takes approximate 30 usec */
        !          1793:        for (i = 0; i < 10; i++) {
        !          1794:                val = REG_RD(bp, BNX2_PCICFG_MISC_CONFIG);
        !          1795:                if ((val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
        !          1796:                            BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) == 0) {
        !          1797:                        break;
        !          1798:                }
        !          1799:                udelay(10);
        !          1800:        }
        !          1801: 
        !          1802:        if (val & (BNX2_PCICFG_MISC_CONFIG_CORE_RST_REQ |
        !          1803:                   BNX2_PCICFG_MISC_CONFIG_CORE_RST_BSY)) {
        !          1804:                printf("Chip reset did not complete\n");
        !          1805:                return -EBUSY;
        !          1806:        }
        !          1807: 
        !          1808:        /* Make sure byte swapping is properly configured. */
        !          1809:        val = REG_RD(bp, BNX2_PCI_SWAP_DIAG0);
        !          1810:        if (val != 0x01020304) {
        !          1811:                printf("Chip not in correct endian mode\n");
        !          1812:                return -ENODEV;
        !          1813:        }
        !          1814: 
        !          1815:        /* Wait for the firmware to finish its initialization. */
        !          1816:        rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT1 | reset_code, 0);
        !          1817:        if (rc) {
        !          1818:                return rc;
        !          1819:        }
        !          1820: 
        !          1821:        if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
        !          1822:                /* Adjust the voltage regular to two steps lower.  The default
        !          1823:                 * of this register is 0x0000000e. */
        !          1824:                REG_WR(bp, BNX2_MISC_VREG_CONTROL, 0x000000fa);
        !          1825: 
        !          1826:                /* Remove bad rbuf memory from the free pool. */
        !          1827:                rc = bnx2_alloc_bad_rbuf(bp);
        !          1828:        }
        !          1829: 
        !          1830:        return rc;
        !          1831: }
        !          1832: 
        !          1833: static void
        !          1834: bnx2_disable(struct nic *nic __unused)
        !          1835: {
        !          1836:        struct bnx2* bp = &bnx2;
        !          1837: 
        !          1838:        if (bp->regview) {
        !          1839:                bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_UNLOAD);
        !          1840:                iounmap(bp->regview);
        !          1841:        }
        !          1842: }
        !          1843: 
        !          1844: static int
        !          1845: bnx2_init_chip(struct bnx2 *bp)
        !          1846: {
        !          1847:        u32 val;
        !          1848:        int rc;
        !          1849: 
        !          1850:        /* Make sure the interrupt is not active. */
        !          1851:        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, BNX2_PCICFG_INT_ACK_CMD_MASK_INT);
        !          1852: 
        !          1853:        val = BNX2_DMA_CONFIG_DATA_BYTE_SWAP |
        !          1854:              BNX2_DMA_CONFIG_DATA_WORD_SWAP |
        !          1855: #if __BYTE_ORDER ==  __BIG_ENDIAN
        !          1856:              BNX2_DMA_CONFIG_CNTL_BYTE_SWAP | 
        !          1857: #endif
        !          1858:              BNX2_DMA_CONFIG_CNTL_WORD_SWAP | 
        !          1859:              DMA_READ_CHANS << 12 |
        !          1860:              DMA_WRITE_CHANS << 16;
        !          1861: 
        !          1862:        val |= (0x2 << 20) | (1 << 11);
        !          1863: 
        !          1864:        if ((bp->flags & PCIX_FLAG) && (bp->bus_speed_mhz == 133))
        !          1865:                val |= (1 << 23);
        !          1866: 
        !          1867:        if ((CHIP_NUM(bp) == CHIP_NUM_5706) &&
        !          1868:            (CHIP_ID(bp) != CHIP_ID_5706_A0) && !(bp->flags & PCIX_FLAG))
        !          1869:                val |= BNX2_DMA_CONFIG_CNTL_PING_PONG_DMA;
        !          1870: 
        !          1871:        REG_WR(bp, BNX2_DMA_CONFIG, val);
        !          1872: 
        !          1873:        if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
        !          1874:                val = REG_RD(bp, BNX2_TDMA_CONFIG);
        !          1875:                val |= BNX2_TDMA_CONFIG_ONE_DMA;
        !          1876:                REG_WR(bp, BNX2_TDMA_CONFIG, val);
        !          1877:        }
        !          1878: 
        !          1879:        if (bp->flags & PCIX_FLAG) {
        !          1880:                u16 val16;
        !          1881: 
        !          1882:                pci_read_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
        !          1883:                                     &val16);
        !          1884:                pci_write_config_word(bp->pdev, bp->pcix_cap + PCI_X_CMD,
        !          1885:                                      val16 & ~PCI_X_CMD_ERO);
        !          1886:        }
        !          1887: 
        !          1888:        REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS,
        !          1889:               BNX2_MISC_ENABLE_SET_BITS_HOST_COALESCE_ENABLE |
        !          1890:               BNX2_MISC_ENABLE_STATUS_BITS_RX_V2P_ENABLE |
        !          1891:               BNX2_MISC_ENABLE_STATUS_BITS_CONTEXT_ENABLE);
        !          1892: 
        !          1893:        /* Initialize context mapping and zero out the quick contexts.  The
        !          1894:         * context block must have already been enabled. */
        !          1895:        bnx2_init_context(bp);
        !          1896: 
        !          1897:        bnx2_init_nvram(bp);
        !          1898:        bnx2_init_cpus(bp);
        !          1899: 
        !          1900:        bnx2_set_mac_addr(bp);
        !          1901: 
        !          1902:        val = REG_RD(bp, BNX2_MQ_CONFIG);
        !          1903:        val &= ~BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE;
        !          1904:        val |= BNX2_MQ_CONFIG_KNL_BYP_BLK_SIZE_256;
        !          1905:        REG_WR(bp, BNX2_MQ_CONFIG, val);
        !          1906: 
        !          1907:        val = 0x10000 + (MAX_CID_CNT * MB_KERNEL_CTX_SIZE);
        !          1908:        REG_WR(bp, BNX2_MQ_KNL_BYP_WIND_START, val);
        !          1909:        REG_WR(bp, BNX2_MQ_KNL_WIND_END, val);
        !          1910: 
        !          1911:        val = (BCM_PAGE_BITS - 8) << 24;
        !          1912:        REG_WR(bp, BNX2_RV2P_CONFIG, val);
        !          1913: 
        !          1914:        /* Configure page size. */
        !          1915:        val = REG_RD(bp, BNX2_TBDR_CONFIG);
        !          1916:        val &= ~BNX2_TBDR_CONFIG_PAGE_SIZE;
        !          1917:        val |= (BCM_PAGE_BITS - 8) << 24 | 0x40;
        !          1918:        REG_WR(bp, BNX2_TBDR_CONFIG, val);
        !          1919: 
        !          1920:        val = bp->mac_addr[0] +
        !          1921:              (bp->mac_addr[1] << 8) +
        !          1922:              (bp->mac_addr[2] << 16) +
        !          1923:              bp->mac_addr[3] +
        !          1924:              (bp->mac_addr[4] << 8) +
        !          1925:              (bp->mac_addr[5] << 16);
        !          1926:        REG_WR(bp, BNX2_EMAC_BACKOFF_SEED, val);
        !          1927: 
        !          1928:        /* Program the MTU.  Also include 4 bytes for CRC32. */
        !          1929:        val = ETH_MAX_MTU + ETH_HLEN + 4;
        !          1930:        if (val > (MAX_ETHERNET_PACKET_SIZE + 4))
        !          1931:                val |= BNX2_EMAC_RX_MTU_SIZE_JUMBO_ENA;
        !          1932:        REG_WR(bp, BNX2_EMAC_RX_MTU_SIZE, val);
        !          1933: 
        !          1934:        bp->last_status_idx = 0;
        !          1935:        bp->rx_mode = BNX2_EMAC_RX_MODE_SORT_MODE;
        !          1936: 
        !          1937:        /* Set up how to generate a link change interrupt. */
        !          1938:        REG_WR(bp, BNX2_EMAC_ATTENTION_ENA, BNX2_EMAC_ATTENTION_ENA_LINK);
        !          1939: 
        !          1940:        REG_WR(bp, BNX2_HC_STATUS_ADDR_L,
        !          1941:               (u64) bp->status_blk_mapping & 0xffffffff);
        !          1942:        REG_WR(bp, BNX2_HC_STATUS_ADDR_H, (u64) bp->status_blk_mapping >> 32);
        !          1943: 
        !          1944:        REG_WR(bp, BNX2_HC_STATISTICS_ADDR_L,
        !          1945:               (u64) bp->stats_blk_mapping & 0xffffffff);
        !          1946:        REG_WR(bp, BNX2_HC_STATISTICS_ADDR_H,
        !          1947:               (u64) bp->stats_blk_mapping >> 32);
        !          1948: 
        !          1949:        REG_WR(bp, BNX2_HC_TX_QUICK_CONS_TRIP, 
        !          1950:               (bp->tx_quick_cons_trip_int << 16) | bp->tx_quick_cons_trip);
        !          1951: 
        !          1952:        REG_WR(bp, BNX2_HC_RX_QUICK_CONS_TRIP,
        !          1953:               (bp->rx_quick_cons_trip_int << 16) | bp->rx_quick_cons_trip);
        !          1954: 
        !          1955:        REG_WR(bp, BNX2_HC_COMP_PROD_TRIP,
        !          1956:               (bp->comp_prod_trip_int << 16) | bp->comp_prod_trip);
        !          1957: 
        !          1958:        REG_WR(bp, BNX2_HC_TX_TICKS, (bp->tx_ticks_int << 16) | bp->tx_ticks);
        !          1959: 
        !          1960:        REG_WR(bp, BNX2_HC_RX_TICKS, (bp->rx_ticks_int << 16) | bp->rx_ticks);
        !          1961: 
        !          1962:        REG_WR(bp, BNX2_HC_COM_TICKS,
        !          1963:               (bp->com_ticks_int << 16) | bp->com_ticks);
        !          1964: 
        !          1965:        REG_WR(bp, BNX2_HC_CMD_TICKS,
        !          1966:               (bp->cmd_ticks_int << 16) | bp->cmd_ticks);
        !          1967: 
        !          1968:        REG_WR(bp, BNX2_HC_STATS_TICKS, bp->stats_ticks & 0xffff00);
        !          1969:        REG_WR(bp, BNX2_HC_STAT_COLLECT_TICKS, 0xbb8);  /* 3ms */
        !          1970: 
        !          1971:        if (CHIP_ID(bp) == CHIP_ID_5706_A1)
        !          1972:                REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_COLLECT_STATS);
        !          1973:        else {
        !          1974:                REG_WR(bp, BNX2_HC_CONFIG, BNX2_HC_CONFIG_RX_TMR_MODE |
        !          1975:                       BNX2_HC_CONFIG_TX_TMR_MODE |
        !          1976:                       BNX2_HC_CONFIG_COLLECT_STATS);
        !          1977:        }
        !          1978: 
        !          1979:        /* Clear internal stats counters. */
        !          1980:        REG_WR(bp, BNX2_HC_COMMAND, BNX2_HC_COMMAND_CLR_STAT_NOW);
        !          1981: 
        !          1982:        REG_WR(bp, BNX2_HC_ATTN_BITS_ENABLE, STATUS_ATTN_BITS_LINK_STATE);
        !          1983: 
        !          1984:        if (REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_FEATURE) &
        !          1985:            BNX2_PORT_FEATURE_ASF_ENABLED)
        !          1986:                bp->flags |= ASF_ENABLE_FLAG;
        !          1987: 
        !          1988:        /* Initialize the receive filter. */
        !          1989:        bnx2_set_rx_mode(bp->nic);
        !          1990: 
        !          1991:        rc = bnx2_fw_sync(bp, BNX2_DRV_MSG_DATA_WAIT2 | BNX2_DRV_MSG_CODE_RESET,
        !          1992:                          0);
        !          1993: 
        !          1994:        REG_WR(bp, BNX2_MISC_ENABLE_SET_BITS, 0x5ffffff);
        !          1995:        REG_RD(bp, BNX2_MISC_ENABLE_SET_BITS);
        !          1996: 
        !          1997:        udelay(20);
        !          1998: 
        !          1999:        bp->hc_cmd = REG_RD(bp, BNX2_HC_COMMAND);
        !          2000: 
        !          2001:        return rc;
        !          2002: }
        !          2003: 
        !          2004: static void
        !          2005: bnx2_init_tx_ring(struct bnx2 *bp)
        !          2006: {
        !          2007:        struct tx_bd *txbd;
        !          2008:        u32 val;
        !          2009: 
        !          2010:        txbd = &bp->tx_desc_ring[MAX_TX_DESC_CNT];
        !          2011:                
        !          2012:        /* Etherboot lives below 4GB, so hi is always 0 */
        !          2013:        txbd->tx_bd_haddr_hi = 0;
        !          2014:        txbd->tx_bd_haddr_lo = bp->tx_desc_mapping;
        !          2015: 
        !          2016:        bp->tx_prod = 0;
        !          2017:        bp->tx_cons = 0;
        !          2018:        bp->hw_tx_cons = 0;
        !          2019:        bp->tx_prod_bseq = 0;
        !          2020:        
        !          2021:        val = BNX2_L2CTX_TYPE_TYPE_L2;
        !          2022:        val |= BNX2_L2CTX_TYPE_SIZE_L2;
        !          2023:        CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TYPE, val);
        !          2024: 
        !          2025:        val = BNX2_L2CTX_CMD_TYPE_TYPE_L2;
        !          2026:        val |= 8 << 16;
        !          2027:        CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_CMD_TYPE, val);
        !          2028: 
        !          2029:        /* Etherboot lives below 4GB, so hi is always 0 */
        !          2030:        CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_HI, 0);
        !          2031: 
        !          2032:        val = (u64) bp->tx_desc_mapping & 0xffffffff;
        !          2033:        CTX_WR(bp, GET_CID_ADDR(TX_CID), BNX2_L2CTX_TBDR_BHADDR_LO, val);
        !          2034: }
        !          2035: 
        !          2036: static void
        !          2037: bnx2_init_rx_ring(struct bnx2 *bp)
        !          2038: {
        !          2039:        struct rx_bd *rxbd;
        !          2040:        unsigned int i;
        !          2041:        u16 prod, ring_prod;
        !          2042:        u32 val;
        !          2043: 
        !          2044:        bp->rx_buf_use_size = RX_BUF_USE_SIZE;
        !          2045:        bp->rx_buf_size = RX_BUF_SIZE;
        !          2046: 
        !          2047:        ring_prod = prod = bp->rx_prod = 0;
        !          2048:        bp->rx_cons = 0;
        !          2049:        bp->hw_rx_cons = 0;
        !          2050:        bp->rx_prod_bseq = 0;
        !          2051: 
        !          2052:        memset(bnx2_bss.rx_buf, 0, sizeof(bnx2_bss.rx_buf));
        !          2053:                
        !          2054:        rxbd = &bp->rx_desc_ring[0];
        !          2055:        for (i = 0; i < MAX_RX_DESC_CNT; i++, rxbd++) {
        !          2056:                rxbd->rx_bd_len = bp->rx_buf_use_size;
        !          2057:                rxbd->rx_bd_flags = RX_BD_FLAGS_START | RX_BD_FLAGS_END;
        !          2058:        }
        !          2059:        rxbd->rx_bd_haddr_hi = 0;
        !          2060:        rxbd->rx_bd_haddr_lo = (u64) bp->rx_desc_mapping & 0xffffffff;
        !          2061: 
        !          2062:        val = BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE;
        !          2063:        val |= BNX2_L2CTX_CTX_TYPE_SIZE_L2;
        !          2064:        val |= 0x02 << 8;
        !          2065:        CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_CTX_TYPE, val);
        !          2066: 
        !          2067:        /* Etherboot doesn't use memory above 4GB, so this is always 0 */
        !          2068:        CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_HI, 0);
        !          2069: 
        !          2070:        val = bp->rx_desc_mapping & 0xffffffff;
        !          2071:        CTX_WR(bp, GET_CID_ADDR(RX_CID), BNX2_L2CTX_NX_BDHADDR_LO, val);
        !          2072: 
        !          2073:        for (i = 0; (int) i < bp->rx_ring_size; i++) {
        !          2074:                rxbd = &bp->rx_desc_ring[RX_RING_IDX(ring_prod)];
        !          2075:                rxbd->rx_bd_haddr_hi = 0;
        !          2076:                rxbd->rx_bd_haddr_lo = virt_to_bus(&bnx2_bss.rx_buf[ring_prod][0]);
        !          2077:                bp->rx_prod_bseq += bp->rx_buf_use_size;
        !          2078:                prod = NEXT_RX_BD(prod);
        !          2079:                ring_prod = RX_RING_IDX(prod);
        !          2080:        }
        !          2081:        bp->rx_prod = prod;
        !          2082: 
        !          2083:        REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, bp->rx_prod);
        !          2084: 
        !          2085:        REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
        !          2086: }
        !          2087: 
        !          2088: static int
        !          2089: bnx2_reset_nic(struct bnx2 *bp, u32 reset_code)
        !          2090: {
        !          2091:        int rc;
        !          2092: 
        !          2093:        rc = bnx2_reset_chip(bp, reset_code);
        !          2094:        if (rc) {
        !          2095:                return rc;
        !          2096:        }
        !          2097: 
        !          2098:        bnx2_init_chip(bp);
        !          2099:        bnx2_init_tx_ring(bp);
        !          2100:        bnx2_init_rx_ring(bp);
        !          2101:        return 0;
        !          2102: }
        !          2103: 
        !          2104: static int
        !          2105: bnx2_init_nic(struct bnx2 *bp)
        !          2106: {
        !          2107:        int rc;
        !          2108: 
        !          2109:        if ((rc = bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET)) != 0)
        !          2110:                return rc;
        !          2111: 
        !          2112:        bnx2_init_phy(bp);
        !          2113:        bnx2_set_link(bp);
        !          2114:        return 0;
        !          2115: }
        !          2116: 
        !          2117: static int
        !          2118: bnx2_init_board(struct pci_device *pdev, struct nic *nic)
        !          2119: {
        !          2120:        unsigned long bnx2reg_base, bnx2reg_len;
        !          2121:        struct bnx2 *bp = &bnx2;
        !          2122:        int rc;
        !          2123:        u32 reg;
        !          2124: 
        !          2125:        bp->flags = 0;
        !          2126:        bp->phy_flags = 0;
        !          2127: 
        !          2128:        /* enable device (incl. PCI PM wakeup), and bus-mastering */
        !          2129:        adjust_pci_device(pdev);
        !          2130: 
        !          2131:        nic->ioaddr = pdev->ioaddr & ~3;
        !          2132:        nic->irqno = 0;
        !          2133: 
        !          2134:        rc = 0;
        !          2135:        bp->pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
        !          2136:        if (bp->pm_cap == 0) {
        !          2137:                printf("Cannot find power management capability, aborting.\n");
        !          2138:                rc = -EIO;
        !          2139:                goto err_out_disable;
        !          2140:        }
        !          2141: 
        !          2142:        bp->pcix_cap = pci_find_capability(pdev, PCI_CAP_ID_PCIX);
        !          2143:        if (bp->pcix_cap == 0) {
        !          2144:                printf("Cannot find PCIX capability, aborting.\n");
        !          2145:                rc = -EIO;
        !          2146:                goto err_out_disable;
        !          2147:        }
        !          2148: 
        !          2149:        bp->pdev = pdev;
        !          2150:        bp->nic = nic;
        !          2151: 
        !          2152:        bnx2reg_base = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
        !          2153:        bnx2reg_len = MB_GET_CID_ADDR(17);
        !          2154: 
        !          2155:        bp->regview = ioremap(bnx2reg_base, bnx2reg_len);
        !          2156: 
        !          2157:        if (!bp->regview) {
        !          2158:                printf("Cannot map register space, aborting.\n");
        !          2159:                rc = -EIO;
        !          2160:                goto err_out_disable;
        !          2161:        }
        !          2162: 
        !          2163:        /* Configure byte swap and enable write to the reg_window registers.
        !          2164:         * Rely on CPU to do target byte swapping on big endian systems
        !          2165:         * The chip's target access swapping will not swap all accesses
        !          2166:         */
        !          2167:        pci_write_config_dword(bp->pdev, BNX2_PCICFG_MISC_CONFIG,
        !          2168:                               BNX2_PCICFG_MISC_CONFIG_REG_WINDOW_ENA |
        !          2169:                               BNX2_PCICFG_MISC_CONFIG_TARGET_MB_WORD_SWAP);
        !          2170: 
        !          2171:        bnx2_set_power_state_0(bp);
        !          2172: 
        !          2173:        bp->chip_id = REG_RD(bp, BNX2_MISC_ID);
        !          2174: 
        !          2175:        /* Get bus information. */
        !          2176:        reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS);
        !          2177:        if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) {
        !          2178:                u32 clkreg;
        !          2179: 
        !          2180:                bp->flags |= PCIX_FLAG;
        !          2181: 
        !          2182:                clkreg = REG_RD(bp, BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS);
        !          2183:                
        !          2184:                clkreg &= BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET;
        !          2185:                switch (clkreg) {
        !          2186:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_133MHZ:
        !          2187:                        bp->bus_speed_mhz = 133;
        !          2188:                        break;
        !          2189: 
        !          2190:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_95MHZ:
        !          2191:                        bp->bus_speed_mhz = 100;
        !          2192:                        break;
        !          2193: 
        !          2194:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_66MHZ:
        !          2195:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_80MHZ:
        !          2196:                        bp->bus_speed_mhz = 66;
        !          2197:                        break;
        !          2198: 
        !          2199:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_48MHZ:
        !          2200:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_55MHZ:
        !          2201:                        bp->bus_speed_mhz = 50;
        !          2202:                        break;
        !          2203: 
        !          2204:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_LOW:
        !          2205:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_32MHZ:
        !          2206:                case BNX2_PCICFG_PCI_CLOCK_CONTROL_BITS_PCI_CLK_SPD_DET_38MHZ:
        !          2207:                        bp->bus_speed_mhz = 33;
        !          2208:                        break;
        !          2209:                }
        !          2210:        }
        !          2211:        else {
        !          2212:                if (reg & BNX2_PCICFG_MISC_STATUS_M66EN)
        !          2213:                        bp->bus_speed_mhz = 66;
        !          2214:                else
        !          2215:                        bp->bus_speed_mhz = 33;
        !          2216:        }
        !          2217: 
        !          2218:        if (reg & BNX2_PCICFG_MISC_STATUS_32BIT_DET)
        !          2219:                bp->flags |= PCI_32BIT_FLAG;
        !          2220: 
        !          2221:        /* 5706A0 may falsely detect SERR and PERR. */
        !          2222:        if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
        !          2223:                reg = REG_RD(bp, PCI_COMMAND);
        !          2224:                reg &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
        !          2225:                REG_WR(bp, PCI_COMMAND, reg);
        !          2226:        }
        !          2227:        else if ((CHIP_ID(bp) == CHIP_ID_5706_A1) &&
        !          2228:                !(bp->flags & PCIX_FLAG)) {
        !          2229: 
        !          2230:                printf("5706 A1 can only be used in a PCIX bus, aborting.\n");
        !          2231:                goto err_out_disable;
        !          2232:        }
        !          2233: 
        !          2234:        bnx2_init_nvram(bp);
        !          2235: 
        !          2236:        reg = REG_RD_IND(bp, BNX2_SHM_HDR_SIGNATURE);
        !          2237: 
        !          2238:        if ((reg & BNX2_SHM_HDR_SIGNATURE_SIG_MASK) ==
        !          2239:            BNX2_SHM_HDR_SIGNATURE_SIG)
        !          2240:                bp->shmem_base = REG_RD_IND(bp, BNX2_SHM_HDR_ADDR_0);
        !          2241:        else
        !          2242:                bp->shmem_base = HOST_VIEW_SHMEM_BASE;
        !          2243: 
        !          2244:        /* Get the permanent MAC address.  First we need to make sure the
        !          2245:         * firmware is actually running.
        !          2246:         */
        !          2247:        reg = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_SIGNATURE);
        !          2248: 
        !          2249:        if ((reg & BNX2_DEV_INFO_SIGNATURE_MAGIC_MASK) !=
        !          2250:            BNX2_DEV_INFO_SIGNATURE_MAGIC) {
        !          2251:                printf("Firmware not running, aborting.\n");
        !          2252:                rc = -ENODEV;
        !          2253:                goto err_out_disable;
        !          2254:        }
        !          2255: 
        !          2256:        bp->fw_ver = REG_RD_IND(bp, bp->shmem_base + BNX2_DEV_INFO_BC_REV);
        !          2257: 
        !          2258:        reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_UPPER);
        !          2259:        bp->mac_addr[0] = (u8) (reg >> 8);
        !          2260:        bp->mac_addr[1] = (u8) reg;
        !          2261: 
        !          2262:        reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_MAC_LOWER);
        !          2263:        bp->mac_addr[2] = (u8) (reg >> 24);
        !          2264:        bp->mac_addr[3] = (u8) (reg >> 16);
        !          2265:        bp->mac_addr[4] = (u8) (reg >> 8);
        !          2266:        bp->mac_addr[5] = (u8) reg;
        !          2267: 
        !          2268:        bp->tx_ring_size = MAX_TX_DESC_CNT;
        !          2269:        bp->rx_ring_size = RX_BUF_CNT;
        !          2270:        bp->rx_max_ring_idx = MAX_RX_DESC_CNT;
        !          2271: 
        !          2272:        bp->rx_offset = RX_OFFSET;
        !          2273: 
        !          2274:        bp->tx_quick_cons_trip_int = 20;
        !          2275:        bp->tx_quick_cons_trip = 20;
        !          2276:        bp->tx_ticks_int = 80;
        !          2277:        bp->tx_ticks = 80;
        !          2278:                
        !          2279:        bp->rx_quick_cons_trip_int = 6;
        !          2280:        bp->rx_quick_cons_trip = 6;
        !          2281:        bp->rx_ticks_int = 18;
        !          2282:        bp->rx_ticks = 18;
        !          2283: 
        !          2284:        bp->stats_ticks = 1000000 & 0xffff00;
        !          2285: 
        !          2286:        bp->phy_addr = 1;
        !          2287: 
        !          2288:        /* No need for WOL support in Etherboot */
        !          2289:        bp->flags |= NO_WOL_FLAG;
        !          2290: 
        !          2291:        /* Disable WOL support if we are running on a SERDES chip. */
        !          2292:        if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) {
        !          2293:                bp->phy_flags |= PHY_SERDES_FLAG;
        !          2294:                if (CHIP_NUM(bp) == CHIP_NUM_5708) {
        !          2295:                        bp->phy_addr = 2;
        !          2296:                        reg = REG_RD_IND(bp, bp->shmem_base +
        !          2297:                                         BNX2_SHARED_HW_CFG_CONFIG);
        !          2298:                        if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G)
        !          2299:                                bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG;
        !          2300:                }
        !          2301:        }
        !          2302: 
        !          2303:        if (CHIP_ID(bp) == CHIP_ID_5706_A0) {
        !          2304:                bp->tx_quick_cons_trip_int =
        !          2305:                        bp->tx_quick_cons_trip;
        !          2306:                bp->tx_ticks_int = bp->tx_ticks;
        !          2307:                bp->rx_quick_cons_trip_int =
        !          2308:                        bp->rx_quick_cons_trip;
        !          2309:                bp->rx_ticks_int = bp->rx_ticks;
        !          2310:                bp->comp_prod_trip_int = bp->comp_prod_trip;
        !          2311:                bp->com_ticks_int = bp->com_ticks;
        !          2312:                bp->cmd_ticks_int = bp->cmd_ticks;
        !          2313:        }
        !          2314: 
        !          2315:        bp->autoneg = AUTONEG_SPEED | AUTONEG_FLOW_CTRL;
        !          2316:        bp->req_line_speed = 0;
        !          2317:        if (bp->phy_flags & PHY_SERDES_FLAG) {
        !          2318:                bp->advertising = ETHTOOL_ALL_FIBRE_SPEED | ADVERTISED_Autoneg;
        !          2319: 
        !          2320:                reg = REG_RD_IND(bp, bp->shmem_base + BNX2_PORT_HW_CFG_CONFIG);
        !          2321:                reg &= BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK;
        !          2322:                if (reg == BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G) {
        !          2323:                        bp->autoneg = 0;
        !          2324:                        bp->req_line_speed = bp->line_speed = SPEED_1000;
        !          2325:                        bp->req_duplex = DUPLEX_FULL;
        !          2326:                }
        !          2327:        }
        !          2328:        else {
        !          2329:                bp->advertising = ETHTOOL_ALL_COPPER_SPEED | ADVERTISED_Autoneg;
        !          2330:        }
        !          2331: 
        !          2332:        bp->req_flow_ctrl = FLOW_CTRL_RX | FLOW_CTRL_TX;
        !          2333: 
        !          2334:        /* Disable driver heartbeat checking */
        !          2335:        REG_WR_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB,
        !          2336:                        BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE);
        !          2337:        REG_RD_IND(bp, bp->shmem_base + BNX2_DRV_PULSE_MB);
        !          2338: 
        !          2339:        return 0;
        !          2340: 
        !          2341: err_out_disable:
        !          2342:        bnx2_disable(nic);
        !          2343: 
        !          2344:        return rc;
        !          2345: }
        !          2346: 
        !          2347: static void
        !          2348: bnx2_transmit(struct nic *nic, const char *dst_addr,
        !          2349:                unsigned int type, unsigned int size, const char *packet)
        !          2350: {
        !          2351:        /* Sometimes the nic will be behind by a frame.  Using two transmit
        !          2352:         * buffers prevents us from timing out in that case.
        !          2353:         */
        !          2354:        static struct eth_frame {
        !          2355:                uint8_t  dst_addr[ETH_ALEN];
        !          2356:                uint8_t  src_addr[ETH_ALEN];
        !          2357:                uint16_t type;
        !          2358:                uint8_t  data [ETH_FRAME_LEN - ETH_HLEN];
        !          2359:        } frame[2];
        !          2360:        static int frame_idx = 0;
        !          2361:        
        !          2362:        /* send the packet to destination */
        !          2363:        struct tx_bd *txbd;
        !          2364:        struct bnx2 *bp = &bnx2;
        !          2365:        u16 prod, ring_prod;
        !          2366:        u16 hw_cons;
        !          2367:        int i = 0;
        !          2368: 
        !          2369:        prod = bp->tx_prod;
        !          2370:        ring_prod = TX_RING_IDX(prod);
        !          2371:        hw_cons = bp->status_blk->status_tx_quick_consumer_index0;
        !          2372:        if ((hw_cons & MAX_TX_DESC_CNT) == MAX_TX_DESC_CNT) {
        !          2373:                hw_cons++;
        !          2374:        }
        !          2375: 
        !          2376:        while((hw_cons != prod) && (hw_cons != (PREV_TX_BD(prod)))) {
        !          2377:                mdelay(10);     /* give the nic a chance */
        !          2378:                //poll_interruptions();
        !          2379:                if (++i > 500) { /* timeout 5s for transmit */
        !          2380:                        printf("transmit timed out\n");
        !          2381:                        bnx2_disable(bp->nic);
        !          2382:                        bnx2_init_board(bp->pdev, bp->nic);
        !          2383:                        return;
        !          2384:                }
        !          2385:        }
        !          2386:        if (i != 0) {
        !          2387:                printf("#");
        !          2388:        }
        !          2389: 
        !          2390:        /* Copy the packet to the our local buffer */
        !          2391:        memcpy(&frame[frame_idx].dst_addr, dst_addr, ETH_ALEN);
        !          2392:        memcpy(&frame[frame_idx].src_addr, nic->node_addr, ETH_ALEN);
        !          2393:        frame[frame_idx].type = htons(type);
        !          2394:        memset(&frame[frame_idx].data, 0, sizeof(frame[frame_idx].data));
        !          2395:        memcpy(&frame[frame_idx].data, packet, size);
        !          2396: 
        !          2397:        /* Setup the ring buffer entry to transmit */
        !          2398:        txbd = &bp->tx_desc_ring[ring_prod];
        !          2399:        txbd->tx_bd_haddr_hi = 0; /* Etherboot runs under 4GB */
        !          2400:        txbd->tx_bd_haddr_lo = virt_to_bus(&frame[frame_idx]);
        !          2401:        txbd->tx_bd_mss_nbytes = (size + ETH_HLEN);
        !          2402:        txbd->tx_bd_vlan_tag_flags = TX_BD_FLAGS_START | TX_BD_FLAGS_END;
        !          2403: 
        !          2404:        /* Advance to the next entry */
        !          2405:        prod = NEXT_TX_BD(prod);
        !          2406:        frame_idx ^= 1;
        !          2407: 
        !          2408:        bp->tx_prod_bseq += (size + ETH_HLEN);
        !          2409: 
        !          2410:        REG_WR16(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BIDX, prod);
        !          2411:        REG_WR(bp, MB_TX_CID_ADDR + BNX2_L2CTX_TX_HOST_BSEQ, bp->tx_prod_bseq);
        !          2412: 
        !          2413:        wmb();
        !          2414: 
        !          2415:        bp->tx_prod = prod;
        !          2416: }
        !          2417: 
        !          2418: static int
        !          2419: bnx2_poll_link(struct bnx2 *bp)
        !          2420: {
        !          2421:        u32 new_link_state, old_link_state, emac_status;
        !          2422: 
        !          2423:        new_link_state = bp->status_blk->status_attn_bits &
        !          2424:                STATUS_ATTN_BITS_LINK_STATE;
        !          2425: 
        !          2426:        old_link_state = bp->status_blk->status_attn_bits_ack &
        !          2427:                STATUS_ATTN_BITS_LINK_STATE;
        !          2428: 
        !          2429:        if (!new_link_state && !old_link_state) {
        !          2430:                /* For some reason the card doesn't always update the link
        !          2431:                 * status bits properly.  Kick the stupid thing and try again.
        !          2432:                 */
        !          2433:                u32 bmsr;
        !          2434: 
        !          2435:                bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !          2436:                bnx2_read_phy(bp, MII_BMSR, &bmsr);
        !          2437: 
        !          2438:                if ((bp->phy_flags & PHY_SERDES_FLAG) &&
        !          2439:                    (CHIP_NUM(bp) == CHIP_NUM_5706)) {
        !          2440:                        REG_RD(bp, BNX2_EMAC_STATUS);
        !          2441:                }
        !          2442: 
        !          2443:                new_link_state = bp->status_blk->status_attn_bits &
        !          2444:                        STATUS_ATTN_BITS_LINK_STATE;
        !          2445: 
        !          2446:                old_link_state = bp->status_blk->status_attn_bits_ack &
        !          2447:                        STATUS_ATTN_BITS_LINK_STATE;
        !          2448: 
        !          2449:                /* Okay, for some reason the above doesn't work with some
        !          2450:                 * switches (like HP ProCurve). If the above doesn't work,
        !          2451:                 * check the MAC directly to see if we have a link.  Perhaps we
        !          2452:                 * should always check the MAC instead probing the MII.
        !          2453:                 */
        !          2454:                if (!new_link_state && !old_link_state) {
        !          2455:                        emac_status = REG_RD(bp, BNX2_EMAC_STATUS);
        !          2456:                        if (emac_status & BNX2_EMAC_STATUS_LINK_CHANGE) {
        !          2457:                                /* Acknowledge the link change */
        !          2458:                                REG_WR(bp, BNX2_EMAC_STATUS, BNX2_EMAC_STATUS_LINK_CHANGE);
        !          2459:                        } else if (emac_status & BNX2_EMAC_STATUS_LINK) {
        !          2460:                                new_link_state = !old_link_state;
        !          2461:                        }
        !          2462:                }
        !          2463: 
        !          2464:        }
        !          2465: 
        !          2466:        if (new_link_state != old_link_state) {
        !          2467:                if (new_link_state) {
        !          2468:                        REG_WR(bp, BNX2_PCICFG_STATUS_BIT_SET_CMD,
        !          2469:                                STATUS_ATTN_BITS_LINK_STATE);
        !          2470:                }
        !          2471:                else {
        !          2472:                        REG_WR(bp, BNX2_PCICFG_STATUS_BIT_CLEAR_CMD,
        !          2473:                                STATUS_ATTN_BITS_LINK_STATE);
        !          2474:                }
        !          2475: 
        !          2476:                bnx2_set_link(bp);
        !          2477: 
        !          2478:                /* This is needed to take care of transient status
        !          2479:                 * during link changes.
        !          2480:                 */
        !          2481: 
        !          2482:                REG_WR(bp, BNX2_HC_COMMAND,
        !          2483:                       bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
        !          2484:                REG_RD(bp, BNX2_HC_COMMAND);
        !          2485: 
        !          2486:        }
        !          2487: 
        !          2488:        return bp->link_up;
        !          2489: }
        !          2490: 
        !          2491: static int
        !          2492: bnx2_poll(struct nic* nic, int retrieve)
        !          2493: {
        !          2494:        struct bnx2 *bp = &bnx2;
        !          2495:        struct rx_bd *cons_bd, *prod_bd;
        !          2496:        u16 hw_cons, sw_cons, sw_ring_cons, sw_prod, sw_ring_prod;
        !          2497:        struct l2_fhdr *rx_hdr;
        !          2498:        int result = 0;
        !          2499:        unsigned int len;
        !          2500:        unsigned char *data;
        !          2501:        u32 status;
        !          2502:        
        !          2503: #if 0
        !          2504:        if ((bp->status_blk->status_idx == bp->last_status_idx) &&
        !          2505:            (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) &
        !          2506:             BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) {
        !          2507: 
        !          2508:                bp->last_status_idx = bp->status_blk->status_idx;
        !          2509:                REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
        !          2510:               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
        !          2511:               BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
        !          2512:               bp->last_status_idx);
        !          2513:                return 0;
        !          2514:        }
        !          2515: #endif
        !          2516: 
        !          2517:        if ((bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) && !retrieve)
        !          2518:                return 1;
        !          2519: 
        !          2520:        if (bp->status_blk->status_rx_quick_consumer_index0 != bp->rx_cons) {
        !          2521: 
        !          2522:                hw_cons = bp->hw_rx_cons = bp->status_blk->status_rx_quick_consumer_index0;
        !          2523:                if ((hw_cons & MAX_RX_DESC_CNT) == MAX_RX_DESC_CNT) {
        !          2524:                        hw_cons++;
        !          2525:                }
        !          2526:                sw_cons = bp->rx_cons;
        !          2527:                sw_prod = bp->rx_prod;
        !          2528: 
        !          2529:                rmb();
        !          2530:                if (sw_cons != hw_cons) {
        !          2531: 
        !          2532:                        sw_ring_cons = RX_RING_IDX(sw_cons);
        !          2533:                        sw_ring_prod = RX_RING_IDX(sw_prod);
        !          2534: 
        !          2535:                        data = bus_to_virt(bp->rx_desc_ring[sw_ring_cons].rx_bd_haddr_lo);
        !          2536: 
        !          2537:                        rx_hdr = (struct l2_fhdr *)data;
        !          2538:                        len = rx_hdr->l2_fhdr_pkt_len - 4;
        !          2539:                        if ((len > (ETH_MAX_MTU + ETH_HLEN)) ||
        !          2540:                                ((status = rx_hdr->l2_fhdr_status) &
        !          2541:                                (L2_FHDR_ERRORS_BAD_CRC |
        !          2542:                                L2_FHDR_ERRORS_PHY_DECODE |
        !          2543:                                L2_FHDR_ERRORS_ALIGNMENT |
        !          2544:                                L2_FHDR_ERRORS_TOO_SHORT |
        !          2545:                                L2_FHDR_ERRORS_GIANT_FRAME))) {
        !          2546:                                result = 0;
        !          2547:                        }
        !          2548:                        else
        !          2549:                        {
        !          2550:                                nic->packetlen = len;
        !          2551:                                memcpy(nic->packet, data + bp->rx_offset, len);
        !          2552:                                result = 1;
        !          2553:                        }
        !          2554: 
        !          2555:                        /* Reuse the buffer */
        !          2556:                        bp->rx_prod_bseq += bp->rx_buf_use_size;
        !          2557:                        if (sw_cons != sw_prod) {
        !          2558:                                cons_bd = &bp->rx_desc_ring[sw_ring_cons];
        !          2559:                                prod_bd = &bp->rx_desc_ring[sw_ring_prod];
        !          2560:                                prod_bd->rx_bd_haddr_hi = 0; /* Etherboot runs under 4GB */
        !          2561:                                prod_bd->rx_bd_haddr_lo = cons_bd->rx_bd_haddr_lo;
        !          2562:                        }
        !          2563: 
        !          2564:                        sw_cons = NEXT_RX_BD(sw_cons);
        !          2565:                        sw_prod = NEXT_RX_BD(sw_prod);
        !          2566: 
        !          2567:                }
        !          2568: 
        !          2569:                bp->rx_cons = sw_cons;
        !          2570:                bp->rx_prod = sw_prod;
        !          2571: 
        !          2572:                REG_WR16(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BDIDX, bp->rx_prod);
        !          2573: 
        !          2574:                REG_WR(bp, MB_RX_CID_ADDR + BNX2_L2CTX_HOST_BSEQ, bp->rx_prod_bseq);
        !          2575: 
        !          2576:                wmb();
        !          2577: 
        !          2578:        }
        !          2579: 
        !          2580:        bnx2_poll_link(bp);
        !          2581: 
        !          2582: #if 0
        !          2583:        bp->last_status_idx = bp->status_blk->status_idx;
        !          2584:        rmb();
        !          2585: 
        !          2586:        REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD,
        !          2587:               BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID |
        !          2588:               BNX2_PCICFG_INT_ACK_CMD_MASK_INT |
        !          2589:               bp->last_status_idx);
        !          2590: 
        !          2591:        REG_WR(bp, BNX2_HC_COMMAND, bp->hc_cmd | BNX2_HC_COMMAND_COAL_NOW_WO_INT);
        !          2592: #endif
        !          2593: 
        !          2594:        return result;
        !          2595: }
        !          2596: 
        !          2597: static void
        !          2598: bnx2_irq(struct nic *nic __unused, irq_action_t action __unused)
        !          2599: {
        !          2600:        switch ( action ) {
        !          2601:                case DISABLE: break;
        !          2602:                case ENABLE: break;
        !          2603:                case FORCE: break;
        !          2604:        }
        !          2605: }
        !          2606: 
        !          2607: static struct nic_operations bnx2_operations = {
        !          2608:        .connect        = dummy_connect,
        !          2609:        .poll           = bnx2_poll,
        !          2610:        .transmit       = bnx2_transmit,
        !          2611:        .irq            = bnx2_irq,
        !          2612: };
        !          2613: 
        !          2614: static int
        !          2615: bnx2_probe(struct nic *nic, struct pci_device *pdev)
        !          2616: {
        !          2617:        struct bnx2 *bp = &bnx2;
        !          2618:        int i, rc;
        !          2619: 
        !          2620:        if (pdev == 0)
        !          2621:                return 0;
        !          2622: 
        !          2623:        memset(bp, 0, sizeof(*bp));
        !          2624: 
        !          2625:        rc = bnx2_init_board(pdev, nic);
        !          2626:        if (rc < 0) {
        !          2627:                return 0;
        !          2628:        }
        !          2629: 
        !          2630:        /*
        !          2631:        nic->disable = bnx2_disable;
        !          2632:        nic->transmit = bnx2_transmit;
        !          2633:        nic->poll = bnx2_poll;
        !          2634:        nic->irq = bnx2_irq;
        !          2635:        */
        !          2636:        
        !          2637:        nic->nic_op     = &bnx2_operations;
        !          2638: 
        !          2639:        memcpy(nic->node_addr, bp->mac_addr, ETH_ALEN);
        !          2640:        printf("Ethernet addr: %s\n", eth_ntoa( nic->node_addr ) );
        !          2641:        printf("Broadcom NetXtreme II (%c%d) PCI%s %s %dMHz\n",
        !          2642:                (int) ((CHIP_ID(bp) & 0xf000) >> 12) + 'A',
        !          2643:                (int) ((CHIP_ID(bp) & 0x0ff0) >> 4),
        !          2644:                ((bp->flags & PCIX_FLAG) ? "-X" : ""),
        !          2645:                ((bp->flags & PCI_32BIT_FLAG) ? "32-bit" : "64-bit"),
        !          2646:                bp->bus_speed_mhz);
        !          2647: 
        !          2648:        bnx2_set_power_state_0(bp);
        !          2649:        bnx2_disable_int(bp);
        !          2650: 
        !          2651:        bnx2_alloc_mem(bp);
        !          2652: 
        !          2653:        rc = bnx2_init_nic(bp);
        !          2654:        if (rc) {
        !          2655:                return 0;
        !          2656:        }
        !          2657: 
        !          2658:        bnx2_poll_link(bp);
        !          2659:        for(i = 0; !bp->link_up && (i < VALID_LINK_TIMEOUT*100); i++) {
        !          2660:                mdelay(1);
        !          2661:                bnx2_poll_link(bp);
        !          2662:        }
        !          2663: #if 1
        !          2664:        if (!bp->link_up){
        !          2665:                printf("Valid link not established\n");
        !          2666:                goto err_out_disable;
        !          2667:        }
        !          2668: #endif
        !          2669:        
        !          2670:        return 1;
        !          2671: 
        !          2672: err_out_disable:
        !          2673:        bnx2_disable(nic);
        !          2674:        return 0;
        !          2675: }
        !          2676: 
        !          2677: static struct pci_device_id bnx2_nics[] = {
        !          2678:        PCI_ROM(0x14e4, 0x164a, "bnx2-5706",        "Broadcom NetXtreme II BCM5706", 0),
        !          2679:        PCI_ROM(0x14e4, 0x164c, "bnx2-5708",        "Broadcom NetXtreme II BCM5708", 0),
        !          2680:        PCI_ROM(0x14e4, 0x16aa, "bnx2-5706S",       "Broadcom NetXtreme II BCM5706S", 0),
        !          2681:        PCI_ROM(0x14e4, 0x16ac, "bnx2-5708S",       "Broadcom NetXtreme II BCM5708S", 0),
        !          2682: };
        !          2683: 
        !          2684: PCI_DRIVER ( bnx2_driver, bnx2_nics, PCI_NO_CLASS );
        !          2685: 
        !          2686: DRIVER ( "BNX2", nic_driver, pci_driver, bnx2_driver, bnx2_probe, bnx2_disable );
        !          2687: 
        !          2688: /*
        !          2689: static struct pci_driver bnx2_driver __pci_driver = {
        !          2690:        .type     = NIC_DRIVER,
        !          2691:        .name     = "BNX2",              
        !          2692:        .probe    = bnx2_probe,
        !          2693:        .ids      = bnx2_nics,                  
        !          2694:        .id_count = sizeof(bnx2_nics)/sizeof(bnx2_nics[0]), 
        !          2695:        .class    = 0,    
        !          2696: };
        !          2697: */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.