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

Annotation of sys/dev/pci/if_nxe.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: if_nxe.c,v 1.40 2007/08/15 10:24:54 dlg Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include "bpfilter.h"
                     20:
                     21: #include <sys/param.h>
                     22: #include <sys/systm.h>
                     23: #include <sys/sockio.h>
                     24: #include <sys/mbuf.h>
                     25: #include <sys/kernel.h>
                     26: #include <sys/socket.h>
                     27: #include <sys/malloc.h>
                     28: #include <sys/device.h>
                     29: #include <sys/proc.h>
                     30: #include <sys/queue.h>
                     31: #include <sys/timeout.h>
                     32: #include <sys/sensors.h>
                     33: #include <sys/rwlock.h>
                     34:
                     35: #include <machine/bus.h>
                     36:
                     37: #include <dev/pci/pcireg.h>
                     38: #include <dev/pci/pcivar.h>
                     39: #include <dev/pci/pcidevs.h>
                     40:
                     41: #include <net/if.h>
                     42: #include <net/if_dl.h>
                     43: #include <net/if_media.h>
                     44: #include <net/if_types.h>
                     45:
                     46: #if NBPFILTER > 0
                     47: #include <net/bpf.h>
                     48: #endif
                     49:
                     50: #ifdef INET
                     51: #include <netinet/in.h>
                     52: #include <netinet/if_ether.h>
                     53: #endif
                     54:
                     55: #ifdef NXE_DEBUG
                     56: int nxedebug = 0;
                     57:
                     58: #define DPRINTF(l, f...)       do { if (nxedebug & (l)) printf(f); } while (0)
                     59: #define DASSERT(_a)            assert(_a)
                     60: #else
                     61: #define DPRINTF(l, f...)
                     62: #define DASSERT(_a)
                     63: #endif
                     64:
                     65: /* this driver likes firmwares around this version */
                     66: #define NXE_VERSION_MAJOR      3
                     67: #define NXE_VERSION_MINOR      4
                     68: #define NXE_VERSION_BUILD      31
                     69: #define NXE_VERSION \
                     70:     ((NXE_VERSION_MAJOR << 16)|(NXE_VERSION_MINOR << 8)|(NXE_VERSION_BUILD))
                     71:
                     72:
                     73: /*
                     74:  * PCI configuration space registers
                     75:  */
                     76:
                     77: #define NXE_PCI_BAR_MEM                0x10 /* bar 0 */
                     78: #define NXE_PCI_BAR_MEM_128MB          (128 * 1024 * 1024)
                     79: #define NXE_PCI_BAR_DOORBELL   0x20 /* bar 4 */
                     80:
                     81: /*
                     82:  * doorbell register space
                     83:  */
                     84:
                     85: #define NXE_DB                 0x00000000
                     86: #define  NXE_DB_PEGID                  0x00000003
                     87: #define  NXE_DB_PEGID_RX               0x00000001 /* rx unit */
                     88: #define  NXE_DB_PEGID_TX               0x00000002 /* tx unit */
                     89: #define  NXE_DB_PRIVID                 0x00000004 /* must be set */
                     90: #define  NXE_DB_COUNT(_c)              ((_c)<<3) /* count */
                     91: #define  NXE_DB_CTXID(_c)              ((_c)<<18) /* context id */
                     92: #define  NXE_DB_OPCODE_RX_PROD         0x00000000
                     93: #define  NXE_DB_OPCODE_RX_JUMBO_PROD   0x10000000
                     94: #define  NXE_DB_OPCODE_RX_LRO_PROD     0x20000000
                     95: #define  NXE_DB_OPCODE_CMD_PROD                0x30000000
                     96: #define  NXE_DB_OPCODE_UPD_CONS                0x40000000
                     97: #define  NXE_DB_OPCODE_RESET_CTX       0x50000000
                     98:
                     99: /*
                    100:  * register space
                    101:  */
                    102:
                    103: /* different PCI functions use different registers sometimes */
                    104: #define _F(_f)                 ((_f) * 0x20)
                    105:
                    106: /*
                    107:  * driver ref section 4.2
                    108:  *
                    109:  * All the hardware registers are mapped in memory. Apart from the registers
                    110:  * for the individual hardware blocks, the memory map includes a large number
                    111:  * of software definable registers.
                    112:  *
                    113:  * The following table gives the memory map in the PCI address space.
                    114:  */
                    115:
                    116: #define NXE_MAP_DDR_NET                0x00000000
                    117: #define NXE_MAP_DDR_MD         0x02000000
                    118: #define NXE_MAP_QDR_NET                0x04000000
                    119: #define NXE_MAP_DIRECT_CRB     0x04400000
                    120: #define NXE_MAP_OCM0           0x05000000
                    121: #define NXE_MAP_OCM1           0x05100000
                    122: #define NXE_MAP_CRB            0x06000000
                    123:
                    124: /*
                    125:  * Since there are a large number of registers they do not fit in a single
                    126:  * PCI addressing range. Hence two windows are defined. The window starts at
                    127:  * NXE_MAP_CRB, and extends to the end of the register map. The window is set
                    128:  * using the NXE_REG_WINDOW_CRB register. The format of the NXE_REG_WINDOW_CRB
                    129:  * register is as follows:
                    130:  */
                    131:
                    132: #define NXE_WIN_CRB(_f)                (0x06110210 + _F(_f))
                    133: #define  NXE_WIN_CRB_0                 (0<<25)
                    134: #define  NXE_WIN_CRB_1                 (1<<25)
                    135:
                    136: /*
                    137:  * The memory map inside the register windows are divided into a set of blocks.
                    138:  * Each register block is owned by one hardware agent. The following table
                    139:  * gives the memory map of the various register blocks in window 0. These
                    140:  * registers are all in the CRB register space, so the offsets given here are
                    141:  * relative to the base of the CRB offset region (NXE_MAP_CRB).
                    142:  */
                    143:
                    144: #define NXE_W0_PCIE            0x00100000 /* PCI Express */
                    145: #define NXE_W0_NIU             0x00600000 /* Network Interface Unit */
                    146: #define NXE_W0_PPE_0           0x01100000 /* Protocol Processing Engine 0 */
                    147: #define NXE_W0_PPE_1           0x01200000 /* Protocol Processing Engine 1 */
                    148: #define NXE_W0_PPE_2           0x01300000 /* Protocol Processing Engine 2 */
                    149: #define NXE_W0_PPE_3           0x01400000 /* Protocol Processing Engine 3 */
                    150: #define NXE_W0_PPE_D           0x01500000 /* PPE D-cache */
                    151: #define NXE_W0_PPE_I           0x01600000 /* PPE I-cache */
                    152:
                    153: /*
                    154:  * These are the register blocks inside window 1.
                    155:  */
                    156:
                    157: #define NXE_W1_PCIE            0x00100000
                    158: #define NXE_W1_SW              0x00200000
                    159: #define NXE_W1_SIR             0x01200000
                    160: #define NXE_W1_ROMUSB          0x01300000
                    161:
                    162: /*
                    163:  * Global registers
                    164:  */
                    165: #define NXE_BOOTLD_START       0x00010000
                    166:
                    167:
                    168: /*
                    169:  * driver ref section 5
                    170:  *
                    171:  * CRB Window Register Descriptions
                    172:  */
                    173:
                    174: /*
                    175:  * PCI Express Registers
                    176:  *
                    177:  * Despite being in the CRB window space, they can be accessed via both
                    178:  * windows. This means they are accessable "globally" without going relative
                    179:  * to the start of the CRB window space.
                    180:  */
                    181:
                    182: /* Interrupts */
                    183: #define NXE_ISR_VECTOR         0x06110100 /* Interrupt Vector */
                    184: #define  NXE_ISR_VECTOR_FUNC(_f)       (0x08 << (_f))
                    185: #define NXE_ISR_MASK           0x06110104 /* Interrupt Mask */
                    186: #define NXE_ISR_TARGET_STATUS  0x06110118
                    187: #define NXE_ISR_TARGET_MASK    0x06110128
                    188:
                    189: /* lock registers (semaphores between chipset and driver) */
                    190: #define NXE_SEM_ROM_LOCK       0x0611c010 /* ROM access lock */
                    191: #define NXE_SEM_ROM_UNLOCK     0x0611c014
                    192: #define NXE_SEM_PHY_LOCK       0x0611c018 /* PHY access lock */
                    193: #define NXE_SEM_PHY_UNLOCK     0x0611c01c
                    194: #define  NXE_SEM_DONE                  0x1
                    195:
                    196: /*
                    197:  * Network Interface Unit (NIU) Registers
                    198:  */
                    199:
                    200: #define NXE_0_NIU_MODE         0x00600000
                    201: #define  NXE_0_NIU_MODE_XGE            (1<<2) /* XGE interface enabled */
                    202: #define  NXE_0_NIU_MODE_GBE            (1<<1) /* 4 GbE interfaces enabled */
                    203: #define NXE_0_NIU_SINGLE_TERM  0x00600004
                    204:
                    205: #define NXE_0_NIU_RESET_XG     0x0060001c /* reset XG */
                    206: #define NXE_0_NIU_RESET_FIFO   0x00600088 /* reset sys fifos */
                    207:
                    208: #define _P(_p)                 ((_p) * 0x10000)
                    209:
                    210: #define NXE_0_XG_CFG0(_p)      (0x00670000 + _P(_p))
                    211: #define  NXE_0_XG_CFG0_TX_EN           (1<<0) /* TX enable */
                    212: #define  NXE_0_XG_CFG0_TX_SYNC         (1<<1) /* TX synced */
                    213: #define  NXE_0_XG_CFG0_RX_EN           (1<<2) /* RX enable */
                    214: #define  NXE_0_XG_CFG0_RX_SYNC         (1<<3) /* RX synced */
                    215: #define  NXE_0_XG_CFG0_TX_FLOWCTL      (1<<4) /* enable pause frame gen */
                    216: #define  NXE_0_XG_CFG0_RX_FLOWCTL      (1<<5) /* act on rxed pause frames */
                    217: #define  NXE_0_XG_CFG0_LOOPBACK                (1<<8) /* tx appears on rx */
                    218: #define  NXE_0_XG_CFG0_TX_RST_PB       (1<<15) /* reset frm tx proto block */
                    219: #define  NXE_0_XG_CFG0_RX_RST_PB       (1<<16) /* reset frm rx proto block */
                    220: #define  NXE_0_XG_CFG0_TX_RST_MAC      (1<<17) /* reset frm tx multiplexer */
                    221: #define  NXE_0_XG_CFG0_RX_RST_MAC      (1<<18) /* reset ctl frms and timers */
                    222: #define  NXE_0_XG_CFG0_SOFT_RST                (1<<31) /* soft reset */
                    223: #define NXE_0_XG_CFG1(_p)      (0x00670004 + _P(_p))
                    224: #define  NXE_0_XG_CFG1_REM_CRC         (1<<0) /* enable crc removal */
                    225: #define  NXE_0_XG_CFG1_CRC_EN          (1<<1) /* append crc to tx frames */
                    226: #define  NXE_0_XG_CFG1_NO_MAX          (1<<5) /* rx all frames despite size */
                    227: #define  NXE_0_XG_CFG1_WIRE_LO_ERR     (1<<6) /* recognize local err */
                    228: #define  NXE_0_XG_CFG1_PAUSE_FR_DIS    (1<<8) /* disable pause frame detect */
                    229: #define  NXE_0_XG_CFG1_SEQ_ERR_EN      (1<<10) /* enable seq err detection */
                    230: #define  NXE_0_XG_CFG1_MULTICAST       (1<<12) /* accept all multicast */
                    231: #define  NXE_0_XG_CFG1_PROMISC         (1<<13) /* accept all multicast */
                    232: #define NXE_0_XG_MAC_LO(_p)    (0x00670010 + _P(_p))
                    233: #define NXE_0_XG_MAC_HI(_p)    (0x0067000c + _P(_p))
                    234:
                    235: /*
                    236:  * Software Defined Registers
                    237:  */
                    238:
                    239: /* chipset state registers */
                    240: #define NXE_1_SW_ROM_LOCK_ID   0x00202100
                    241: #define  NXE_1_SW_ROM_LOCK_ID_DRV      0x0d417340
                    242: #define NXE_1_SW_PHY_LOCK_ID   0x00202120
                    243: #define  NXE_1_SW_PHY_LOCK_ID_DRV      0x44524956
                    244:
                    245: /* firmware version */
                    246: #define NXE_1_SW_FWVER_MAJOR   0x00202150 /* Major f/w version */
                    247: #define NXE_1_SW_FWVER_MINOR   0x00202154 /* Minor f/w version */
                    248: #define NXE_1_SW_FWVER_BUILD   0x00202158 /* Build/Sub f/w version */
                    249:
                    250: /* misc */
                    251: #define NXE_1_SW_CMD_ADDR_HI   0x00202218 /* cmd ring phys addr */
                    252: #define NXE_1_SW_CMD_ADDR_LO   0x0020221c /* cmd ring phys addr */
                    253: #define NXE_1_SW_CMD_SIZE      0x002022c8 /* entries in the cmd ring */
                    254: #define NXE_1_SW_DUMMY_ADDR_HI 0x0020223c /* hi address of dummy buf */
                    255: #define NXE_1_SW_DUMMY_ADDR_LO 0x00202240 /* lo address of dummy buf */
                    256: #define  NXE_1_SW_DUMMY_ADDR_LEN       1024
                    257:
                    258: static const u_int32_t nxe_regmap[][4] = {
                    259: #define NXE_1_SW_CMD_PRODUCER(_f)      (nxe_regmap[0][(_f)])
                    260:     { 0x00202208, 0x002023ac, 0x002023b8, 0x002023d0 },
                    261: #define NXE_1_SW_CMD_CONSUMER(_f)      (nxe_regmap[1][(_f)])
                    262:     { 0x0020220c, 0x002023b0, 0x002023bc, 0x002023d4 },
                    263:
                    264: #define NXE_1_SW_CONTEXT(_p)           (nxe_regmap[2][(_p)])
                    265: #define NXE_1_SW_CONTEXT_SIG(_p)       (0xdee0 | (_p))
                    266:     { 0x0020238c, 0x00202390, 0x0020239c, 0x002023a4 },
                    267: #define NXE_1_SW_CONTEXT_ADDR_LO(_p)   (nxe_regmap[3][(_p)])
                    268:     { 0x00202388, 0x00202390, 0x00202398, 0x002023a0 },
                    269: #define NXE_1_SW_CONTEXT_ADDR_HI(_p)   (nxe_regmap[4][(_p)])
                    270:     { 0x002023c0, 0x002023c4, 0x002023c8, 0x002023cc },
                    271:
                    272: #define NXE_1_SW_INT_MASK(_p)          (nxe_regmap[5][(_p)])
                    273:     { 0x002023d8, 0x082023e0, 0x082023e4, 0x082023e8 },
                    274:
                    275: #define NXE_1_SW_RX_PRODUCER(_c)       (nxe_regmap[6][(_c)])
                    276:     { 0x00202300, 0x00202344, 0x002023d8, 0x0020242c },
                    277: #define NXE_1_SW_RX_CONSUMER(_c)       (nxe_regmap[7][(_c)])
                    278:     { 0x00202304, 0x00202348, 0x002023dc, 0x00202430 },
                    279: #define NXE_1_SW_RX_RING(_c)           (nxe_regmap[8][(_c)])
                    280:     { 0x00202308, 0x0020234c, 0x002023f0, 0x00202434 },
                    281: #define NXE_1_SW_RX_SIZE(_c)           (nxe_regmap[9][(_c)])
                    282:     { 0x0020230c, 0x00202350, 0x002023f4, 0x00202438 },
                    283:
                    284: #define NXE_1_SW_RX_JUMBO_PRODUCER(_c) (nxe_regmap[10][(_c)])
                    285:     { 0x00202310, 0x00202354, 0x002023f8, 0x0020243c },
                    286: #define NXE_1_SW_RX_JUMBO_CONSUMER(_c) (nxe_regmap[11][(_c)])
                    287:     { 0x00202314, 0x00202358, 0x002023fc, 0x00202440 },
                    288: #define NXE_1_SW_RX_JUMBO_RING(_c)     (nxe_regmap[12][(_c)])
                    289:     { 0x00202318, 0x0020235c, 0x00202400, 0x00202444 },
                    290: #define NXE_1_SW_RX_JUMBO_SIZE(_c)     (nxe_regmap[13][(_c)])
                    291:     { 0x0020231c, 0x00202360, 0x00202404, 0x00202448 },
                    292:
                    293: #define NXE_1_SW_RX_LRO_PRODUCER(_c)   (nxe_regmap[14][(_c)])
                    294:     { 0x00202320, 0x00202364, 0x00202408, 0x0020244c },
                    295: #define NXE_1_SW_RX_LRO_CONSUMER(_c)   (nxe_regmap[15][(_c)])
                    296:     { 0x00202324, 0x00202368, 0x0020240c, 0x00202450 },
                    297: #define NXE_1_SW_RX_LRO_RING(_c)       (nxe_regmap[16][(_c)])
                    298:     { 0x00202328, 0x0020236c, 0x00202410, 0x00202454 },
                    299: #define NXE_1_SW_RX_LRO_SIZE(_c)       (nxe_regmap[17][(_c)])
                    300:     { 0x0020232c, 0x00202370, 0x00202414, 0x00202458 },
                    301:
                    302: #define NXE_1_SW_STATUS_RING(_c)       (nxe_regmap[18][(_c)])
                    303:     { 0x00202330, 0x00202374, 0x00202418, 0x0020245c },
                    304: #define NXE_1_SW_STATUS_PRODUCER(_c)   (nxe_regmap[19][(_c)])
                    305:     { 0x00202334, 0x00202378, 0x0020241c, 0x00202460 },
                    306: #define NXE_1_SW_STATUS_CONSUMER(_c)   (nxe_regmap[20][(_c)])
                    307:     { 0x00202338, 0x0020237c, 0x00202420, 0x00202464 },
                    308: #define NXE_1_SW_STATUS_STATE(_c)      (nxe_regmap[21][(_c)])
                    309: #define  NXE_1_SW_STATUS_STATE_READY           0x0000ff01
                    310:     { 0x0020233c, 0x00202380, 0x00202424, 0x00202468 },
                    311: #define NXE_1_SW_STATUS_SIZE(_c)       (nxe_regmap[22][(_c)])
                    312:     { 0x00202340, 0x00202384, 0x00202428, 0x0020246c }
                    313: };
                    314:
                    315:
                    316: #define NXE_1_SW_BOOTLD_CONFIG 0x002021fc
                    317: #define  NXE_1_SW_BOOTLD_CONFIG_ROM    0x00000000
                    318: #define  NXE_1_SW_BOOTLD_CONFIG_RAM    0x12345678
                    319:
                    320: #define NXE_1_SW_CMDPEG_STATE  0x00202250 /* init status */
                    321: #define  NXE_1_SW_CMDPEG_STATE_START   0xff00 /* init starting */
                    322: #define  NXE_1_SW_CMDPEG_STATE_DONE    0xff01 /* init complete */
                    323: #define  NXE_1_SW_CMDPEG_STATE_ACK     0xf00f /* init ack */
                    324: #define  NXE_1_SW_CMDPEG_STATE_ERROR   0xffff /* init failed */
                    325:
                    326: #define NXE_1_SW_XG_STATE      0x00202294 /* phy state */
                    327: #define  NXE_1_SW_XG_STATE_PORT(_r, _p)        (((_r)>>8*(_p))&0xff)
                    328: #define  NXE_1_SW_XG_STATE_UP          (1<<4)
                    329: #define  NXE_1_SW_XG_STATE_DOWN                (1<<5)
                    330:
                    331: #define NXE_1_SW_MPORT_MODE    0x002022c4
                    332: #define  NXE_1_SW_MPORT_MODE_SINGLE    0x1111
                    333: #define  NXE_1_SW_MPORT_MODE_MULTI     0x2222
                    334:
                    335: #define NXE_1_SW_NIC_CAP_HOST  0x002023a8 /* host capabilities */
                    336: #define  NXE_1_SW_NIC_CAP_HOST_DEF     0x1 /* nfi */
                    337:
                    338: #define  NXE_1_SW_DRIVER_VER   0x002024a0 /* host driver version */
                    339:
                    340:
                    341: #define NXE_1_SW_TEMP          0x002023b4 /* Temperature sensor */
                    342: #define  NXE_1_SW_TEMP_STATE(_x)       ((_x)&0xffff) /* Temp state */
                    343: #define  NXE_1_SW_TEMP_STATE_NONE      0x0000
                    344: #define  NXE_1_SW_TEMP_STATE_OK                0x0001
                    345: #define  NXE_1_SW_TEMP_STATE_WARN      0x0002
                    346: #define  NXE_1_SW_TEMP_STATE_CRIT      0x0003
                    347: #define  NXE_1_SW_TEMP_VAL(_x)         (((_x)>>16)&0xffff) /* Temp value */
                    348:
                    349: #define NXE_1_SW_V2P(_f)       (0x00202490+((_f)*4)) /* virtual to phys */
                    350:
                    351: /*
                    352:  * ROMUSB Registers
                    353:  */
                    354: #define NXE_1_ROMUSB_STATUS    0x01300004 /* ROM Status */
                    355: #define  NXE_1_ROMUSB_STATUS_DONE      (1<<1)
                    356: #define NXE_1_ROMUSB_SW_RESET  0x01300008
                    357: #define NXE_1_ROMUSB_SW_RESET_DEF      0xffffffff
                    358: #define NXE_1_ROMUSB_SW_RESET_BOOT     0x0080000f
                    359:
                    360: #define NXE_1_CASPER_RESET     0x01300038
                    361: #define  NXE_1_CASPER_RESET_ENABLE     0x1
                    362: #define  NXE_1_CASPER_RESET_DISABLE    0x1
                    363:
                    364: #define NXE_1_GLB_PEGTUNE      0x0130005c /* reset register */
                    365: #define  NXE_1_GLB_PEGTUNE_DONE                0x00000001
                    366:
                    367: #define NXE_1_GLB_CHIPCLKCTL   0x013000a8
                    368: #define NXE_1_GLB_CHIPCLKCTL_ON                0x00003fff
                    369:
                    370: /* ROM Registers */
                    371: #define NXE_1_ROM_CONTROL      0x01310000
                    372: #define NXE_1_ROM_OPCODE       0x01310004
                    373: #define  NXE_1_ROM_OPCODE_READ         0x0000000b
                    374: #define NXE_1_ROM_ADDR         0x01310008
                    375: #define NXE_1_ROM_WDATA                0x0131000c
                    376: #define NXE_1_ROM_ABYTE_CNT    0x01310010
                    377: #define NXE_1_ROM_DBYTE_CNT    0x01310014 /* dummy byte count */
                    378: #define NXE_1_ROM_RDATA                0x01310018
                    379: #define NXE_1_ROM_AGT_TAG      0x0131001c
                    380: #define NXE_1_ROM_TIME_PARM    0x01310020
                    381: #define NXE_1_ROM_CLK_DIV      0x01310024
                    382: #define NXE_1_ROM_MISS_INSTR   0x01310028
                    383:
                    384: /*
                    385:  * flash memory layout
                    386:  *
                    387:  * These are offsets of memory accessable via the ROM Registers above
                    388:  */
                    389: #define NXE_FLASH_CRBINIT      0x00000000 /* crb init section */
                    390: #define NXE_FLASH_BRDCFG       0x00004000 /* board config */
                    391: #define NXE_FLASH_INITCODE     0x00006000 /* pegtune code */
                    392: #define NXE_FLASH_BOOTLD       0x00010000 /* boot loader */
                    393: #define NXE_FLASH_IMAGE                0x00043000 /* compressed image */
                    394: #define NXE_FLASH_SECONDARY    0x00200000 /* backup image */
                    395: #define NXE_FLASH_PXE          0x003d0000 /* pxe image */
                    396: #define NXE_FLASH_USER         0x003e8000 /* user region for new boards */
                    397: #define NXE_FLASH_VPD          0x003e8c00 /* vendor private data */
                    398: #define NXE_FLASH_LICENSE      0x003e9000 /* firmware license */
                    399: #define NXE_FLASH_FIXED                0x003f0000 /* backup of crbinit */
                    400:
                    401:
                    402: /*
                    403:  * misc hardware details
                    404:  */
                    405: #define NXE_MAX_PORTS          4
                    406: #define NXE_MAX_PORT_LLADDRS   32
                    407: #define NXE_MAX_PKTLEN         (64 * 1024)
                    408:
                    409:
                    410: /*
                    411:  * hardware structures
                    412:  */
                    413:
                    414: struct nxe_info {
                    415:        u_int32_t               ni_hdrver;
                    416: #define NXE_INFO_HDRVER_1              0x00000001
                    417:
                    418:        u_int32_t               ni_board_mfg;
                    419:        u_int32_t               ni_board_type;
                    420: #define NXE_BRDTYPE_P1_BD              0x0000
                    421: #define NXE_BRDTYPE_P1_SB              0x0001
                    422: #define NXE_BRDTYPE_P1_SMAX            0x0002
                    423: #define NXE_BRDTYPE_P1_SOCK            0x0003
                    424: #define NXE_BRDTYPE_P2_SOCK_31         0x0008
                    425: #define NXE_BRDTYPE_P2_SOCK_35         0x0009
                    426: #define NXE_BRDTYPE_P2_SB35_4G         0x000a
                    427: #define NXE_BRDTYPE_P2_SB31_10G                0x000b
                    428: #define NXE_BRDTYPE_P2_SB31_2G         0x000c
                    429: #define NXE_BRDTYPE_P2_SB31_10G_IMEZ   0x000d
                    430: #define NXE_BRDTYPE_P2_SB31_10G_HMEZ   0x000e
                    431: #define NXE_BRDTYPE_P2_SB31_10G_CX4    0x000f
                    432:        u_int32_t               ni_board_num;
                    433:
                    434:        u_int32_t               ni_chip_id;
                    435:        u_int32_t               ni_chip_minor;
                    436:        u_int32_t               ni_chip_major;
                    437:        u_int32_t               ni_chip_pkg;
                    438:        u_int32_t               ni_chip_lot;
                    439:
                    440:        u_int32_t               ni_port_mask;
                    441:        u_int32_t               ni_peg_mask;
                    442:        u_int32_t               ni_icache;
                    443:        u_int32_t               ni_dcache;
                    444:        u_int32_t               ni_casper;
                    445:
                    446:        u_int32_t               ni_lladdr0_low;
                    447:        u_int32_t               ni_lladdr1_low;
                    448:        u_int32_t               ni_lladdr2_low;
                    449:        u_int32_t               ni_lladdr3_low;
                    450:
                    451:        u_int32_t               ni_mnsync_mode;
                    452:        u_int32_t               ni_mnsync_shift_cclk;
                    453:        u_int32_t               ni_mnsync_shift_mclk;
                    454:        u_int32_t               ni_mnwb_enable;
                    455:        u_int32_t               ni_mnfreq_crystal;
                    456:        u_int32_t               ni_mnfreq_speed;
                    457:        u_int32_t               ni_mnorg;
                    458:        u_int32_t               ni_mndepth;
                    459:        u_int32_t               ni_mnranks0;
                    460:        u_int32_t               ni_mnranks1;
                    461:        u_int32_t               ni_mnrd_latency0;
                    462:        u_int32_t               ni_mnrd_latency1;
                    463:        u_int32_t               ni_mnrd_latency2;
                    464:        u_int32_t               ni_mnrd_latency3;
                    465:        u_int32_t               ni_mnrd_latency4;
                    466:        u_int32_t               ni_mnrd_latency5;
                    467:        u_int32_t               ni_mnrd_latency6;
                    468:        u_int32_t               ni_mnrd_latency7;
                    469:        u_int32_t               ni_mnrd_latency8;
                    470:        u_int32_t               ni_mndll[18];
                    471:        u_int32_t               ni_mnddr_mode;
                    472:        u_int32_t               ni_mnddr_extmode;
                    473:        u_int32_t               ni_mntiming0;
                    474:        u_int32_t               ni_mntiming1;
                    475:        u_int32_t               ni_mntiming2;
                    476:
                    477:        u_int32_t               ni_snsync_mode;
                    478:        u_int32_t               ni_snpt_mode;
                    479:        u_int32_t               ni_snecc_enable;
                    480:        u_int32_t               ni_snwb_enable;
                    481:        u_int32_t               ni_snfreq_crystal;
                    482:        u_int32_t               ni_snfreq_speed;
                    483:        u_int32_t               ni_snorg;
                    484:        u_int32_t               ni_sndepth;
                    485:        u_int32_t               ni_sndll;
                    486:        u_int32_t               ni_snrd_latency;
                    487:
                    488:        u_int32_t               ni_lladdr0_high;
                    489:        u_int32_t               ni_lladdr1_high;
                    490:        u_int32_t               ni_lladdr2_high;
                    491:        u_int32_t               ni_lladdr3_high;
                    492:
                    493:        u_int32_t               ni_magic;
                    494: #define NXE_INFO_MAGIC                 0x12345678
                    495:
                    496:        u_int32_t               ni_mnrd_imm;
                    497:        u_int32_t               ni_mndll_override;
                    498: } __packed;
                    499:
                    500: struct nxe_imageinfo {
                    501:        u_int32_t               nim_bootld_ver;
                    502:        u_int32_t               nim_bootld_size;
                    503:
                    504:        u_int8_t                nim_img_ver_major;
                    505:        u_int8_t                nim_img_ver_minor;
                    506:        u_int16_t               nim_img_ver_build;
                    507:
                    508:        u_int32_t               min_img_size;
                    509: } __packed;
                    510:
                    511: struct nxe_lladdr {
                    512:        u_int8_t                pad[2];
                    513:        u_int8_t                lladdr[6];
                    514: } __packed;
                    515:
                    516: struct nxe_userinfo {
                    517:        u_int8_t                nu_flash_md5[1024];
                    518:
                    519:        struct nxe_imageinfo    nu_imageinfo;
                    520:
                    521:        u_int32_t               nu_primary;
                    522:        u_int32_t               nu_secondary;
                    523:
                    524:        u_int64_t               nu_lladdr[NXE_MAX_PORTS][NXE_MAX_PORT_LLADDRS];
                    525:
                    526:        u_int32_t               nu_subsys_id;
                    527:
                    528:        u_int8_t                nu_serial[32];
                    529:
                    530:        u_int32_t               nu_bios_ver;
                    531: } __packed;
                    532:
                    533: /* hw structures actually used in the io path */
                    534:
                    535: struct nxe_ctx_ring {
                    536:        u_int64_t               r_addr;
                    537:        u_int32_t               r_size;
                    538:        u_int32_t               r_reserved;
                    539: };
                    540:
                    541: #define NXE_RING_RX            0
                    542: #define NXE_RING_RX_JUMBO      1
                    543: #define NXE_RING_RX_LRO                2
                    544: #define NXE_NRING              3
                    545:
                    546: struct nxe_ctx {
                    547:        u_int64_t               ctx_cmd_consumer_addr;
                    548:
                    549:        struct nxe_ctx_ring     ctx_cmd_ring;
                    550:
                    551:        struct nxe_ctx_ring     ctx_rx_rings[NXE_NRING];
                    552:
                    553:        u_int64_t               ctx_status_ring_addr;
                    554:        u_int32_t               ctx_status_ring_size;
                    555:
                    556:        u_int32_t               ctx_id;
                    557: } __packed;
                    558:
                    559: struct nxe_tx_desc {
                    560:        u_int8_t                tx_tcp_offset;
                    561:        u_int8_t                tx_ip_offset;
                    562:        u_int16_t               tx_flags;
                    563: #define NXE_TXD_F_OPCODE_TX            (0x01 << 7)
                    564:
                    565:        u_int8_t                tx_nbufs;
                    566:        u_int16_t               tx_length; /* XXX who makes a 24bit field? */
                    567:        u_int8_t                tx_length_hi;
                    568:
                    569:        u_int64_t               tx_addr_2;
                    570:
                    571:        u_int16_t               tx_id;
                    572:        u_int16_t               tx_mss;
                    573:
                    574:        u_int8_t                tx_port;
                    575:        u_int8_t                tx_tso_hdr_len;
                    576:        u_int16_t               tx_ipsec_id;
                    577:
                    578:        u_int64_t               tx_addr_3;
                    579:
                    580:        u_int64_t               tx_addr_1;
                    581:
                    582:        u_int16_t               tx_slen_1;
                    583:        u_int16_t               tx_slen_2;
                    584:        u_int16_t               tx_slen_3;
                    585:        u_int16_t               tx_slen_4;
                    586:
                    587:        u_int64_t               tx_addr_4;
                    588:
                    589:        u_int64_t               tx_reserved;
                    590: } __packed;
                    591: #define NXE_TXD_SEGS           4
                    592: #define NXE_TXD_DESCS          8
                    593: #define NXE_TXD_MAX_SEGS       (NXE_TXD_SEGS * NXE_TXD_DESCS)
                    594:
                    595: struct nxe_rx_desc {
                    596:        u_int16_t               rx_id;
                    597:        u_int16_t               rx_flags;
                    598:        u_int32_t               rx_len; /* packet length */
                    599:        u_int64_t               rx_addr;
                    600: } __packed;
                    601: #define NXE_RXD_MAX_SEGS               1
                    602:
                    603: struct nxe_status_desc {
                    604:        u_int8_t                st_lro;
                    605:        u_int8_t                st_owner;
                    606:        u_int16_t               st_id;
                    607:        u_int16_t               st_len;
                    608:        u_int16_t               st_flags;
                    609: } __packed;
                    610:
                    611: /*
                    612:  * driver definitions
                    613:  */
                    614:
                    615: struct nxe_board {
                    616:        u_int32_t               brd_type;
                    617:        u_int                   brd_mode;
                    618: };
                    619:
                    620: struct nxe_dmamem {
                    621:        bus_dmamap_t            ndm_map;
                    622:        bus_dma_segment_t       ndm_seg;
                    623:        size_t                  ndm_size;
                    624:        caddr_t                 ndm_kva;
                    625: };
                    626: #define NXE_DMA_MAP(_ndm)      ((_ndm)->ndm_map)
                    627: #define NXE_DMA_LEN(_ndm)      ((_ndm)->ndm_size)
                    628: #define NXE_DMA_DVA(_ndm)      ((_ndm)->ndm_map->dm_segs[0].ds_addr)
                    629: #define NXE_DMA_KVA(_ndm)      ((void *)(_ndm)->ndm_kva)
                    630:
                    631: struct nxe_pkt {
                    632:        u_int16_t               pkt_id;
                    633:        bus_dmamap_t            pkt_dmap;
                    634:        struct mbuf             *pkt_m;
                    635:        TAILQ_ENTRY(nxe_pkt)    pkt_link;
                    636: };
                    637:
                    638: struct nxe_pkt_list {
                    639:        struct nxe_pkt          *npl_pkts;
                    640:        TAILQ_HEAD(, nxe_pkt)   npl_free;
                    641:        TAILQ_HEAD(, nxe_pkt)   npl_used;
                    642: };
                    643:
                    644: struct nxe_ring {
                    645:        struct nxe_dmamem       *nr_dmamem;
                    646:        u_int8_t                *nr_pos;
                    647:
                    648:        u_int                   nr_slot;
                    649:        int                     nr_ready;
                    650:
                    651:        size_t                  nr_desclen;
                    652:        u_int                   nr_nentries;
                    653: };
                    654:
                    655: /*
                    656:  * autoconf glue
                    657:  */
                    658:
                    659: struct nxe_softc {
                    660:        struct device           sc_dev;
                    661:
                    662:        bus_dma_tag_t           sc_dmat;
                    663:
                    664:        bus_space_tag_t         sc_memt;
                    665:        bus_space_handle_t      sc_memh;
                    666:        bus_size_t              sc_mems;
                    667:        bus_space_handle_t      sc_crbh;
                    668:        bus_space_tag_t         sc_dbt;
                    669:        bus_space_handle_t      sc_dbh;
                    670:        bus_size_t              sc_dbs;
                    671:
                    672:        void                    *sc_ih;
                    673:
                    674:        int                     sc_function;
                    675:        int                     sc_port;
                    676:        int                     sc_window;
                    677:
                    678:        const struct nxe_board  *sc_board;
                    679:        u_int                   sc_fw_major;
                    680:        u_int                   sc_fw_minor;
                    681:        u_int                   sc_fw_build;
                    682:
                    683:        struct arpcom           sc_ac;
                    684:        struct ifmedia          sc_media;
                    685:
                    686:        struct nxe_pkt_list     *sc_tx_pkts;
                    687:        struct nxe_pkt_list     *sc_rx_pkts;
                    688:
                    689:        /* allocations for the hw */
                    690:        struct nxe_dmamem       *sc_dummy_dma;
                    691:
                    692:        struct nxe_dmamem       *sc_ctx;
                    693:        u_int32_t               *sc_cmd_consumer;
                    694:
                    695:        struct nxe_ring         *sc_cmd_ring;
                    696:        struct nxe_ring         *sc_rx_rings[NXE_NRING];
                    697:        struct nxe_ring         *sc_status_ring;
                    698:
                    699:        /* monitoring */
                    700:        struct timeout          sc_tick;
                    701:        struct ksensor          sc_sensor;
                    702:        struct ksensordev       sc_sensor_dev;
                    703:
                    704:        /* ioctl lock */
                    705:        struct rwlock           sc_lock;
                    706: };
                    707:
                    708: int                    nxe_match(struct device *, void *, void *);
                    709: void                   nxe_attach(struct device *, struct device *, void *);
                    710: int                    nxe_intr(void *);
                    711:
                    712: struct cfattach nxe_ca = {
                    713:        sizeof(struct nxe_softc),
                    714:        nxe_match,
                    715:        nxe_attach
                    716: };
                    717:
                    718: struct cfdriver nxe_cd = {
                    719:        NULL,
                    720:        "nxe",
                    721:        DV_IFNET
                    722: };
                    723:
                    724: /* init code */
                    725: int                    nxe_pci_map(struct nxe_softc *,
                    726:                            struct pci_attach_args *);
                    727: void                   nxe_pci_unmap(struct nxe_softc *);
                    728:
                    729: int                    nxe_board_info(struct nxe_softc *);
                    730: int                    nxe_user_info(struct nxe_softc *);
                    731: int                    nxe_init(struct nxe_softc *);
                    732: void                   nxe_uninit(struct nxe_softc *);
                    733: void                   nxe_mountroot(void *);
                    734:
                    735: /* chip state */
                    736: void                   nxe_tick(void *);
                    737: void                   nxe_link_state(struct nxe_softc *);
                    738:
                    739: /* interface operations */
                    740: int                    nxe_ioctl(struct ifnet *, u_long, caddr_t);
                    741: void                   nxe_start(struct ifnet *);
                    742: void                   nxe_watchdog(struct ifnet *);
                    743:
                    744: void                   nxe_up(struct nxe_softc *);
                    745: void                   nxe_lladdr(struct nxe_softc *);
                    746: void                   nxe_iff(struct nxe_softc *);
                    747: void                   nxe_down(struct nxe_softc *);
                    748:
                    749: int                    nxe_up_fw(struct nxe_softc *);
                    750:
                    751: /* ifmedia operations */
                    752: int                    nxe_media_change(struct ifnet *);
                    753: void                   nxe_media_status(struct ifnet *, struct ifmediareq *);
                    754:
                    755:
                    756: /* ring handling */
                    757: struct nxe_ring                *nxe_ring_alloc(struct nxe_softc *, size_t, u_int);
                    758: void                   nxe_ring_sync(struct nxe_softc *, struct nxe_ring *,
                    759:                            int);
                    760: void                   nxe_ring_free(struct nxe_softc *, struct nxe_ring *);
                    761: int                    nxe_ring_readable(struct nxe_ring *, int);
                    762: int                    nxe_ring_writeable(struct nxe_ring *, int);
                    763: void                   *nxe_ring_cur(struct nxe_softc *, struct nxe_ring *);
                    764: void                   *nxe_ring_next(struct nxe_softc *, struct nxe_ring *);
                    765:
                    766: struct mbuf            *nxe_load_pkt(struct nxe_softc *, bus_dmamap_t,
                    767:                            struct mbuf *);
                    768: struct mbuf            *nxe_coalesce_m(struct mbuf *);
                    769:
                    770: /* pkts */
                    771: struct nxe_pkt_list    *nxe_pkt_alloc(struct nxe_softc *, u_int, int);
                    772: void                   nxe_pkt_free(struct nxe_softc *,
                    773:                            struct nxe_pkt_list *);
                    774: void                   nxe_pkt_put(struct nxe_pkt_list *, struct nxe_pkt *);
                    775: struct nxe_pkt         *nxe_pkt_get(struct nxe_pkt_list *);
                    776: struct nxe_pkt         *nxe_pkt_used(struct nxe_pkt_list *);
                    777:
                    778:
                    779: /* wrapper around dmaable memory allocations */
                    780: struct nxe_dmamem      *nxe_dmamem_alloc(struct nxe_softc *, bus_size_t,
                    781:                            bus_size_t);
                    782: void                   nxe_dmamem_free(struct nxe_softc *,
                    783:                            struct nxe_dmamem *);
                    784:
                    785: /* low level hardware access goo */
                    786: u_int32_t              nxe_read(struct nxe_softc *, bus_size_t);
                    787: void                   nxe_write(struct nxe_softc *, bus_size_t, u_int32_t);
                    788: int                    nxe_wait(struct nxe_softc *, bus_size_t, u_int32_t,
                    789:                            u_int32_t, u_int);
                    790:
                    791: int                    nxe_crb_set(struct nxe_softc *, int);
                    792: u_int32_t              nxe_crb_read(struct nxe_softc *, bus_size_t);
                    793: void                   nxe_crb_write(struct nxe_softc *, bus_size_t,
                    794:                            u_int32_t);
                    795: int                    nxe_crb_wait(struct nxe_softc *, bus_size_t,
                    796:                            u_int32_t, u_int32_t, u_int);
                    797:
                    798: int                    nxe_rom_lock(struct nxe_softc *);
                    799: void                   nxe_rom_unlock(struct nxe_softc *);
                    800: int                    nxe_rom_read(struct nxe_softc *, u_int32_t,
                    801:                            u_int32_t *);
                    802: int                    nxe_rom_read_region(struct nxe_softc *, u_int32_t,
                    803:                            void *, size_t);
                    804:
                    805:
                    806: /* misc bits */
                    807: #define DEVNAME(_sc)   ((_sc)->sc_dev.dv_xname)
                    808: #define sizeofa(_a)    (sizeof(_a) / sizeof((_a)[0]))
                    809:
                    810: /* let's go! */
                    811:
                    812: const struct pci_matchid nxe_devices[] = {
                    813:        { PCI_VENDOR_NETXEN, PCI_PRODUCT_NETXEN_NXB_10GXxR },
                    814:        { PCI_VENDOR_NETXEN, PCI_PRODUCT_NETXEN_NXB_10GCX4 },
                    815:        { PCI_VENDOR_NETXEN, PCI_PRODUCT_NETXEN_NXB_4GCU },
                    816:        { PCI_VENDOR_NETXEN, PCI_PRODUCT_NETXEN_NXB_IMEZ },
                    817:        { PCI_VENDOR_NETXEN, PCI_PRODUCT_NETXEN_NXB_HMEZ },
                    818:        { PCI_VENDOR_NETXEN, PCI_PRODUCT_NETXEN_NXB_IMEZ_2 },
                    819:        { PCI_VENDOR_NETXEN, PCI_PRODUCT_NETXEN_NXB_HMEZ_2 }
                    820: };
                    821:
                    822: const struct nxe_board nxe_boards[] = {
                    823:        { NXE_BRDTYPE_P2_SB35_4G,       NXE_0_NIU_MODE_GBE },
                    824:        { NXE_BRDTYPE_P2_SB31_10G,      NXE_0_NIU_MODE_XGE },
                    825:        { NXE_BRDTYPE_P2_SB31_2G,       NXE_0_NIU_MODE_GBE },
                    826:        { NXE_BRDTYPE_P2_SB31_10G_IMEZ, NXE_0_NIU_MODE_XGE },
                    827:        { NXE_BRDTYPE_P2_SB31_10G_HMEZ, NXE_0_NIU_MODE_XGE },
                    828:        { NXE_BRDTYPE_P2_SB31_10G_CX4,  NXE_0_NIU_MODE_XGE }
                    829: };
                    830:
                    831: int
                    832: nxe_match(struct device *parent, void *match, void *aux)
                    833: {
                    834:        struct pci_attach_args          *pa = aux;
                    835:
                    836:        if (PCI_CLASS(pa->pa_class) != PCI_CLASS_NETWORK)
                    837:                return (0);
                    838:
                    839:        return (pci_matchbyid(pa, nxe_devices, sizeofa(nxe_devices)));
                    840: }
                    841:
                    842: void
                    843: nxe_attach(struct device *parent, struct device *self, void *aux)
                    844: {
                    845:        struct nxe_softc                *sc = (struct nxe_softc *)self;
                    846:        struct pci_attach_args          *pa = aux;
                    847:        pci_intr_handle_t               ih;
                    848:        struct ifnet                    *ifp;
                    849:
                    850:        sc->sc_dmat = pa->pa_dmat;
                    851:        sc->sc_function = pa->pa_function;
                    852:        sc->sc_window = -1;
                    853:
                    854:        rw_init(&sc->sc_lock, NULL);
                    855:
                    856:        if (nxe_pci_map(sc, pa) != 0) {
                    857:                /* error already printed by nxe_pci_map() */
                    858:                return;
                    859:        }
                    860:
                    861:        nxe_crb_set(sc, 1);
                    862:
                    863:        if (nxe_board_info(sc) != 0) {
                    864:                /* error already printed by nxe_board_info() */
                    865:                goto unmap;
                    866:        }
                    867:
                    868:        if (nxe_user_info(sc) != 0) {
                    869:                /* error already printed by nxe_board_info() */
                    870:                goto unmap;
                    871:        }
                    872:
                    873:        if (nxe_init(sc) != 0) {
                    874:                /* error already printed by nxe_init() */
                    875:                goto unmap;
                    876:        }
                    877:
                    878:        if (pci_intr_map(pa, &ih) != 0) {
                    879:                printf(": unable to map interrupt\n");
                    880:                goto uninit;
                    881:        }
                    882:        sc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_NET,
                    883:            nxe_intr, sc, DEVNAME(sc));
                    884:        if (sc->sc_ih == NULL) {
                    885:                printf(": unable to establish interrupt\n");
                    886:                goto uninit;
                    887:        }
                    888:
                    889:        ifp = &sc->sc_ac.ac_if;
                    890:        ifp->if_softc = sc;
                    891:        ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
                    892:        ifp->if_capabilities = IFCAP_VLAN_MTU;
                    893:        ifp->if_ioctl = nxe_ioctl;
                    894:        ifp->if_start = nxe_start;
                    895:        ifp->if_watchdog = nxe_watchdog;
                    896:        ifp->if_hardmtu = MCLBYTES - ETHER_HDR_LEN - ETHER_CRC_LEN;
                    897:        strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
                    898:        IFQ_SET_MAXLEN(&ifp->if_snd, 512); /* XXX */
                    899:        IFQ_SET_READY(&ifp->if_snd);
                    900:
                    901:        ifmedia_init(&sc->sc_media, 0, nxe_media_change, nxe_media_status);
                    902:        ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_AUTO, 0, NULL);
                    903:        ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_AUTO);
                    904:
                    905:        if_attach(ifp);
                    906:        ether_ifattach(ifp);
                    907:
                    908:        printf(": %s firmware %d.%d.%d address %s\n",
                    909:            pci_intr_string(pa->pa_pc, ih),
                    910:            sc->sc_fw_major, sc->sc_fw_minor, sc->sc_fw_build,
                    911:            ether_sprintf(sc->sc_ac.ac_enaddr));
                    912:        return;
                    913:
                    914: uninit:
                    915:        nxe_uninit(sc);
                    916: unmap:
                    917:        nxe_pci_unmap(sc);
                    918: }
                    919:
                    920: int
                    921: nxe_pci_map(struct nxe_softc *sc, struct pci_attach_args *pa)
                    922: {
                    923:        pcireg_t                        memtype;
                    924:
                    925:        memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, NXE_PCI_BAR_MEM);
                    926:        if (pci_mapreg_map(pa, NXE_PCI_BAR_MEM, memtype, 0, &sc->sc_memt,
                    927:            &sc->sc_memh, NULL, &sc->sc_mems, 0) != 0) {
                    928:                printf(": unable to map host registers\n");
                    929:                return (1);
                    930:        }
                    931:        if (sc->sc_mems != NXE_PCI_BAR_MEM_128MB) {
                    932:                printf(": unexpected register map size\n");
                    933:                goto unmap_mem;
                    934:        }
                    935:
                    936:        /* set up the CRB window */
                    937:        if (bus_space_subregion(sc->sc_memt, sc->sc_memh, NXE_MAP_CRB,
                    938:            sc->sc_mems - NXE_MAP_CRB, &sc->sc_crbh) != 0) {
                    939:                printf(": unable to create CRB window\n");
                    940:                goto unmap_mem;
                    941:        }
                    942:
                    943:        memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, NXE_PCI_BAR_DOORBELL);
                    944:        if (pci_mapreg_map(pa, NXE_PCI_BAR_DOORBELL, memtype, 0, &sc->sc_dbt,
                    945:            &sc->sc_dbh, NULL, &sc->sc_dbs, 0) != 0) {
                    946:                printf(": unable to map doorbell registers\n");
                    947:                /* bus_space(9) says i dont have to unmap subregions */
                    948:                goto unmap_mem;
                    949:        }
                    950:
                    951:        mountroothook_establish(nxe_mountroot, sc);
                    952:        return (0);
                    953:
                    954: unmap_mem:
                    955:        bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
                    956:        sc->sc_mems = 0;
                    957:        return (1);
                    958: }
                    959:
                    960: void
                    961: nxe_pci_unmap(struct nxe_softc *sc)
                    962: {
                    963:        bus_space_unmap(sc->sc_dbt, sc->sc_dbh, sc->sc_dbs);
                    964:        sc->sc_dbs = 0;
                    965:        /* bus_space(9) says i dont have to unmap the crb subregion */
                    966:        bus_space_unmap(sc->sc_memt, sc->sc_memh, sc->sc_mems);
                    967:        sc->sc_mems = 0;
                    968: }
                    969:
                    970: int
                    971: nxe_intr(void *xsc)
                    972: {
                    973:        return (0);
                    974: }
                    975:
                    976: int
                    977: nxe_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr)
                    978: {
                    979:        struct nxe_softc                *sc = ifp->if_softc;
                    980:        struct ifreq                    *ifr = (struct ifreq *)addr;
                    981:        struct ifaddr                   *ifa;
                    982:        int                             error;
                    983:        int                             s;
                    984:
                    985:        rw_enter_write(&sc->sc_lock);
                    986:        s = splnet();
                    987:
                    988:        error = ether_ioctl(ifp, &sc->sc_ac, cmd, addr);
                    989:        if (error > 0)
                    990:                goto err;
                    991:
                    992:        timeout_del(&sc->sc_tick);
                    993:
                    994:        switch (cmd) {
                    995:        case SIOCSIFADDR:
                    996:                SET(ifp->if_flags, IFF_UP);
                    997: #ifdef INET
                    998:                ifa = (struct ifaddr *)addr;
                    999:                if (ifa->ifa_addr->sa_family == AF_INET)
                   1000:                        arp_ifinit(&sc->sc_ac, ifa);
                   1001: #endif
                   1002:                /* FALLTHROUGH */
                   1003:        case SIOCSIFFLAGS:
                   1004:                if (ISSET(ifp->if_flags, IFF_UP)) {
                   1005:                        if (ISSET(ifp->if_flags, IFF_RUNNING))
                   1006:                                error = ENETRESET;
                   1007:                        else
                   1008:                                nxe_up(sc);
                   1009:                } else {
                   1010:                        if (ISSET(ifp->if_flags, IFF_RUNNING))
                   1011:                                nxe_down(sc);
                   1012:                }
                   1013:                break;
                   1014:
                   1015:        case SIOCGIFMEDIA:
                   1016:        case SIOCSIFMEDIA:
                   1017:                error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd);
                   1018:                break;
                   1019:
                   1020:        default:
                   1021:                error = ENOTTY;
                   1022:                break;
                   1023:        }
                   1024:
                   1025:        if (error == ENETRESET) {
                   1026:                if (ISSET(ifp->if_flags, IFF_RUNNING)) {
                   1027:                        nxe_crb_set(sc, 0);
                   1028:                        nxe_iff(sc);
                   1029:                        nxe_crb_set(sc, 1);
                   1030:                }
                   1031:                error = 0;
                   1032:        }
                   1033:
                   1034:        nxe_tick(sc);
                   1035:
                   1036: err:
                   1037:        splx(s);
                   1038:        rw_exit_write(&sc->sc_lock);
                   1039:        return (error);
                   1040: }
                   1041:
                   1042: void
                   1043: nxe_up(struct nxe_softc *sc)
                   1044: {
                   1045:        struct ifnet                    *ifp = &sc->sc_ac.ac_if;
                   1046:        static const u_int              rx_ring_sizes[] = { 16384, 1024, 128 };
                   1047:        struct {
                   1048:                struct nxe_ctx                  ctx;
                   1049:                u_int32_t                       cmd_consumer;
                   1050:        } __packed                      *dmamem;
                   1051:        struct nxe_ctx                  *ctx;
                   1052:        struct nxe_ctx_ring             *ring;
                   1053:        struct nxe_ring                 *nr;
                   1054:        u_int64_t                       dva;
                   1055:        int                             i;
                   1056:
                   1057:        if (nxe_up_fw(sc) != 0)
                   1058:                return;
                   1059:
                   1060:        /* allocate pkt lists */
                   1061:        sc->sc_tx_pkts = nxe_pkt_alloc(sc, 128, NXE_TXD_MAX_SEGS);
                   1062:        if (sc->sc_tx_pkts == NULL)
                   1063:                return;
                   1064:        sc->sc_rx_pkts = nxe_pkt_alloc(sc, 128, NXE_RXD_MAX_SEGS);
                   1065:        if (sc->sc_rx_pkts == NULL)
                   1066:                goto free_tx_pkts;
                   1067:
                   1068:        /* allocate the context memory and the consumer field */
                   1069:        sc->sc_ctx = nxe_dmamem_alloc(sc, sizeof(*dmamem), PAGE_SIZE);
                   1070:        if (sc->sc_ctx == NULL)
                   1071:                goto free_rx_pkts;
                   1072:
                   1073:        dmamem = NXE_DMA_KVA(sc->sc_ctx);
                   1074:        dva = NXE_DMA_DVA(sc->sc_ctx);
                   1075:
                   1076:        ctx = &dmamem->ctx;
                   1077:        ctx->ctx_cmd_consumer_addr = htole64(dva + sizeof(dmamem->ctx));
                   1078:        ctx->ctx_id = htole32(sc->sc_function);
                   1079:
                   1080:        sc->sc_cmd_consumer = &dmamem->cmd_consumer;
                   1081:
                   1082:        /* allocate the cmd/tx ring */
                   1083:        sc->sc_cmd_ring = nxe_ring_alloc(sc,
                   1084:            sizeof(struct nxe_tx_desc), 1024 /* XXX */);
                   1085:        if (sc->sc_cmd_ring == NULL)
                   1086:                goto free_ctx;
                   1087:
                   1088:        ctx->ctx_cmd_ring.r_addr =
                   1089:            htole64(NXE_DMA_DVA(sc->sc_cmd_ring->nr_dmamem));
                   1090:        ctx->ctx_cmd_ring.r_size = htole64(sc->sc_cmd_ring->nr_nentries);
                   1091:
                   1092:        /* allocate the status ring */
                   1093:        sc->sc_status_ring = nxe_ring_alloc(sc,
                   1094:            sizeof(struct nxe_status_desc), 16384 /* XXX */);
                   1095:        if (sc->sc_status_ring == NULL)
                   1096:                goto free_cmd_ring;
                   1097:
                   1098:        ctx->ctx_status_ring_addr =
                   1099:            htole64(NXE_DMA_DVA(sc->sc_status_ring->nr_dmamem));
                   1100:        ctx->ctx_status_ring_size = htole64(sc->sc_status_ring->nr_nentries);
                   1101:
                   1102:        /* allocate the rx rings */
                   1103:        for (i = 0; i < NXE_NRING; i++) {
                   1104:                ring = &ctx->ctx_rx_rings[i];
                   1105:                nr = nxe_ring_alloc(sc, sizeof(struct nxe_rx_desc),
                   1106:                    rx_ring_sizes[i]);
                   1107:                if (nr == NULL)
                   1108:                        goto free_rx_rings;
                   1109:
                   1110:                ring->r_addr = htole64(NXE_DMA_DVA(nr->nr_dmamem));
                   1111:                ring->r_size = htole32(nr->nr_nentries);
                   1112:
                   1113:                sc->sc_rx_rings[i] = nr;
                   1114:                nxe_ring_sync(sc, sc->sc_rx_rings[i], BUS_DMASYNC_PREWRITE);
                   1115:        }
                   1116:
                   1117:        /* nothing can possibly go wrong now */
                   1118:        nxe_ring_sync(sc, sc->sc_status_ring, BUS_DMASYNC_PREREAD);
                   1119:        nxe_ring_sync(sc, sc->sc_cmd_ring, BUS_DMASYNC_PREWRITE);
                   1120:        bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(sc->sc_ctx),
                   1121:            0, NXE_DMA_LEN(sc->sc_ctx),
                   1122:            BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
                   1123:
                   1124:        nxe_crb_write(sc, NXE_1_SW_CONTEXT_ADDR_LO(sc->sc_function),
                   1125:            (u_int32_t)dva);
                   1126:        nxe_crb_write(sc, NXE_1_SW_CONTEXT_ADDR_HI(sc->sc_function),
                   1127:            (u_int32_t)(dva >> 32));
                   1128:        nxe_crb_write(sc, NXE_1_SW_CONTEXT(sc->sc_port),
                   1129:            NXE_1_SW_CONTEXT_SIG(sc->sc_port));
                   1130:
                   1131:        nxe_crb_set(sc, 0);
                   1132:        nxe_lladdr(sc);
                   1133:        nxe_iff(sc);
                   1134:        nxe_crb_set(sc, 1);
                   1135:
                   1136:        SET(ifp->if_flags, IFF_RUNNING);
                   1137:        CLR(ifp->if_flags, IFF_OACTIVE);
                   1138:
                   1139:        /* enable interrupts */
                   1140:
                   1141:        return;
                   1142:
                   1143: free_rx_rings:
                   1144:        while (i > 0) {
                   1145:                i--;
                   1146:                nxe_ring_sync(sc, sc->sc_rx_rings[i], BUS_DMASYNC_POSTWRITE);
                   1147:                nxe_ring_free(sc, sc->sc_rx_rings[i]);
                   1148:        }
                   1149:
                   1150:        nxe_ring_free(sc, sc->sc_status_ring);
                   1151: free_cmd_ring:
                   1152:        nxe_ring_free(sc, sc->sc_cmd_ring);
                   1153: free_ctx:
                   1154:        nxe_dmamem_free(sc, sc->sc_ctx);
                   1155: free_rx_pkts:
                   1156:        nxe_pkt_free(sc, sc->sc_rx_pkts);
                   1157: free_tx_pkts:
                   1158:        nxe_pkt_free(sc, sc->sc_tx_pkts);
                   1159: }
                   1160:
                   1161: int
                   1162: nxe_up_fw(struct nxe_softc *sc)
                   1163: {
                   1164:        u_int32_t                       r;
                   1165:
                   1166:        r = nxe_crb_read(sc, NXE_1_SW_CMDPEG_STATE);
                   1167:        if (r == NXE_1_SW_CMDPEG_STATE_ACK)
                   1168:                return (0);
                   1169:
                   1170:        if (r != NXE_1_SW_CMDPEG_STATE_DONE)
                   1171:                return (1);
                   1172:
                   1173:        nxe_crb_write(sc, NXE_1_SW_NIC_CAP_HOST, NXE_1_SW_NIC_CAP_HOST_DEF);
                   1174:        nxe_crb_write(sc, NXE_1_SW_MPORT_MODE, NXE_1_SW_MPORT_MODE_MULTI);
                   1175:        nxe_crb_write(sc, NXE_1_SW_CMDPEG_STATE, NXE_1_SW_CMDPEG_STATE_ACK);
                   1176:
                   1177:        /* XXX busy wait in a process context is naughty */
                   1178:        if (!nxe_crb_wait(sc, NXE_1_SW_STATUS_STATE(sc->sc_function),
                   1179:            0xffffffff, NXE_1_SW_STATUS_STATE_READY, 1000))
                   1180:                return (1);
                   1181:
                   1182:        return (0);
                   1183: }
                   1184:
                   1185: void
                   1186: nxe_lladdr(struct nxe_softc *sc)
                   1187: {
                   1188:        u_int8_t                        *lladdr = sc->sc_ac.ac_enaddr;
                   1189:
                   1190:        DASSERT(sc->sc_window == 0);
                   1191:
                   1192:        nxe_crb_write(sc, NXE_0_XG_MAC_LO(sc->sc_port),
                   1193:            (lladdr[0] << 24) | (lladdr[1] << 16));
                   1194:        nxe_crb_write(sc, NXE_0_XG_MAC_HI(sc->sc_port),
                   1195:            (lladdr[2] << 24) | (lladdr[3] << 16) |
                   1196:            (lladdr[4] << 8)  | (lladdr[5] << 0));
                   1197: }
                   1198:
                   1199: void
                   1200: nxe_iff(struct nxe_softc *sc)
                   1201: {
                   1202:        struct ifnet                    *ifp = &sc->sc_ac.ac_if;
                   1203:        u_int32_t                       cfg1 = 0x1447; /* XXX */
                   1204:
                   1205:        DASSERT(sc->sc_window == 0);
                   1206:
                   1207:        CLR(ifp->if_flags, IFF_ALLMULTI);
                   1208:        if (sc->sc_ac.ac_multirangecnt > 0 || sc->sc_ac.ac_multicnt > 0) {
                   1209:                cfg1 |= NXE_0_XG_CFG1_MULTICAST;
                   1210:                SET(ifp->if_flags, IFF_ALLMULTI);
                   1211:        }
                   1212:
                   1213:        if (ISSET(ifp->if_flags, IFF_PROMISC))
                   1214:                cfg1 |= NXE_0_XG_CFG1_PROMISC;
                   1215:
                   1216:        nxe_crb_write(sc, NXE_0_XG_CFG0(sc->sc_port),
                   1217:            NXE_0_XG_CFG0_TX_EN | NXE_0_XG_CFG0_RX_EN);
                   1218:        nxe_crb_write(sc, NXE_0_XG_CFG1(sc->sc_port), cfg1);
                   1219: }
                   1220:
                   1221: void
                   1222: nxe_down(struct nxe_softc *sc)
                   1223: {
                   1224:        struct ifnet                    *ifp = &sc->sc_ac.ac_if;
                   1225:        int                             i;
                   1226:
                   1227:        CLR(ifp->if_flags, IFF_RUNNING | IFF_OACTIVE | IFF_ALLMULTI);
                   1228:
                   1229:        /* XXX turn the chip off */
                   1230:
                   1231:        bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(sc->sc_ctx),
                   1232:            0, NXE_DMA_LEN(sc->sc_ctx),
                   1233:            BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
                   1234:        nxe_ring_sync(sc, sc->sc_cmd_ring, BUS_DMASYNC_POSTWRITE);
                   1235:        nxe_ring_sync(sc, sc->sc_status_ring, BUS_DMASYNC_POSTREAD);
                   1236:
                   1237:        for (i = 0; i < NXE_NRING; i++) {
                   1238:                nxe_ring_sync(sc, sc->sc_rx_rings[i], BUS_DMASYNC_POSTWRITE);
                   1239:                nxe_ring_free(sc, sc->sc_rx_rings[i]);
                   1240:        }
                   1241:        nxe_ring_free(sc, sc->sc_status_ring);
                   1242:        nxe_ring_free(sc, sc->sc_cmd_ring);
                   1243:        nxe_dmamem_free(sc, sc->sc_ctx);
                   1244:        nxe_pkt_free(sc, sc->sc_rx_pkts);
                   1245:        nxe_pkt_free(sc, sc->sc_tx_pkts);
                   1246: }
                   1247:
                   1248: void
                   1249: nxe_start(struct ifnet *ifp)
                   1250: {
                   1251:        struct nxe_softc                *sc = ifp->if_softc;
                   1252:        struct nxe_ring                 *nr = sc->sc_cmd_ring;
                   1253:        struct nxe_tx_desc              *txd;
                   1254:        struct nxe_pkt                  *pkt;
                   1255:        struct mbuf                     *m;
                   1256:        bus_dmamap_t                    dmap;
                   1257:        bus_dma_segment_t               *segs;
                   1258:        int                             nsegs;
                   1259:
                   1260:        if (!ISSET(ifp->if_flags, IFF_RUNNING) ||
                   1261:            ISSET(ifp->if_flags, IFF_OACTIVE) ||
                   1262:            IFQ_IS_EMPTY(&ifp->if_snd))
                   1263:                return;
                   1264:
                   1265:        if (nxe_ring_writeable(nr, 0 /* XXX */) < NXE_TXD_DESCS) {
                   1266:                SET(ifp->if_flags, IFF_OACTIVE);
                   1267:                return;
                   1268:        }
                   1269:
                   1270:        nxe_ring_sync(sc, nr, BUS_DMASYNC_POSTWRITE);
                   1271:        txd = nxe_ring_cur(sc, nr);
                   1272:        bzero(txd, sizeof(struct nxe_tx_desc));
                   1273:
                   1274:        do {
                   1275:                IFQ_POLL(&ifp->if_snd, m);
                   1276:                if (m == NULL)
                   1277:                        break;
                   1278:
                   1279:                pkt = nxe_pkt_get(sc->sc_tx_pkts);
                   1280:                if (pkt == NULL) {
                   1281:                        SET(ifp->if_flags, IFF_OACTIVE);
                   1282:                        break;
                   1283:                }
                   1284:
                   1285:                IFQ_DEQUEUE(&ifp->if_snd, m);
                   1286:
                   1287:                dmap = pkt->pkt_dmap;
                   1288:                m = nxe_load_pkt(sc, dmap, m);
                   1289:                if (m == NULL) {
                   1290:                        nxe_pkt_put(sc->sc_tx_pkts, pkt);
                   1291:                        ifp->if_oerrors++;
                   1292:                        break;
                   1293:                }
                   1294:
                   1295: #if NBPFILTER > 0
                   1296:                if (ifp->if_bpf)
                   1297:                        bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
                   1298: #endif
                   1299:
                   1300:                pkt->pkt_m = m;
                   1301:
                   1302:                txd->tx_flags = htole16(NXE_TXD_F_OPCODE_TX);
                   1303:                txd->tx_nbufs = dmap->dm_nsegs;
                   1304:                txd->tx_length = htole16(dmap->dm_mapsize);
                   1305:                txd->tx_id = pkt->pkt_id;
                   1306:                txd->tx_port = sc->sc_port;
                   1307:
                   1308:                segs = dmap->dm_segs;
                   1309:                nsegs = dmap->dm_nsegs;
                   1310:                do {
                   1311:                        switch ((nsegs > NXE_TXD_SEGS) ?
                   1312:                            NXE_TXD_SEGS : nsegs) {
                   1313:                        case 4:
                   1314:                                txd->tx_addr_4 = htole64(segs[3].ds_addr);
                   1315:                                txd->tx_slen_4 = htole32(segs[3].ds_len);
                   1316:                        case 3:
                   1317:                                txd->tx_addr_3 = htole64(segs[2].ds_addr);
                   1318:                                txd->tx_slen_3 = htole32(segs[2].ds_len);
                   1319:                        case 2:
                   1320:                                txd->tx_addr_2 = htole64(segs[1].ds_addr);
                   1321:                                txd->tx_slen_2 = htole32(segs[1].ds_len);
                   1322:                        case 1:
                   1323:                                txd->tx_addr_1 = htole64(segs[0].ds_addr);
                   1324:                                txd->tx_slen_1 = htole32(segs[0].ds_len);
                   1325:                                break;
                   1326:                        default:
                   1327:                                panic("%s: unexpected segments in tx map",
                   1328:                                    DEVNAME(sc));
                   1329:                        }
                   1330:
                   1331:                        nsegs -= NXE_TXD_SEGS;
                   1332:                        segs += NXE_TXD_SEGS;
                   1333:
                   1334:                        txd = nxe_ring_next(sc, nr);
                   1335:                        bzero(txd, sizeof(struct nxe_tx_desc));
                   1336:                } while (nsegs > 0);
                   1337:
                   1338:                bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
                   1339:                    BUS_DMASYNC_PREWRITE);
                   1340:
                   1341:                ifp->if_opackets++;
                   1342:        } while (nr->nr_ready >= NXE_TXD_DESCS);
                   1343:
                   1344:        nxe_ring_sync(sc, nr, BUS_DMASYNC_PREWRITE);
                   1345:        nxe_crb_write(sc, NXE_1_SW_CMD_PRODUCER(sc->sc_function), nr->nr_slot);
                   1346: }
                   1347:
                   1348: struct mbuf *
                   1349: nxe_coalesce_m(struct mbuf *m)
                   1350: {
                   1351:        struct mbuf                     *m0;
                   1352:
                   1353:        MGETHDR(m0, M_DONTWAIT, MT_DATA);
                   1354:        if (m0 == NULL)
                   1355:                goto err;
                   1356:
                   1357:        if (m->m_pkthdr.len > MHLEN) {
                   1358:                MCLGET(m0, M_DONTWAIT);
                   1359:                if (!(m0->m_flags & M_EXT)) {
                   1360:                        m_freem(m0);
                   1361:                        m0 = NULL;
                   1362:                        goto err;
                   1363:                }
                   1364:        }
                   1365:
                   1366:        m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t));
                   1367:        m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len;
                   1368:
                   1369: err:
                   1370:        m_freem(m);
                   1371:        return (m0);
                   1372: }
                   1373:
                   1374: struct mbuf *
                   1375: nxe_load_pkt(struct nxe_softc *sc, bus_dmamap_t dmap, struct mbuf *m)
                   1376: {
                   1377:        switch (bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m, BUS_DMA_NOWAIT)) {
                   1378:        case 0:
                   1379:                break;
                   1380:
                   1381:        case EFBIG:
                   1382:                m = nxe_coalesce_m(m);
                   1383:                if (m == NULL)
                   1384:                        break;
                   1385:
                   1386:                if (bus_dmamap_load_mbuf(sc->sc_dmat, dmap, m,
                   1387:                    BUS_DMA_NOWAIT) == 0)
                   1388:                        break;
                   1389:
                   1390:                /* we get here on error */
                   1391:                /* FALLTHROUGH */
                   1392:        default:
                   1393:                m_freem(m);
                   1394:                m = NULL;
                   1395:                break;
                   1396:        }
                   1397:
                   1398:        return (m);
                   1399: }
                   1400:
                   1401: void
                   1402: nxe_watchdog(struct ifnet *ifp)
                   1403: {
                   1404:        /* do nothing */
                   1405: }
                   1406:
                   1407: int
                   1408: nxe_media_change(struct ifnet *ifp)
                   1409: {
                   1410:        /* ignore for now */
                   1411:        return (0);
                   1412: }
                   1413:
                   1414: void
                   1415: nxe_media_status(struct ifnet *ifp, struct ifmediareq *imr)
                   1416: {
                   1417:        struct nxe_softc                *sc = ifp->if_softc;
                   1418:
                   1419:        imr->ifm_active = IFM_ETHER | IFM_AUTO;
                   1420:        imr->ifm_status = IFM_AVALID;
                   1421:
                   1422:        nxe_link_state(sc);
                   1423:        if (LINK_STATE_IS_UP(ifp->if_link_state))
                   1424:                imr->ifm_status |= IFM_ACTIVE;
                   1425: }
                   1426:
                   1427: void
                   1428: nxe_link_state(struct nxe_softc *sc)
                   1429: {
                   1430:        struct ifnet                    *ifp = &sc->sc_ac.ac_if;
                   1431:        int                             link_state = LINK_STATE_DOWN;
                   1432:        u_int32_t                       r;
                   1433:
                   1434:        DASSERT(sc->sc_window == 1);
                   1435:
                   1436:        r = nxe_crb_read(sc, NXE_1_SW_XG_STATE);
                   1437:        if (NXE_1_SW_XG_STATE_PORT(r, sc->sc_function) & NXE_1_SW_XG_STATE_UP)
                   1438:                link_state = LINK_STATE_UP;
                   1439:
                   1440:        if (ifp->if_link_state != link_state) {
                   1441:                ifp->if_link_state = link_state;
                   1442:                if_link_state_change(ifp);
                   1443:        }
                   1444: }
                   1445:
                   1446: int
                   1447: nxe_board_info(struct nxe_softc *sc)
                   1448: {
                   1449:        struct nxe_info                 *ni;
                   1450:        int                             rv = 1;
                   1451:        int                             i;
                   1452:
                   1453:        ni = malloc(sizeof(struct nxe_info), M_NOWAIT, M_TEMP);
                   1454:        if (ni == NULL) {
                   1455:                printf(": unable to allocate temporary memory\n");
                   1456:                return (1);
                   1457:        }
                   1458:
                   1459:        if (nxe_rom_read_region(sc, NXE_FLASH_BRDCFG, ni,
                   1460:            sizeof(struct nxe_info)) != 0) {
                   1461:                printf(": unable to read board info\n");
                   1462:                goto out;
                   1463:        }
                   1464:
                   1465:        if (ni->ni_hdrver != NXE_INFO_HDRVER_1) {
                   1466:                printf(": unexpected board info header version 0x%08x\n",
                   1467:                    ni->ni_hdrver);
                   1468:                goto out;
                   1469:        }
                   1470:        if (ni->ni_magic != NXE_INFO_MAGIC) {
                   1471:                printf(": board info magic is invalid\n");
                   1472:                goto out;
                   1473:        }
                   1474:
                   1475:        for (i = 0; i < sizeofa(nxe_boards); i++) {
                   1476:                if (ni->ni_board_type == nxe_boards[i].brd_type) {
                   1477:                        sc->sc_board = &nxe_boards[i];
                   1478:                        break;
                   1479:                }
                   1480:        }
                   1481:        if (sc->sc_board == NULL) {
                   1482:                printf(": unknown board type %04x\n", ni->ni_board_type);
                   1483:                goto out;
                   1484:        }
                   1485:
                   1486:        rv = 0;
                   1487: out:
                   1488:        free(ni, M_TEMP);
                   1489:        return (rv);
                   1490: }
                   1491:
                   1492: int
                   1493: nxe_user_info(struct nxe_softc *sc)
                   1494: {
                   1495:        struct nxe_userinfo             *nu;
                   1496:        u_int64_t                       lladdr;
                   1497:        struct nxe_lladdr               *la;
                   1498:        int                             rv = 1;
                   1499:
                   1500:        nu = malloc(sizeof(struct nxe_userinfo), M_NOWAIT, M_TEMP);
                   1501:        if (nu == NULL) {
                   1502:                printf(": unable to allocate temp memory\n");
                   1503:                return (1);
                   1504:        }
                   1505:        if (nxe_rom_read_region(sc, NXE_FLASH_USER, nu,
                   1506:            sizeof(struct nxe_userinfo)) != 0) {
                   1507:                printf(": unable to read user info\n");
                   1508:                goto out;
                   1509:        }
                   1510:
                   1511:        sc->sc_fw_major = nu->nu_imageinfo.nim_img_ver_major;
                   1512:        sc->sc_fw_minor = nu->nu_imageinfo.nim_img_ver_minor;
                   1513:        sc->sc_fw_build = letoh16(nu->nu_imageinfo.nim_img_ver_build);
                   1514:
                   1515:        if (sc->sc_fw_major > NXE_VERSION_MAJOR ||
                   1516:            sc->sc_fw_major < NXE_VERSION_MAJOR ||
                   1517:            sc->sc_fw_minor > NXE_VERSION_MINOR ||
                   1518:            sc->sc_fw_minor < NXE_VERSION_MINOR) {
                   1519:                printf(": firmware %d.%d.%d is unsupported by this driver\n",
                   1520:                    sc->sc_fw_major, sc->sc_fw_minor, sc->sc_fw_build);
                   1521:                goto out;
                   1522:        }
                   1523:
                   1524:        lladdr = swap64(nu->nu_lladdr[sc->sc_function][0]);
                   1525:        la = (struct nxe_lladdr *)&lladdr;
                   1526:        bcopy(la->lladdr, sc->sc_ac.ac_enaddr, ETHER_ADDR_LEN);
                   1527:
                   1528:        rv = 0;
                   1529: out:
                   1530:        free(nu, M_TEMP);
                   1531:        return (rv);
                   1532: }
                   1533:
                   1534: int
                   1535: nxe_init(struct nxe_softc *sc)
                   1536: {
                   1537:        u_int64_t                       dva;
                   1538:        u_int32_t                       r;
                   1539:
                   1540:        /* stop the chip from processing */
                   1541:        nxe_crb_write(sc, NXE_1_SW_CMD_PRODUCER(sc->sc_function), 0);
                   1542:        nxe_crb_write(sc, NXE_1_SW_CMD_CONSUMER(sc->sc_function), 0);
                   1543:        nxe_crb_write(sc, NXE_1_SW_CMD_ADDR_HI, 0);
                   1544:        nxe_crb_write(sc, NXE_1_SW_CMD_ADDR_LO, 0);
                   1545:
                   1546:        /*
                   1547:         * if this is the first port on the device it needs some special
                   1548:         * treatment to get things going.
                   1549:         */
                   1550:        if (sc->sc_function == 0) {
                   1551:                /* init adapter offload */
                   1552:                sc->sc_dummy_dma = nxe_dmamem_alloc(sc,
                   1553:                    NXE_1_SW_DUMMY_ADDR_LEN, PAGE_SIZE);
                   1554:                if (sc->sc_dummy_dma == NULL) {
                   1555:                        printf(": unable to allocate dummy memory\n");
                   1556:                        return (1);
                   1557:                }
                   1558:
                   1559:                bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(sc->sc_dummy_dma),
                   1560:                    0, NXE_DMA_LEN(sc->sc_dummy_dma), BUS_DMASYNC_PREREAD);
                   1561:
                   1562:                dva = NXE_DMA_DVA(sc->sc_dummy_dma);
                   1563:                nxe_crb_write(sc, NXE_1_SW_DUMMY_ADDR_HI, dva >> 32);
                   1564:                nxe_crb_write(sc, NXE_1_SW_DUMMY_ADDR_LO, dva);
                   1565:
                   1566:                r = nxe_crb_read(sc, NXE_1_SW_BOOTLD_CONFIG);
                   1567:                if (r == 0x55555555) {
                   1568:                        r = nxe_crb_read(sc, NXE_1_ROMUSB_SW_RESET);
                   1569:                        if (r != NXE_1_ROMUSB_SW_RESET_BOOT) {
                   1570:                                printf(": unexpected boot state\n");
                   1571:                                goto err;
                   1572:                        }
                   1573:
                   1574:                        /* clear */
                   1575:                        nxe_crb_write(sc, NXE_1_SW_BOOTLD_CONFIG, 0);
                   1576:                }
                   1577:
                   1578:                /* start the device up */
                   1579:                nxe_crb_write(sc, NXE_1_SW_DRIVER_VER, NXE_VERSION);
                   1580:                nxe_crb_write(sc, NXE_1_GLB_PEGTUNE, NXE_1_GLB_PEGTUNE_DONE);
                   1581:
                   1582:                /*
                   1583:                 * the firmware takes a long time to boot, so we'll check
                   1584:                 * it later on, and again when we want to bring a port up.
                   1585:                 */
                   1586:        }
                   1587:
                   1588:        return (0);
                   1589:
                   1590: err:
                   1591:        bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(sc->sc_dummy_dma),
                   1592:            0, NXE_DMA_LEN(sc->sc_dummy_dma), BUS_DMASYNC_POSTREAD);
                   1593:        nxe_dmamem_free(sc, sc->sc_dummy_dma);
                   1594:        return (1);
                   1595: }
                   1596:
                   1597: void
                   1598: nxe_uninit(struct nxe_softc *sc)
                   1599: {
                   1600:        if (sc->sc_function == 0) {
                   1601:                bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(sc->sc_dummy_dma),
                   1602:                    0, NXE_DMA_LEN(sc->sc_dummy_dma), BUS_DMASYNC_POSTREAD);
                   1603:                nxe_dmamem_free(sc, sc->sc_dummy_dma);
                   1604:        }
                   1605: }
                   1606:
                   1607: void
                   1608: nxe_mountroot(void *arg)
                   1609: {
                   1610:        struct nxe_softc                *sc = arg;
                   1611:
                   1612:        DASSERT(sc->sc_window == 1);
                   1613:
                   1614:        if (!nxe_crb_wait(sc, NXE_1_SW_CMDPEG_STATE, 0xffffffff,
                   1615:            NXE_1_SW_CMDPEG_STATE_DONE, 10000)) {
                   1616:                printf("%s: firmware bootstrap failed, code 0x%08x\n",
                   1617:                    DEVNAME(sc), nxe_crb_read(sc, NXE_1_SW_CMDPEG_STATE));
                   1618:                return;
                   1619:        }
                   1620:
                   1621:        sc->sc_port = nxe_crb_read(sc, NXE_1_SW_V2P(sc->sc_function));
                   1622:        if (sc->sc_port == 0x55555555)
                   1623:                sc->sc_port = sc->sc_function;
                   1624:
                   1625:        nxe_crb_write(sc, NXE_1_SW_NIC_CAP_HOST, NXE_1_SW_NIC_CAP_HOST_DEF);
                   1626:        nxe_crb_write(sc, NXE_1_SW_MPORT_MODE, NXE_1_SW_MPORT_MODE_MULTI);
                   1627:        nxe_crb_write(sc, NXE_1_SW_CMDPEG_STATE, NXE_1_SW_CMDPEG_STATE_ACK);
                   1628:
                   1629:        sc->sc_sensor.type = SENSOR_TEMP;
                   1630:        strlcpy(sc->sc_sensor_dev.xname, DEVNAME(sc),
                   1631:            sizeof(sc->sc_sensor_dev.xname));
                   1632:        sensor_attach(&sc->sc_sensor_dev, &sc->sc_sensor);
                   1633:        sensordev_install(&sc->sc_sensor_dev);
                   1634:
                   1635:        timeout_set(&sc->sc_tick, nxe_tick, sc);
                   1636:        nxe_tick(sc);
                   1637: }
                   1638:
                   1639: void
                   1640: nxe_tick(void *xsc)
                   1641: {
                   1642:        struct nxe_softc                *sc = xsc;
                   1643:        u_int32_t                       temp;
                   1644:        int                             window;
                   1645:        int                             s;
                   1646:
                   1647:        s = splnet();
                   1648:        window = nxe_crb_set(sc, 1);
                   1649:        temp = nxe_crb_read(sc, NXE_1_SW_TEMP);
                   1650:        nxe_link_state(sc);
                   1651:        nxe_crb_set(sc, window);
                   1652:        splx(s);
                   1653:
                   1654:        sc->sc_sensor.value = NXE_1_SW_TEMP_VAL(temp) * 1000000 + 273150000;
                   1655:        sc->sc_sensor.flags = 0;
                   1656:
                   1657:        switch (NXE_1_SW_TEMP_STATE(temp)) {
                   1658:        case NXE_1_SW_TEMP_STATE_NONE:
                   1659:                sc->sc_sensor.status = SENSOR_S_UNSPEC;
                   1660:                break;
                   1661:        case NXE_1_SW_TEMP_STATE_OK:
                   1662:                sc->sc_sensor.status = SENSOR_S_OK;
                   1663:                break;
                   1664:        case NXE_1_SW_TEMP_STATE_WARN:
                   1665:                sc->sc_sensor.status = SENSOR_S_WARN;
                   1666:                break;
                   1667:        case NXE_1_SW_TEMP_STATE_CRIT:
                   1668:                /* we should probably bring things down if this is true */
                   1669:                sc->sc_sensor.status = SENSOR_S_CRIT;
                   1670:                break;
                   1671:        default:
                   1672:                sc->sc_sensor.flags = SENSOR_FUNKNOWN;
                   1673:                break;
                   1674:        }
                   1675:
                   1676:        timeout_add(&sc->sc_tick, hz * 5);
                   1677: }
                   1678:
                   1679:
                   1680: struct nxe_ring *
                   1681: nxe_ring_alloc(struct nxe_softc *sc, size_t desclen, u_int nentries)
                   1682: {
                   1683:        struct nxe_ring                 *nr;
                   1684:
                   1685:        nr = malloc(sizeof(struct nxe_ring), M_DEVBUF, M_WAITOK);
                   1686:
                   1687:        nr->nr_dmamem = nxe_dmamem_alloc(sc, desclen * nentries, PAGE_SIZE);
                   1688:        if (nr->nr_dmamem == NULL) {
                   1689:                free(nr, M_DEVBUF);
                   1690:                return (NULL);
                   1691:        }
                   1692:
                   1693:        nr->nr_pos = NXE_DMA_KVA(nr->nr_dmamem);
                   1694:        nr->nr_slot = 0;
                   1695:        nr->nr_desclen = desclen;
                   1696:        nr->nr_nentries = nentries;
                   1697:
                   1698:        return (nr);
                   1699: }
                   1700:
                   1701: void
                   1702: nxe_ring_sync(struct nxe_softc *sc, struct nxe_ring *nr, int flags)
                   1703: {
                   1704:        bus_dmamap_sync(sc->sc_dmat, NXE_DMA_MAP(nr->nr_dmamem),
                   1705:            0, NXE_DMA_LEN(nr->nr_dmamem), flags);
                   1706: }
                   1707:
                   1708: void
                   1709: nxe_ring_free(struct nxe_softc *sc, struct nxe_ring *nr)
                   1710: {
                   1711:        nxe_dmamem_free(sc, nr->nr_dmamem);
                   1712:        free(nr, M_DEVBUF);
                   1713: }
                   1714:
                   1715: int
                   1716: nxe_ring_readable(struct nxe_ring *nr, int producer)
                   1717: {
                   1718:        nr->nr_ready = producer - nr->nr_slot;
                   1719:        if (nr->nr_ready < 0)
                   1720:                nr->nr_ready += nr->nr_nentries;
                   1721:
                   1722:        return (nr->nr_ready);
                   1723: }
                   1724:
                   1725: int
                   1726: nxe_ring_writeable(struct nxe_ring *nr, int consumer)
                   1727: {
                   1728:        nr->nr_ready = consumer - nr->nr_slot;
                   1729:        if (nr->nr_ready <= 0)
                   1730:                nr->nr_ready += nr->nr_nentries;
                   1731:
                   1732:        return (nr->nr_ready);
                   1733: }
                   1734:
                   1735: void *
                   1736: nxe_ring_cur(struct nxe_softc *sc, struct nxe_ring *nr)
                   1737: {
                   1738:        return (nr->nr_pos);
                   1739: }
                   1740:
                   1741: void *
                   1742: nxe_ring_next(struct nxe_softc *sc, struct nxe_ring *nr)
                   1743: {
                   1744:        if (++nr->nr_slot >= nr->nr_nentries) {
                   1745:                nr->nr_slot = 0;
                   1746:                nr->nr_pos = NXE_DMA_KVA(nr->nr_dmamem);
                   1747:        } else
                   1748:                nr->nr_pos += nr->nr_desclen;
                   1749:
                   1750:        nr->nr_ready--;
                   1751:
                   1752:        return (nr->nr_pos);
                   1753: }
                   1754:
                   1755: struct nxe_pkt_list *
                   1756: nxe_pkt_alloc(struct nxe_softc *sc, u_int npkts, int nsegs)
                   1757: {
                   1758:        struct nxe_pkt_list             *npl;
                   1759:        struct nxe_pkt                  *pkt;
                   1760:        int                             i;
                   1761:
                   1762:        npl = malloc(sizeof(struct nxe_pkt_list), M_DEVBUF, M_WAITOK);
                   1763:        bzero(npl, sizeof(struct nxe_pkt_list));
                   1764:
                   1765:        pkt = malloc(sizeof(struct nxe_pkt) * npkts, M_DEVBUF, M_WAITOK);
                   1766:        bzero(pkt, sizeof(struct nxe_pkt) * npkts);
                   1767:
                   1768:        npl->npl_pkts = pkt;
                   1769:        TAILQ_INIT(&npl->npl_free);
                   1770:        TAILQ_INIT(&npl->npl_used);
                   1771:        for (i = 0; i < npkts; i++) {
                   1772:                pkt = &npl->npl_pkts[i];
                   1773:
                   1774:                pkt->pkt_id = i;
                   1775:                if (bus_dmamap_create(sc->sc_dmat, NXE_MAX_PKTLEN, nsegs,
                   1776:                    NXE_MAX_PKTLEN, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
                   1777:                    &pkt->pkt_dmap) != 0) {
                   1778:                        nxe_pkt_free(sc, npl);
                   1779:                        return (NULL);
                   1780:                }
                   1781:
                   1782:                TAILQ_INSERT_TAIL(&npl->npl_free, pkt, pkt_link);
                   1783:        }
                   1784:
                   1785:        return (npl);
                   1786: }
                   1787:
                   1788: void
                   1789: nxe_pkt_free(struct nxe_softc *sc, struct nxe_pkt_list *npl)
                   1790: {
                   1791:        struct nxe_pkt                  *pkt;
                   1792:
                   1793:        while ((pkt = nxe_pkt_get(npl)) != NULL)
                   1794:                bus_dmamap_destroy(sc->sc_dmat, pkt->pkt_dmap);
                   1795:
                   1796:        free(npl->npl_pkts, M_DEVBUF);
                   1797:        free(npl, M_DEVBUF);
                   1798: }
                   1799:
                   1800: struct nxe_pkt *
                   1801: nxe_pkt_get(struct nxe_pkt_list *npl)
                   1802: {
                   1803:        struct nxe_pkt                  *pkt;
                   1804:
                   1805:        pkt = TAILQ_FIRST(&npl->npl_free);
                   1806:        if (pkt != NULL) {
                   1807:                TAILQ_REMOVE(&npl->npl_free, pkt, pkt_link);
                   1808:                TAILQ_INSERT_TAIL(&npl->npl_used, pkt, pkt_link);
                   1809:        }
                   1810:
                   1811:        return (pkt);
                   1812: }
                   1813:
                   1814: void
                   1815: nxe_pkt_put(struct nxe_pkt_list *npl, struct nxe_pkt *pkt)
                   1816: {
                   1817:        TAILQ_REMOVE(&npl->npl_used, pkt, pkt_link);
                   1818:        TAILQ_INSERT_TAIL(&npl->npl_free, pkt, pkt_link);
                   1819:
                   1820: }
                   1821:
                   1822: struct nxe_pkt *
                   1823: nxe_pkt_used(struct nxe_pkt_list *npl)
                   1824: {
                   1825:        return (TAILQ_FIRST(&npl->npl_used));
                   1826: }
                   1827:
                   1828: struct nxe_dmamem *
                   1829: nxe_dmamem_alloc(struct nxe_softc *sc, bus_size_t size, bus_size_t align)
                   1830: {
                   1831:        struct nxe_dmamem               *ndm;
                   1832:        int                             nsegs;
                   1833:
                   1834:        ndm = malloc(sizeof(struct nxe_dmamem), M_DEVBUF, M_WAITOK);
                   1835:        bzero(ndm, sizeof(struct nxe_dmamem));
                   1836:        ndm->ndm_size = size;
                   1837:
                   1838:        if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
                   1839:            BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &ndm->ndm_map) != 0)
                   1840:                goto ndmfree;
                   1841:
                   1842:        if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &ndm->ndm_seg, 1,
                   1843:            &nsegs, BUS_DMA_WAITOK) != 0)
                   1844:                goto destroy;
                   1845:
                   1846:        if (bus_dmamem_map(sc->sc_dmat, &ndm->ndm_seg, nsegs, size,
                   1847:            &ndm->ndm_kva, BUS_DMA_WAITOK) != 0)
                   1848:                goto free;
                   1849:
                   1850:        if (bus_dmamap_load(sc->sc_dmat, ndm->ndm_map, ndm->ndm_kva, size,
                   1851:            NULL, BUS_DMA_WAITOK) != 0)
                   1852:                goto unmap;
                   1853:
                   1854:        bzero(ndm->ndm_kva, size);
                   1855:
                   1856:        return (ndm);
                   1857:
                   1858: unmap:
                   1859:        bus_dmamem_unmap(sc->sc_dmat, ndm->ndm_kva, size);
                   1860: free:
                   1861:        bus_dmamem_free(sc->sc_dmat, &ndm->ndm_seg, 1);
                   1862: destroy:
                   1863:        bus_dmamap_destroy(sc->sc_dmat, ndm->ndm_map);
                   1864: ndmfree:
                   1865:        free(ndm, M_DEVBUF);
                   1866:
                   1867:        return (NULL);
                   1868: }
                   1869:
                   1870: void
                   1871: nxe_dmamem_free(struct nxe_softc *sc, struct nxe_dmamem *ndm)
                   1872: {
                   1873:        bus_dmamem_unmap(sc->sc_dmat, ndm->ndm_kva, ndm->ndm_size);
                   1874:        bus_dmamem_free(sc->sc_dmat, &ndm->ndm_seg, 1);
                   1875:        bus_dmamap_destroy(sc->sc_dmat, ndm->ndm_map);
                   1876:        free(ndm, M_DEVBUF);
                   1877: }
                   1878:
                   1879: u_int32_t
                   1880: nxe_read(struct nxe_softc *sc, bus_size_t r)
                   1881: {
                   1882:        bus_space_barrier(sc->sc_memt, sc->sc_memh, r, 4,
                   1883:            BUS_SPACE_BARRIER_READ);
                   1884:        return (bus_space_read_4(sc->sc_memt, sc->sc_memh, r));
                   1885: }
                   1886:
                   1887: void
                   1888: nxe_write(struct nxe_softc *sc, bus_size_t r, u_int32_t v)
                   1889: {
                   1890:        bus_space_write_4(sc->sc_memt, sc->sc_memh, r, v);
                   1891:        bus_space_barrier(sc->sc_memt, sc->sc_memh, r, 4,
                   1892:            BUS_SPACE_BARRIER_WRITE);
                   1893: }
                   1894:
                   1895: int
                   1896: nxe_wait(struct nxe_softc *sc, bus_size_t r, u_int32_t m, u_int32_t v,
                   1897:     u_int timeout)
                   1898: {
                   1899:        while ((nxe_read(sc, r) & m) != v) {
                   1900:                if (timeout == 0)
                   1901:                        return (0);
                   1902:
                   1903:                delay(1000);
                   1904:                timeout--;
                   1905:        }
                   1906:
                   1907:        return (1);
                   1908: }
                   1909:
                   1910: int
                   1911: nxe_crb_set(struct nxe_softc *sc, int window)
                   1912: {
                   1913:        int                     oldwindow = sc->sc_window;
                   1914:
                   1915:        if (sc->sc_window != window) {
                   1916:                sc->sc_window = window;
                   1917:
                   1918:                nxe_write(sc, NXE_WIN_CRB(sc->sc_function),
                   1919:                    window ? NXE_WIN_CRB_1 : NXE_WIN_CRB_0);
                   1920:        }
                   1921:
                   1922:        return (oldwindow);
                   1923: }
                   1924:
                   1925: u_int32_t
                   1926: nxe_crb_read(struct nxe_softc *sc, bus_size_t r)
                   1927: {
                   1928:        bus_space_barrier(sc->sc_memt, sc->sc_crbh, r, 4,
                   1929:            BUS_SPACE_BARRIER_READ);
                   1930:        return (bus_space_read_4(sc->sc_memt, sc->sc_crbh, r));
                   1931: }
                   1932:
                   1933: void
                   1934: nxe_crb_write(struct nxe_softc *sc, bus_size_t r, u_int32_t v)
                   1935: {
                   1936:        bus_space_write_4(sc->sc_memt, sc->sc_crbh, r, v);
                   1937:        bus_space_barrier(sc->sc_memt, sc->sc_crbh, r, 4,
                   1938:            BUS_SPACE_BARRIER_WRITE);
                   1939: }
                   1940:
                   1941: int
                   1942: nxe_crb_wait(struct nxe_softc *sc, bus_size_t r, u_int32_t m, u_int32_t v,
                   1943:     u_int timeout)
                   1944: {
                   1945:        while ((nxe_crb_read(sc, r) & m) != v) {
                   1946:                if (timeout == 0)
                   1947:                        return (0);
                   1948:
                   1949:                delay(1000);
                   1950:                timeout--;
                   1951:        }
                   1952:
                   1953:        return (1);
                   1954: }
                   1955:
                   1956: int
                   1957: nxe_rom_lock(struct nxe_softc *sc)
                   1958: {
                   1959:        if (!nxe_wait(sc, NXE_SEM_ROM_LOCK, 0xffffffff,
                   1960:            NXE_SEM_DONE, 10000))
                   1961:                return (1);
                   1962:        nxe_crb_write(sc, NXE_1_SW_ROM_LOCK_ID, NXE_1_SW_ROM_LOCK_ID);
                   1963:
                   1964:        return (0);
                   1965: }
                   1966:
                   1967: void
                   1968: nxe_rom_unlock(struct nxe_softc *sc)
                   1969: {
                   1970:        nxe_read(sc, NXE_SEM_ROM_UNLOCK);
                   1971: }
                   1972:
                   1973: int
                   1974: nxe_rom_read(struct nxe_softc *sc, u_int32_t r, u_int32_t *v)
                   1975: {
                   1976:        int                     rv = 1;
                   1977:
                   1978:        DASSERT(sc->sc_window == 1);
                   1979:
                   1980:        if (nxe_rom_lock(sc) != 0)
                   1981:                return (1);
                   1982:
                   1983:        /* set the rom address */
                   1984:        nxe_crb_write(sc, NXE_1_ROM_ADDR, r);
                   1985:
                   1986:        /* set the xfer len */
                   1987:        nxe_crb_write(sc, NXE_1_ROM_ABYTE_CNT, 3);
                   1988:        delay(100); /* used to prevent bursting on the chipset */
                   1989:        nxe_crb_write(sc, NXE_1_ROM_DBYTE_CNT, 0);
                   1990:
                   1991:        /* set opcode and wait for completion */
                   1992:        nxe_crb_write(sc, NXE_1_ROM_OPCODE, NXE_1_ROM_OPCODE_READ);
                   1993:        if (!nxe_crb_wait(sc, NXE_1_ROMUSB_STATUS, NXE_1_ROMUSB_STATUS_DONE,
                   1994:            NXE_1_ROMUSB_STATUS_DONE, 100))
                   1995:                goto err;
                   1996:
                   1997:        /* reset counters */
                   1998:        nxe_crb_write(sc, NXE_1_ROM_ABYTE_CNT, 0);
                   1999:        delay(100);
                   2000:        nxe_crb_write(sc, NXE_1_ROM_DBYTE_CNT, 0);
                   2001:
                   2002:        *v = nxe_crb_read(sc, NXE_1_ROM_RDATA);
                   2003:
                   2004:        rv = 0;
                   2005: err:
                   2006:        nxe_rom_unlock(sc);
                   2007:        return (rv);
                   2008: }
                   2009:
                   2010: int
                   2011: nxe_rom_read_region(struct nxe_softc *sc, u_int32_t r, void *buf,
                   2012:     size_t buflen)
                   2013: {
                   2014:        u_int32_t               *databuf = buf;
                   2015:        int                     i;
                   2016:
                   2017: #ifdef NXE_DEBUG
                   2018:        if ((buflen % 4) != 0)
                   2019:                panic("nxe_read_rom_region: buflen is wrong (%d)", buflen);
                   2020: #endif
                   2021:
                   2022:        buflen = buflen / 4;
                   2023:        for (i = 0; i < buflen; i++) {
                   2024:                if (nxe_rom_read(sc, r, &databuf[i]) != 0)
                   2025:                        return (1);
                   2026:
                   2027:                r += sizeof(u_int32_t);
                   2028:        }
                   2029:
                   2030:        return (0);
                   2031: }

CVSweb