Annotation of sys/dev/pci/if_nxe.c, Revision 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