|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 2008 Michael Brown <[email protected]>. ! 3: * Copyright (C) 2008 NetXen, Inc. ! 4: * ! 5: * This program is free software; you can redistribute it and/or ! 6: * modify it under the terms of the GNU General Public License as ! 7: * published by the Free Software Foundation; either version 2 of the ! 8: * License, or any later version. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, but ! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 13: * General Public License for more details. ! 14: * ! 15: * You should have received a copy of the GNU General Public License ! 16: * along with this program; if not, write to the Free Software ! 17: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 18: */ ! 19: ! 20: FILE_LICENCE ( GPL2_OR_LATER ); ! 21: ! 22: #include <stdint.h> ! 23: #include <stdlib.h> ! 24: #include <string.h> ! 25: #include <unistd.h> ! 26: #include <errno.h> ! 27: #include <assert.h> ! 28: #include <byteswap.h> ! 29: #include <ipxe/pci.h> ! 30: #include <ipxe/io.h> ! 31: #include <ipxe/malloc.h> ! 32: #include <ipxe/iobuf.h> ! 33: #include <ipxe/netdevice.h> ! 34: #include <ipxe/if_ether.h> ! 35: #include <ipxe/ethernet.h> ! 36: #include <ipxe/spi.h> ! 37: #include <ipxe/settings.h> ! 38: #include "phantom.h" ! 39: ! 40: /** ! 41: * @file ! 42: * ! 43: * NetXen Phantom NICs ! 44: * ! 45: */ ! 46: ! 47: /** Maximum number of ports */ ! 48: #define PHN_MAX_NUM_PORTS 8 ! 49: ! 50: /** Maximum time to wait for command PEG to initialise ! 51: * ! 52: * BUGxxxx ! 53: * ! 54: * The command PEG will currently report initialisation complete only ! 55: * when at least one PHY has detected a link (so that the global PHY ! 56: * clock can be set to 10G/1G as appropriate). This can take a very, ! 57: * very long time. ! 58: * ! 59: * A future firmware revision should decouple PHY initialisation from ! 60: * firmware initialisation, at which point the command PEG will report ! 61: * initialisation complete much earlier, and this timeout can be ! 62: * reduced. ! 63: */ ! 64: #define PHN_CMDPEG_INIT_TIMEOUT_SEC 50 ! 65: ! 66: /** Maximum time to wait for receive PEG to initialise */ ! 67: #define PHN_RCVPEG_INIT_TIMEOUT_SEC 2 ! 68: ! 69: /** Maximum time to wait for firmware to accept a command */ ! 70: #define PHN_ISSUE_CMD_TIMEOUT_MS 2000 ! 71: ! 72: /** Maximum time to wait for test memory */ ! 73: #define PHN_TEST_MEM_TIMEOUT_MS 100 ! 74: ! 75: /** Maximum time to wait for CLP command to be issued */ ! 76: #define PHN_CLP_CMD_TIMEOUT_MS 500 ! 77: ! 78: /** Link state poll frequency ! 79: * ! 80: * The link state will be checked once in every N calls to poll(). ! 81: */ ! 82: #define PHN_LINK_POLL_FREQUENCY 4096 ! 83: ! 84: /** Number of RX descriptors */ ! 85: #define PHN_NUM_RDS 32 ! 86: ! 87: /** RX maximum fill level. Must be strictly less than PHN_NUM_RDS. */ ! 88: #define PHN_RDS_MAX_FILL 16 ! 89: ! 90: /** RX buffer size */ ! 91: #define PHN_RX_BUFSIZE ( 32 /* max LL padding added by card */ + \ ! 92: ETH_FRAME_LEN ) ! 93: ! 94: /** Number of RX status descriptors */ ! 95: #define PHN_NUM_SDS 32 ! 96: ! 97: /** Number of TX descriptors */ ! 98: #define PHN_NUM_CDS 8 ! 99: ! 100: /** A Phantom descriptor ring set */ ! 101: struct phantom_descriptor_rings { ! 102: /** RX descriptors */ ! 103: struct phantom_rds rds[PHN_NUM_RDS]; ! 104: /** RX status descriptors */ ! 105: struct phantom_sds sds[PHN_NUM_SDS]; ! 106: /** TX descriptors */ ! 107: union phantom_cds cds[PHN_NUM_CDS]; ! 108: /** TX consumer index */ ! 109: volatile uint32_t cmd_cons; ! 110: }; ! 111: ! 112: /** RX context creation request and response buffers */ ! 113: struct phantom_create_rx_ctx_rqrsp { ! 114: struct { ! 115: struct nx_hostrq_rx_ctx_s rx_ctx; ! 116: struct nx_hostrq_rds_ring_s rds; ! 117: struct nx_hostrq_sds_ring_s sds; ! 118: } __unm_dma_aligned hostrq; ! 119: struct { ! 120: struct nx_cardrsp_rx_ctx_s rx_ctx; ! 121: struct nx_cardrsp_rds_ring_s rds; ! 122: struct nx_cardrsp_sds_ring_s sds; ! 123: } __unm_dma_aligned cardrsp; ! 124: }; ! 125: ! 126: /** TX context creation request and response buffers */ ! 127: struct phantom_create_tx_ctx_rqrsp { ! 128: struct { ! 129: struct nx_hostrq_tx_ctx_s tx_ctx; ! 130: } __unm_dma_aligned hostrq; ! 131: struct { ! 132: struct nx_cardrsp_tx_ctx_s tx_ctx; ! 133: } __unm_dma_aligned cardrsp; ! 134: }; ! 135: ! 136: /** A Phantom NIC */ ! 137: struct phantom_nic { ! 138: /** BAR 0 */ ! 139: void *bar0; ! 140: /** Current CRB window */ ! 141: unsigned long crb_window; ! 142: /** CRB window access method */ ! 143: unsigned long ( *crb_access ) ( struct phantom_nic *phantom, ! 144: unsigned long reg ); ! 145: ! 146: ! 147: /** Port number */ ! 148: unsigned int port; ! 149: ! 150: ! 151: /** RX context ID */ ! 152: uint16_t rx_context_id; ! 153: /** RX descriptor producer CRB offset */ ! 154: unsigned long rds_producer_crb; ! 155: /** RX status descriptor consumer CRB offset */ ! 156: unsigned long sds_consumer_crb; ! 157: /** RX interrupt mask CRB offset */ ! 158: unsigned long sds_irq_mask_crb; ! 159: /** RX interrupts enabled */ ! 160: unsigned int sds_irq_enabled; ! 161: ! 162: /** RX producer index */ ! 163: unsigned int rds_producer_idx; ! 164: /** RX consumer index */ ! 165: unsigned int rds_consumer_idx; ! 166: /** RX status consumer index */ ! 167: unsigned int sds_consumer_idx; ! 168: /** RX I/O buffers */ ! 169: struct io_buffer *rds_iobuf[PHN_RDS_MAX_FILL]; ! 170: ! 171: ! 172: /** TX context ID */ ! 173: uint16_t tx_context_id; ! 174: /** TX descriptor producer CRB offset */ ! 175: unsigned long cds_producer_crb; ! 176: ! 177: /** TX producer index */ ! 178: unsigned int cds_producer_idx; ! 179: /** TX consumer index */ ! 180: unsigned int cds_consumer_idx; ! 181: /** TX I/O buffers */ ! 182: struct io_buffer *cds_iobuf[PHN_NUM_CDS]; ! 183: ! 184: ! 185: /** Descriptor rings */ ! 186: struct phantom_descriptor_rings *desc; ! 187: ! 188: ! 189: /** Last known link state */ ! 190: uint32_t link_state; ! 191: /** Link state poll timer */ ! 192: unsigned long link_poll_timer; ! 193: ! 194: ! 195: /** Non-volatile settings */ ! 196: struct settings settings; ! 197: }; ! 198: ! 199: /** Interrupt mask registers */ ! 200: static const unsigned long phantom_irq_mask_reg[PHN_MAX_NUM_PORTS] = { ! 201: UNM_PCIE_IRQ_MASK_F0, ! 202: UNM_PCIE_IRQ_MASK_F1, ! 203: UNM_PCIE_IRQ_MASK_F2, ! 204: UNM_PCIE_IRQ_MASK_F3, ! 205: UNM_PCIE_IRQ_MASK_F4, ! 206: UNM_PCIE_IRQ_MASK_F5, ! 207: UNM_PCIE_IRQ_MASK_F6, ! 208: UNM_PCIE_IRQ_MASK_F7, ! 209: }; ! 210: ! 211: /** Interrupt status registers */ ! 212: static const unsigned long phantom_irq_status_reg[PHN_MAX_NUM_PORTS] = { ! 213: UNM_PCIE_IRQ_STATUS_F0, ! 214: UNM_PCIE_IRQ_STATUS_F1, ! 215: UNM_PCIE_IRQ_STATUS_F2, ! 216: UNM_PCIE_IRQ_STATUS_F3, ! 217: UNM_PCIE_IRQ_STATUS_F4, ! 218: UNM_PCIE_IRQ_STATUS_F5, ! 219: UNM_PCIE_IRQ_STATUS_F6, ! 220: UNM_PCIE_IRQ_STATUS_F7, ! 221: }; ! 222: ! 223: /*************************************************************************** ! 224: * ! 225: * CRB register access ! 226: * ! 227: */ ! 228: ! 229: /** ! 230: * Prepare for access to CRB register via 128MB BAR ! 231: * ! 232: * @v phantom Phantom NIC ! 233: * @v reg Register offset within abstract address space ! 234: * @ret offset Register offset within PCI BAR0 ! 235: */ ! 236: static unsigned long phantom_crb_access_128m ( struct phantom_nic *phantom, ! 237: unsigned long reg ) { ! 238: unsigned long offset = ( 0x6000000 + ( reg & 0x1ffffff ) ); ! 239: uint32_t window = ( reg & 0x2000000 ); ! 240: uint32_t verify_window; ! 241: ! 242: if ( phantom->crb_window != window ) { ! 243: ! 244: /* Write to the CRB window register */ ! 245: writel ( window, phantom->bar0 + UNM_128M_CRB_WINDOW ); ! 246: ! 247: /* Ensure that the write has reached the card */ ! 248: verify_window = readl ( phantom->bar0 + UNM_128M_CRB_WINDOW ); ! 249: assert ( verify_window == window ); ! 250: ! 251: /* Record new window */ ! 252: phantom->crb_window = window; ! 253: } ! 254: ! 255: return offset; ! 256: } ! 257: ! 258: /** ! 259: * Prepare for access to CRB register via 32MB BAR ! 260: * ! 261: * @v phantom Phantom NIC ! 262: * @v reg Register offset within abstract address space ! 263: * @ret offset Register offset within PCI BAR0 ! 264: */ ! 265: static unsigned long phantom_crb_access_32m ( struct phantom_nic *phantom, ! 266: unsigned long reg ) { ! 267: unsigned long offset = ( reg & 0x1ffffff ); ! 268: uint32_t window = ( reg & 0x2000000 ); ! 269: uint32_t verify_window; ! 270: ! 271: if ( phantom->crb_window != window ) { ! 272: ! 273: /* Write to the CRB window register */ ! 274: writel ( window, phantom->bar0 + UNM_32M_CRB_WINDOW ); ! 275: ! 276: /* Ensure that the write has reached the card */ ! 277: verify_window = readl ( phantom->bar0 + UNM_32M_CRB_WINDOW ); ! 278: assert ( verify_window == window ); ! 279: ! 280: /* Record new window */ ! 281: phantom->crb_window = window; ! 282: } ! 283: ! 284: return offset; ! 285: } ! 286: ! 287: /** ! 288: * Prepare for access to CRB register via 2MB BAR ! 289: * ! 290: * @v phantom Phantom NIC ! 291: * @v reg Register offset within abstract address space ! 292: * @ret offset Register offset within PCI BAR0 ! 293: */ ! 294: static unsigned long phantom_crb_access_2m ( struct phantom_nic *phantom, ! 295: unsigned long reg ) { ! 296: static const struct { ! 297: uint8_t block; ! 298: uint16_t window_hi; ! 299: } reg_window_hi[] = { ! 300: { UNM_CRB_BLK_PCIE, 0x773 }, ! 301: { UNM_CRB_BLK_CAM, 0x416 }, ! 302: { UNM_CRB_BLK_ROMUSB, 0x421 }, ! 303: { UNM_CRB_BLK_TEST, 0x295 }, ! 304: { UNM_CRB_BLK_PEG_0, 0x340 }, ! 305: { UNM_CRB_BLK_PEG_1, 0x341 }, ! 306: { UNM_CRB_BLK_PEG_2, 0x342 }, ! 307: { UNM_CRB_BLK_PEG_3, 0x343 }, ! 308: { UNM_CRB_BLK_PEG_4, 0x34b }, ! 309: }; ! 310: unsigned int block = UNM_CRB_BLK ( reg ); ! 311: unsigned long offset = UNM_CRB_OFFSET ( reg ); ! 312: uint32_t window; ! 313: uint32_t verify_window; ! 314: unsigned int i; ! 315: ! 316: for ( i = 0 ; i < ( sizeof ( reg_window_hi ) / ! 317: sizeof ( reg_window_hi[0] ) ) ; i++ ) { ! 318: ! 319: if ( reg_window_hi[i].block != block ) ! 320: continue; ! 321: ! 322: window = ( ( reg_window_hi[i].window_hi << 20 ) | ! 323: ( offset & 0x000f0000 ) ); ! 324: ! 325: if ( phantom->crb_window != window ) { ! 326: ! 327: /* Write to the CRB window register */ ! 328: writel ( window, phantom->bar0 + UNM_2M_CRB_WINDOW ); ! 329: ! 330: /* Ensure that the write has reached the card */ ! 331: verify_window = readl ( phantom->bar0 + ! 332: UNM_2M_CRB_WINDOW ); ! 333: assert ( verify_window == window ); ! 334: ! 335: /* Record new window */ ! 336: phantom->crb_window = window; ! 337: } ! 338: ! 339: return ( 0x1e0000 + ( offset & 0xffff ) ); ! 340: } ! 341: ! 342: assert ( 0 ); ! 343: return 0; ! 344: } ! 345: ! 346: /** ! 347: * Read from Phantom CRB register ! 348: * ! 349: * @v phantom Phantom NIC ! 350: * @v reg Register offset within abstract address space ! 351: * @ret value Register value ! 352: */ ! 353: static uint32_t phantom_readl ( struct phantom_nic *phantom, ! 354: unsigned long reg ) { ! 355: unsigned long offset; ! 356: ! 357: offset = phantom->crb_access ( phantom, reg ); ! 358: return readl ( phantom->bar0 + offset ); ! 359: } ! 360: ! 361: /** ! 362: * Write to Phantom CRB register ! 363: * ! 364: * @v phantom Phantom NIC ! 365: * @v value Register value ! 366: * @v reg Register offset within abstract address space ! 367: */ ! 368: static void phantom_writel ( struct phantom_nic *phantom, uint32_t value, ! 369: unsigned long reg ) { ! 370: unsigned long offset; ! 371: ! 372: offset = phantom->crb_access ( phantom, reg ); ! 373: writel ( value, phantom->bar0 + offset ); ! 374: } ! 375: ! 376: /** ! 377: * Write to Phantom CRB HI/LO register pair ! 378: * ! 379: * @v phantom Phantom NIC ! 380: * @v value Register value ! 381: * @v lo_offset LO register offset within CRB ! 382: * @v hi_offset HI register offset within CRB ! 383: */ ! 384: static inline void phantom_write_hilo ( struct phantom_nic *phantom, ! 385: uint64_t value, ! 386: unsigned long lo_offset, ! 387: unsigned long hi_offset ) { ! 388: uint32_t lo = ( value & 0xffffffffUL ); ! 389: uint32_t hi = ( value >> 32 ); ! 390: ! 391: phantom_writel ( phantom, lo, lo_offset ); ! 392: phantom_writel ( phantom, hi, hi_offset ); ! 393: } ! 394: ! 395: /*************************************************************************** ! 396: * ! 397: * Firmware message buffer access (for debug) ! 398: * ! 399: */ ! 400: ! 401: /** ! 402: * Read from Phantom test memory ! 403: * ! 404: * @v phantom Phantom NIC ! 405: * @v offset Offset within test memory ! 406: * @v buf 8-byte buffer to fill ! 407: * @ret rc Return status code ! 408: */ ! 409: static int phantom_read_test_mem_block ( struct phantom_nic *phantom, ! 410: unsigned long offset, ! 411: uint32_t buf[2] ) { ! 412: unsigned int retries; ! 413: uint32_t test_control; ! 414: ! 415: phantom_write_hilo ( phantom, offset, UNM_TEST_ADDR_LO, ! 416: UNM_TEST_ADDR_HI ); ! 417: phantom_writel ( phantom, UNM_TEST_CONTROL_ENABLE, UNM_TEST_CONTROL ); ! 418: phantom_writel ( phantom, ! 419: ( UNM_TEST_CONTROL_ENABLE | UNM_TEST_CONTROL_START ), ! 420: UNM_TEST_CONTROL ); ! 421: ! 422: for ( retries = 0 ; retries < PHN_TEST_MEM_TIMEOUT_MS ; retries++ ) { ! 423: test_control = phantom_readl ( phantom, UNM_TEST_CONTROL ); ! 424: if ( ( test_control & UNM_TEST_CONTROL_BUSY ) == 0 ) { ! 425: buf[0] = phantom_readl ( phantom, UNM_TEST_RDDATA_LO ); ! 426: buf[1] = phantom_readl ( phantom, UNM_TEST_RDDATA_HI ); ! 427: return 0; ! 428: } ! 429: mdelay ( 1 ); ! 430: } ! 431: ! 432: DBGC ( phantom, "Phantom %p timed out waiting for test memory\n", ! 433: phantom ); ! 434: return -ETIMEDOUT; ! 435: } ! 436: ! 437: /** ! 438: * Read single byte from Phantom test memory ! 439: * ! 440: * @v phantom Phantom NIC ! 441: * @v offset Offset within test memory ! 442: * @ret byte Byte read, or negative error ! 443: */ ! 444: static int phantom_read_test_mem ( struct phantom_nic *phantom, ! 445: unsigned long offset ) { ! 446: static union { ! 447: uint8_t bytes[8]; ! 448: uint32_t dwords[2]; ! 449: } cache; ! 450: static unsigned long cache_offset = -1UL; ! 451: unsigned long sub_offset; ! 452: int rc; ! 453: ! 454: sub_offset = ( offset & ( sizeof ( cache ) - 1 ) ); ! 455: offset = ( offset & ~( sizeof ( cache ) - 1 ) ); ! 456: ! 457: if ( cache_offset != offset ) { ! 458: if ( ( rc = phantom_read_test_mem_block ( phantom, offset, ! 459: cache.dwords )) !=0 ) ! 460: return rc; ! 461: cache_offset = offset; ! 462: } ! 463: ! 464: return cache.bytes[sub_offset]; ! 465: } ! 466: ! 467: /** ! 468: * Dump Phantom firmware dmesg log ! 469: * ! 470: * @v phantom Phantom NIC ! 471: * @v log Log number ! 472: * @v max_lines Maximum number of lines to show, or -1 to show all ! 473: * @ret rc Return status code ! 474: */ ! 475: static int phantom_dmesg ( struct phantom_nic *phantom, unsigned int log, ! 476: unsigned int max_lines ) { ! 477: uint32_t head; ! 478: uint32_t tail; ! 479: uint32_t sig; ! 480: uint32_t offset; ! 481: int byte; ! 482: ! 483: /* Optimise out for non-debug builds */ ! 484: if ( ! DBG_LOG ) ! 485: return 0; ! 486: ! 487: /* Locate log */ ! 488: head = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_HEAD ( log ) ); ! 489: tail = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_TAIL ( log ) ); ! 490: sig = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_SIG ( log ) ); ! 491: DBGC ( phantom, "Phantom %p firmware dmesg buffer %d (%08x-%08x)\n", ! 492: phantom, log, head, tail ); ! 493: assert ( ( head & 0x07 ) == 0 ); ! 494: if ( sig != UNM_CAM_RAM_DMESG_SIG_MAGIC ) { ! 495: DBGC ( phantom, "Warning: bad signature %08x (want %08lx)\n", ! 496: sig, UNM_CAM_RAM_DMESG_SIG_MAGIC ); ! 497: } ! 498: ! 499: /* Locate start of last (max_lines) lines */ ! 500: for ( offset = tail ; offset > head ; offset-- ) { ! 501: if ( ( byte = phantom_read_test_mem ( phantom, ! 502: ( offset - 1 ) ) ) < 0 ) ! 503: return byte; ! 504: if ( ( byte == '\n' ) && ( max_lines-- == 0 ) ) ! 505: break; ! 506: } ! 507: ! 508: /* Print lines */ ! 509: for ( ; offset < tail ; offset++ ) { ! 510: if ( ( byte = phantom_read_test_mem ( phantom, offset ) ) < 0 ) ! 511: return byte; ! 512: DBG ( "%c", byte ); ! 513: } ! 514: DBG ( "\n" ); ! 515: return 0; ! 516: } ! 517: ! 518: /** ! 519: * Dump Phantom firmware dmesg logs ! 520: * ! 521: * @v phantom Phantom NIC ! 522: * @v max_lines Maximum number of lines to show, or -1 to show all ! 523: */ ! 524: static void __attribute__ (( unused )) ! 525: phantom_dmesg_all ( struct phantom_nic *phantom, unsigned int max_lines ) { ! 526: unsigned int i; ! 527: ! 528: for ( i = 0 ; i < UNM_CAM_RAM_NUM_DMESG_BUFFERS ; i++ ) ! 529: phantom_dmesg ( phantom, i, max_lines ); ! 530: } ! 531: ! 532: /*************************************************************************** ! 533: * ! 534: * Firmware interface ! 535: * ! 536: */ ! 537: ! 538: /** ! 539: * Wait for firmware to accept command ! 540: * ! 541: * @v phantom Phantom NIC ! 542: * @ret rc Return status code ! 543: */ ! 544: static int phantom_wait_for_cmd ( struct phantom_nic *phantom ) { ! 545: unsigned int retries; ! 546: uint32_t cdrp; ! 547: ! 548: for ( retries = 0 ; retries < PHN_ISSUE_CMD_TIMEOUT_MS ; retries++ ) { ! 549: mdelay ( 1 ); ! 550: cdrp = phantom_readl ( phantom, UNM_NIC_REG_NX_CDRP ); ! 551: if ( NX_CDRP_IS_RSP ( cdrp ) ) { ! 552: switch ( NX_CDRP_FORM_RSP ( cdrp ) ) { ! 553: case NX_CDRP_RSP_OK: ! 554: return 0; ! 555: case NX_CDRP_RSP_FAIL: ! 556: return -EIO; ! 557: case NX_CDRP_RSP_TIMEOUT: ! 558: return -ETIMEDOUT; ! 559: default: ! 560: return -EPROTO; ! 561: } ! 562: } ! 563: } ! 564: ! 565: DBGC ( phantom, "Phantom %p timed out waiting for firmware to accept " ! 566: "command\n", phantom ); ! 567: return -ETIMEDOUT; ! 568: } ! 569: ! 570: /** ! 571: * Issue command to firmware ! 572: * ! 573: * @v phantom Phantom NIC ! 574: * @v command Firmware command ! 575: * @v arg1 Argument 1 ! 576: * @v arg2 Argument 2 ! 577: * @v arg3 Argument 3 ! 578: * @ret rc Return status code ! 579: */ ! 580: static int phantom_issue_cmd ( struct phantom_nic *phantom, ! 581: uint32_t command, uint32_t arg1, uint32_t arg2, ! 582: uint32_t arg3 ) { ! 583: uint32_t signature; ! 584: int rc; ! 585: ! 586: /* Issue command */ ! 587: signature = NX_CDRP_SIGNATURE_MAKE ( phantom->port, ! 588: NXHAL_VERSION ); ! 589: DBGC2 ( phantom, "Phantom %p issuing command %08x (%08x, %08x, " ! 590: "%08x)\n", phantom, command, arg1, arg2, arg3 ); ! 591: phantom_writel ( phantom, signature, UNM_NIC_REG_NX_SIGN ); ! 592: phantom_writel ( phantom, arg1, UNM_NIC_REG_NX_ARG1 ); ! 593: phantom_writel ( phantom, arg2, UNM_NIC_REG_NX_ARG2 ); ! 594: phantom_writel ( phantom, arg3, UNM_NIC_REG_NX_ARG3 ); ! 595: phantom_writel ( phantom, NX_CDRP_FORM_CMD ( command ), ! 596: UNM_NIC_REG_NX_CDRP ); ! 597: ! 598: /* Wait for command to be accepted */ ! 599: if ( ( rc = phantom_wait_for_cmd ( phantom ) ) != 0 ) { ! 600: DBGC ( phantom, "Phantom %p could not issue command: %s\n", ! 601: phantom, strerror ( rc ) ); ! 602: return rc; ! 603: } ! 604: ! 605: return 0; ! 606: } ! 607: ! 608: /** ! 609: * Issue buffer-format command to firmware ! 610: * ! 611: * @v phantom Phantom NIC ! 612: * @v command Firmware command ! 613: * @v buffer Buffer to pass to firmware ! 614: * @v len Length of buffer ! 615: * @ret rc Return status code ! 616: */ ! 617: static int phantom_issue_buf_cmd ( struct phantom_nic *phantom, ! 618: uint32_t command, void *buffer, ! 619: size_t len ) { ! 620: uint64_t physaddr; ! 621: ! 622: physaddr = virt_to_bus ( buffer ); ! 623: return phantom_issue_cmd ( phantom, command, ( physaddr >> 32 ), ! 624: ( physaddr & 0xffffffffUL ), len ); ! 625: } ! 626: ! 627: /** ! 628: * Create Phantom RX context ! 629: * ! 630: * @v phantom Phantom NIC ! 631: * @ret rc Return status code ! 632: */ ! 633: static int phantom_create_rx_ctx ( struct phantom_nic *phantom ) { ! 634: struct phantom_create_rx_ctx_rqrsp *buf; ! 635: int rc; ! 636: ! 637: /* Allocate context creation buffer */ ! 638: buf = malloc_dma ( sizeof ( *buf ), UNM_DMA_BUFFER_ALIGN ); ! 639: if ( ! buf ) { ! 640: rc = -ENOMEM; ! 641: goto out; ! 642: } ! 643: memset ( buf, 0, sizeof ( *buf ) ); ! 644: ! 645: /* Prepare request */ ! 646: buf->hostrq.rx_ctx.host_rsp_dma_addr = ! 647: cpu_to_le64 ( virt_to_bus ( &buf->cardrsp ) ); ! 648: buf->hostrq.rx_ctx.capabilities[0] = ! 649: cpu_to_le32 ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN ); ! 650: buf->hostrq.rx_ctx.host_int_crb_mode = ! 651: cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED ); ! 652: buf->hostrq.rx_ctx.host_rds_crb_mode = ! 653: cpu_to_le32 ( NX_HOST_RDS_CRB_MODE_UNIQUE ); ! 654: buf->hostrq.rx_ctx.rds_ring_offset = cpu_to_le32 ( 0 ); ! 655: buf->hostrq.rx_ctx.sds_ring_offset = ! 656: cpu_to_le32 ( sizeof ( buf->hostrq.rds ) ); ! 657: buf->hostrq.rx_ctx.num_rds_rings = cpu_to_le16 ( 1 ); ! 658: buf->hostrq.rx_ctx.num_sds_rings = cpu_to_le16 ( 1 ); ! 659: buf->hostrq.rds.host_phys_addr = ! 660: cpu_to_le64 ( virt_to_bus ( phantom->desc->rds ) ); ! 661: buf->hostrq.rds.buff_size = cpu_to_le64 ( PHN_RX_BUFSIZE ); ! 662: buf->hostrq.rds.ring_size = cpu_to_le32 ( PHN_NUM_RDS ); ! 663: buf->hostrq.rds.ring_kind = cpu_to_le32 ( NX_RDS_RING_TYPE_NORMAL ); ! 664: buf->hostrq.sds.host_phys_addr = ! 665: cpu_to_le64 ( virt_to_bus ( phantom->desc->sds ) ); ! 666: buf->hostrq.sds.ring_size = cpu_to_le32 ( PHN_NUM_SDS ); ! 667: ! 668: DBGC ( phantom, "Phantom %p creating RX context\n", phantom ); ! 669: DBGC2_HDA ( phantom, virt_to_bus ( &buf->hostrq ), ! 670: &buf->hostrq, sizeof ( buf->hostrq ) ); ! 671: ! 672: /* Issue request */ ! 673: if ( ( rc = phantom_issue_buf_cmd ( phantom, ! 674: NX_CDRP_CMD_CREATE_RX_CTX, ! 675: &buf->hostrq, ! 676: sizeof ( buf->hostrq ) ) ) != 0 ) { ! 677: DBGC ( phantom, "Phantom %p could not create RX context: " ! 678: "%s\n", phantom, strerror ( rc ) ); ! 679: DBGC ( phantom, "Request:\n" ); ! 680: DBGC_HDA ( phantom, virt_to_bus ( &buf->hostrq ), ! 681: &buf->hostrq, sizeof ( buf->hostrq ) ); ! 682: DBGC ( phantom, "Response:\n" ); ! 683: DBGC_HDA ( phantom, virt_to_bus ( &buf->cardrsp ), ! 684: &buf->cardrsp, sizeof ( buf->cardrsp ) ); ! 685: goto out; ! 686: } ! 687: ! 688: /* Retrieve context parameters */ ! 689: phantom->rx_context_id = ! 690: le16_to_cpu ( buf->cardrsp.rx_ctx.context_id ); ! 691: phantom->rds_producer_crb = ! 692: ( UNM_CAM_RAM + ! 693: le32_to_cpu ( buf->cardrsp.rds.host_producer_crb ) ); ! 694: phantom->sds_consumer_crb = ! 695: ( UNM_CAM_RAM + ! 696: le32_to_cpu ( buf->cardrsp.sds.host_consumer_crb ) ); ! 697: phantom->sds_irq_mask_crb = ! 698: ( UNM_CAM_RAM + ! 699: le32_to_cpu ( buf->cardrsp.sds.interrupt_crb ) ); ! 700: ! 701: DBGC ( phantom, "Phantom %p created RX context (id %04x, port phys " ! 702: "%02x virt %02x)\n", phantom, phantom->rx_context_id, ! 703: buf->cardrsp.rx_ctx.phys_port, buf->cardrsp.rx_ctx.virt_port ); ! 704: DBGC2_HDA ( phantom, virt_to_bus ( &buf->cardrsp ), ! 705: &buf->cardrsp, sizeof ( buf->cardrsp ) ); ! 706: DBGC ( phantom, "Phantom %p RDS producer CRB is %08lx\n", ! 707: phantom, phantom->rds_producer_crb ); ! 708: DBGC ( phantom, "Phantom %p SDS consumer CRB is %08lx\n", ! 709: phantom, phantom->sds_consumer_crb ); ! 710: DBGC ( phantom, "Phantom %p SDS interrupt mask CRB is %08lx\n", ! 711: phantom, phantom->sds_irq_mask_crb ); ! 712: ! 713: out: ! 714: free_dma ( buf, sizeof ( *buf ) ); ! 715: return rc; ! 716: } ! 717: ! 718: /** ! 719: * Destroy Phantom RX context ! 720: * ! 721: * @v phantom Phantom NIC ! 722: * @ret rc Return status code ! 723: */ ! 724: static void phantom_destroy_rx_ctx ( struct phantom_nic *phantom ) { ! 725: int rc; ! 726: ! 727: DBGC ( phantom, "Phantom %p destroying RX context (id %04x)\n", ! 728: phantom, phantom->rx_context_id ); ! 729: ! 730: /* Issue request */ ! 731: if ( ( rc = phantom_issue_cmd ( phantom, ! 732: NX_CDRP_CMD_DESTROY_RX_CTX, ! 733: phantom->rx_context_id, ! 734: NX_DESTROY_CTX_RESET, 0 ) ) != 0 ) { ! 735: DBGC ( phantom, "Phantom %p could not destroy RX context: " ! 736: "%s\n", phantom, strerror ( rc ) ); ! 737: /* We're probably screwed */ ! 738: return; ! 739: } ! 740: ! 741: /* Clear context parameters */ ! 742: phantom->rx_context_id = 0; ! 743: phantom->rds_producer_crb = 0; ! 744: phantom->sds_consumer_crb = 0; ! 745: ! 746: /* Reset software counters */ ! 747: phantom->rds_producer_idx = 0; ! 748: phantom->rds_consumer_idx = 0; ! 749: phantom->sds_consumer_idx = 0; ! 750: } ! 751: ! 752: /** ! 753: * Create Phantom TX context ! 754: * ! 755: * @v phantom Phantom NIC ! 756: * @ret rc Return status code ! 757: */ ! 758: static int phantom_create_tx_ctx ( struct phantom_nic *phantom ) { ! 759: struct phantom_create_tx_ctx_rqrsp *buf; ! 760: int rc; ! 761: ! 762: /* Allocate context creation buffer */ ! 763: buf = malloc_dma ( sizeof ( *buf ), UNM_DMA_BUFFER_ALIGN ); ! 764: if ( ! buf ) { ! 765: rc = -ENOMEM; ! 766: goto out; ! 767: } ! 768: memset ( buf, 0, sizeof ( *buf ) ); ! 769: ! 770: /* Prepare request */ ! 771: buf->hostrq.tx_ctx.host_rsp_dma_addr = ! 772: cpu_to_le64 ( virt_to_bus ( &buf->cardrsp ) ); ! 773: buf->hostrq.tx_ctx.cmd_cons_dma_addr = ! 774: cpu_to_le64 ( virt_to_bus ( &phantom->desc->cmd_cons ) ); ! 775: buf->hostrq.tx_ctx.capabilities[0] = ! 776: cpu_to_le32 ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN ); ! 777: buf->hostrq.tx_ctx.host_int_crb_mode = ! 778: cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED ); ! 779: buf->hostrq.tx_ctx.cds_ring.host_phys_addr = ! 780: cpu_to_le64 ( virt_to_bus ( phantom->desc->cds ) ); ! 781: buf->hostrq.tx_ctx.cds_ring.ring_size = cpu_to_le32 ( PHN_NUM_CDS ); ! 782: ! 783: DBGC ( phantom, "Phantom %p creating TX context\n", phantom ); ! 784: DBGC2_HDA ( phantom, virt_to_bus ( &buf->hostrq ), ! 785: &buf->hostrq, sizeof ( buf->hostrq ) ); ! 786: ! 787: /* Issue request */ ! 788: if ( ( rc = phantom_issue_buf_cmd ( phantom, ! 789: NX_CDRP_CMD_CREATE_TX_CTX, ! 790: &buf->hostrq, ! 791: sizeof ( buf->hostrq ) ) ) != 0 ) { ! 792: DBGC ( phantom, "Phantom %p could not create TX context: " ! 793: "%s\n", phantom, strerror ( rc ) ); ! 794: DBGC ( phantom, "Request:\n" ); ! 795: DBGC_HDA ( phantom, virt_to_bus ( &buf->hostrq ), ! 796: &buf->hostrq, sizeof ( buf->hostrq ) ); ! 797: DBGC ( phantom, "Response:\n" ); ! 798: DBGC_HDA ( phantom, virt_to_bus ( &buf->cardrsp ), ! 799: &buf->cardrsp, sizeof ( buf->cardrsp ) ); ! 800: goto out; ! 801: } ! 802: ! 803: /* Retrieve context parameters */ ! 804: phantom->tx_context_id = ! 805: le16_to_cpu ( buf->cardrsp.tx_ctx.context_id ); ! 806: phantom->cds_producer_crb = ! 807: ( UNM_CAM_RAM + ! 808: le32_to_cpu(buf->cardrsp.tx_ctx.cds_ring.host_producer_crb)); ! 809: ! 810: DBGC ( phantom, "Phantom %p created TX context (id %04x, port phys " ! 811: "%02x virt %02x)\n", phantom, phantom->tx_context_id, ! 812: buf->cardrsp.tx_ctx.phys_port, buf->cardrsp.tx_ctx.virt_port ); ! 813: DBGC2_HDA ( phantom, virt_to_bus ( &buf->cardrsp ), ! 814: &buf->cardrsp, sizeof ( buf->cardrsp ) ); ! 815: DBGC ( phantom, "Phantom %p CDS producer CRB is %08lx\n", ! 816: phantom, phantom->cds_producer_crb ); ! 817: ! 818: out: ! 819: free_dma ( buf, sizeof ( *buf ) ); ! 820: return rc; ! 821: } ! 822: ! 823: /** ! 824: * Destroy Phantom TX context ! 825: * ! 826: * @v phantom Phantom NIC ! 827: * @ret rc Return status code ! 828: */ ! 829: static void phantom_destroy_tx_ctx ( struct phantom_nic *phantom ) { ! 830: int rc; ! 831: ! 832: DBGC ( phantom, "Phantom %p destroying TX context (id %04x)\n", ! 833: phantom, phantom->tx_context_id ); ! 834: ! 835: /* Issue request */ ! 836: if ( ( rc = phantom_issue_cmd ( phantom, ! 837: NX_CDRP_CMD_DESTROY_TX_CTX, ! 838: phantom->tx_context_id, ! 839: NX_DESTROY_CTX_RESET, 0 ) ) != 0 ) { ! 840: DBGC ( phantom, "Phantom %p could not destroy TX context: " ! 841: "%s\n", phantom, strerror ( rc ) ); ! 842: /* We're probably screwed */ ! 843: return; ! 844: } ! 845: ! 846: /* Clear context parameters */ ! 847: phantom->tx_context_id = 0; ! 848: phantom->cds_producer_crb = 0; ! 849: ! 850: /* Reset software counters */ ! 851: phantom->cds_producer_idx = 0; ! 852: phantom->cds_consumer_idx = 0; ! 853: } ! 854: ! 855: /*************************************************************************** ! 856: * ! 857: * Descriptor ring management ! 858: * ! 859: */ ! 860: ! 861: /** ! 862: * Allocate Phantom RX descriptor ! 863: * ! 864: * @v phantom Phantom NIC ! 865: * @ret index RX descriptor index, or negative error ! 866: */ ! 867: static int phantom_alloc_rds ( struct phantom_nic *phantom ) { ! 868: unsigned int rds_producer_idx; ! 869: unsigned int next_rds_producer_idx; ! 870: ! 871: /* Check for space in the ring. RX descriptors are consumed ! 872: * out of order, but they are *read* by the hardware in strict ! 873: * order. We maintain a pessimistic consumer index, which is ! 874: * guaranteed never to be an overestimate of the number of ! 875: * descriptors read by the hardware. ! 876: */ ! 877: rds_producer_idx = phantom->rds_producer_idx; ! 878: next_rds_producer_idx = ( ( rds_producer_idx + 1 ) % PHN_NUM_RDS ); ! 879: if ( next_rds_producer_idx == phantom->rds_consumer_idx ) { ! 880: DBGC ( phantom, "Phantom %p RDS ring full (index %d not " ! 881: "consumed)\n", phantom, next_rds_producer_idx ); ! 882: return -ENOBUFS; ! 883: } ! 884: ! 885: return rds_producer_idx; ! 886: } ! 887: ! 888: /** ! 889: * Post Phantom RX descriptor ! 890: * ! 891: * @v phantom Phantom NIC ! 892: * @v rds RX descriptor ! 893: */ ! 894: static void phantom_post_rds ( struct phantom_nic *phantom, ! 895: struct phantom_rds *rds ) { ! 896: unsigned int rds_producer_idx; ! 897: unsigned int next_rds_producer_idx; ! 898: struct phantom_rds *entry; ! 899: ! 900: /* Copy descriptor to ring */ ! 901: rds_producer_idx = phantom->rds_producer_idx; ! 902: entry = &phantom->desc->rds[rds_producer_idx]; ! 903: memcpy ( entry, rds, sizeof ( *entry ) ); ! 904: DBGC2 ( phantom, "Phantom %p posting RDS %ld (slot %d):\n", ! 905: phantom, NX_GET ( rds, handle ), rds_producer_idx ); ! 906: DBGC2_HDA ( phantom, virt_to_bus ( entry ), entry, sizeof ( *entry ) ); ! 907: ! 908: /* Update producer index */ ! 909: next_rds_producer_idx = ( ( rds_producer_idx + 1 ) % PHN_NUM_RDS ); ! 910: phantom->rds_producer_idx = next_rds_producer_idx; ! 911: wmb(); ! 912: phantom_writel ( phantom, phantom->rds_producer_idx, ! 913: phantom->rds_producer_crb ); ! 914: } ! 915: ! 916: /** ! 917: * Allocate Phantom TX descriptor ! 918: * ! 919: * @v phantom Phantom NIC ! 920: * @ret index TX descriptor index, or negative error ! 921: */ ! 922: static int phantom_alloc_cds ( struct phantom_nic *phantom ) { ! 923: unsigned int cds_producer_idx; ! 924: unsigned int next_cds_producer_idx; ! 925: ! 926: /* Check for space in the ring. TX descriptors are consumed ! 927: * in strict order, so we just check for a collision against ! 928: * the consumer index. ! 929: */ ! 930: cds_producer_idx = phantom->cds_producer_idx; ! 931: next_cds_producer_idx = ( ( cds_producer_idx + 1 ) % PHN_NUM_CDS ); ! 932: if ( next_cds_producer_idx == phantom->cds_consumer_idx ) { ! 933: DBGC ( phantom, "Phantom %p CDS ring full (index %d not " ! 934: "consumed)\n", phantom, next_cds_producer_idx ); ! 935: return -ENOBUFS; ! 936: } ! 937: ! 938: return cds_producer_idx; ! 939: } ! 940: ! 941: /** ! 942: * Post Phantom TX descriptor ! 943: * ! 944: * @v phantom Phantom NIC ! 945: * @v cds TX descriptor ! 946: */ ! 947: static void phantom_post_cds ( struct phantom_nic *phantom, ! 948: union phantom_cds *cds ) { ! 949: unsigned int cds_producer_idx; ! 950: unsigned int next_cds_producer_idx; ! 951: union phantom_cds *entry; ! 952: ! 953: /* Copy descriptor to ring */ ! 954: cds_producer_idx = phantom->cds_producer_idx; ! 955: entry = &phantom->desc->cds[cds_producer_idx]; ! 956: memcpy ( entry, cds, sizeof ( *entry ) ); ! 957: DBGC2 ( phantom, "Phantom %p posting CDS %d:\n", ! 958: phantom, cds_producer_idx ); ! 959: DBGC2_HDA ( phantom, virt_to_bus ( entry ), entry, sizeof ( *entry ) ); ! 960: ! 961: /* Update producer index */ ! 962: next_cds_producer_idx = ( ( cds_producer_idx + 1 ) % PHN_NUM_CDS ); ! 963: phantom->cds_producer_idx = next_cds_producer_idx; ! 964: wmb(); ! 965: phantom_writel ( phantom, phantom->cds_producer_idx, ! 966: phantom->cds_producer_crb ); ! 967: } ! 968: ! 969: /*************************************************************************** ! 970: * ! 971: * MAC address management ! 972: * ! 973: */ ! 974: ! 975: /** ! 976: * Add/remove MAC address ! 977: * ! 978: * @v phantom Phantom NIC ! 979: * @v ll_addr MAC address to add or remove ! 980: * @v opcode MAC request opcode ! 981: * @ret rc Return status code ! 982: */ ! 983: static int phantom_update_macaddr ( struct phantom_nic *phantom, ! 984: const uint8_t *ll_addr, ! 985: unsigned int opcode ) { ! 986: union phantom_cds cds; ! 987: int index; ! 988: ! 989: /* Get descriptor ring entry */ ! 990: index = phantom_alloc_cds ( phantom ); ! 991: if ( index < 0 ) ! 992: return index; ! 993: ! 994: /* Fill descriptor ring entry */ ! 995: memset ( &cds, 0, sizeof ( cds ) ); ! 996: NX_FILL_1 ( &cds, 0, ! 997: nic_request.common.opcode, UNM_NIC_REQUEST ); ! 998: NX_FILL_2 ( &cds, 1, ! 999: nic_request.header.opcode, UNM_MAC_EVENT, ! 1000: nic_request.header.context_id, phantom->port ); ! 1001: NX_FILL_7 ( &cds, 2, ! 1002: nic_request.body.mac_request.opcode, opcode, ! 1003: nic_request.body.mac_request.mac_addr_0, ll_addr[0], ! 1004: nic_request.body.mac_request.mac_addr_1, ll_addr[1], ! 1005: nic_request.body.mac_request.mac_addr_2, ll_addr[2], ! 1006: nic_request.body.mac_request.mac_addr_3, ll_addr[3], ! 1007: nic_request.body.mac_request.mac_addr_4, ll_addr[4], ! 1008: nic_request.body.mac_request.mac_addr_5, ll_addr[5] ); ! 1009: ! 1010: /* Post descriptor */ ! 1011: phantom_post_cds ( phantom, &cds ); ! 1012: ! 1013: return 0; ! 1014: } ! 1015: ! 1016: /** ! 1017: * Add MAC address ! 1018: * ! 1019: * @v phantom Phantom NIC ! 1020: * @v ll_addr MAC address to add or remove ! 1021: * @ret rc Return status code ! 1022: */ ! 1023: static inline int phantom_add_macaddr ( struct phantom_nic *phantom, ! 1024: const uint8_t *ll_addr ) { ! 1025: ! 1026: DBGC ( phantom, "Phantom %p adding MAC address %s\n", ! 1027: phantom, eth_ntoa ( ll_addr ) ); ! 1028: ! 1029: return phantom_update_macaddr ( phantom, ll_addr, UNM_MAC_ADD ); ! 1030: } ! 1031: ! 1032: /** ! 1033: * Remove MAC address ! 1034: * ! 1035: * @v phantom Phantom NIC ! 1036: * @v ll_addr MAC address to add or remove ! 1037: * @ret rc Return status code ! 1038: */ ! 1039: static inline int phantom_del_macaddr ( struct phantom_nic *phantom, ! 1040: const uint8_t *ll_addr ) { ! 1041: ! 1042: DBGC ( phantom, "Phantom %p removing MAC address %s\n", ! 1043: phantom, eth_ntoa ( ll_addr ) ); ! 1044: ! 1045: return phantom_update_macaddr ( phantom, ll_addr, UNM_MAC_DEL ); ! 1046: } ! 1047: ! 1048: /*************************************************************************** ! 1049: * ! 1050: * Link state detection ! 1051: * ! 1052: */ ! 1053: ! 1054: /** ! 1055: * Poll link state ! 1056: * ! 1057: * @v netdev Network device ! 1058: */ ! 1059: static void phantom_poll_link_state ( struct net_device *netdev ) { ! 1060: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 1061: uint32_t xg_state_p3; ! 1062: unsigned int link; ! 1063: ! 1064: /* Read link state */ ! 1065: xg_state_p3 = phantom_readl ( phantom, UNM_NIC_REG_XG_STATE_P3 ); ! 1066: ! 1067: /* If there is no change, do nothing */ ! 1068: if ( phantom->link_state == xg_state_p3 ) ! 1069: return; ! 1070: ! 1071: /* Record new link state */ ! 1072: DBGC ( phantom, "Phantom %p new link state %08x (was %08x)\n", ! 1073: phantom, xg_state_p3, phantom->link_state ); ! 1074: phantom->link_state = xg_state_p3; ! 1075: ! 1076: /* Indicate link state to iPXE */ ! 1077: link = UNM_NIC_REG_XG_STATE_P3_LINK ( phantom->port, ! 1078: phantom->link_state ); ! 1079: switch ( link ) { ! 1080: case UNM_NIC_REG_XG_STATE_P3_LINK_UP: ! 1081: DBGC ( phantom, "Phantom %p link is up\n", phantom ); ! 1082: netdev_link_up ( netdev ); ! 1083: break; ! 1084: case UNM_NIC_REG_XG_STATE_P3_LINK_DOWN: ! 1085: DBGC ( phantom, "Phantom %p link is down\n", phantom ); ! 1086: netdev_link_down ( netdev ); ! 1087: break; ! 1088: default: ! 1089: DBGC ( phantom, "Phantom %p bad link state %d\n", ! 1090: phantom, link ); ! 1091: break; ! 1092: } ! 1093: } ! 1094: ! 1095: /*************************************************************************** ! 1096: * ! 1097: * Main driver body ! 1098: * ! 1099: */ ! 1100: ! 1101: /** ! 1102: * Refill descriptor ring ! 1103: * ! 1104: * @v netdev Net device ! 1105: */ ! 1106: static void phantom_refill_rx_ring ( struct net_device *netdev ) { ! 1107: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 1108: struct io_buffer *iobuf; ! 1109: struct phantom_rds rds; ! 1110: unsigned int handle; ! 1111: int index; ! 1112: ! 1113: for ( handle = 0 ; handle < PHN_RDS_MAX_FILL ; handle++ ) { ! 1114: ! 1115: /* Skip this index if the descriptor has not yet been ! 1116: * consumed. ! 1117: */ ! 1118: if ( phantom->rds_iobuf[handle] != NULL ) ! 1119: continue; ! 1120: ! 1121: /* Allocate descriptor ring entry */ ! 1122: index = phantom_alloc_rds ( phantom ); ! 1123: assert ( PHN_RDS_MAX_FILL < PHN_NUM_RDS ); ! 1124: assert ( index >= 0 ); /* Guaranteed by MAX_FILL < NUM_RDS ) */ ! 1125: ! 1126: /* Try to allocate an I/O buffer */ ! 1127: iobuf = alloc_iob ( PHN_RX_BUFSIZE ); ! 1128: if ( ! iobuf ) { ! 1129: /* Failure is non-fatal; we will retry later */ ! 1130: netdev_rx_err ( netdev, NULL, -ENOMEM ); ! 1131: break; ! 1132: } ! 1133: ! 1134: /* Fill descriptor ring entry */ ! 1135: memset ( &rds, 0, sizeof ( rds ) ); ! 1136: NX_FILL_2 ( &rds, 0, ! 1137: handle, handle, ! 1138: length, iob_len ( iobuf ) ); ! 1139: NX_FILL_1 ( &rds, 1, ! 1140: dma_addr, virt_to_bus ( iobuf->data ) ); ! 1141: ! 1142: /* Record I/O buffer */ ! 1143: assert ( phantom->rds_iobuf[handle] == NULL ); ! 1144: phantom->rds_iobuf[handle] = iobuf; ! 1145: ! 1146: /* Post descriptor */ ! 1147: phantom_post_rds ( phantom, &rds ); ! 1148: } ! 1149: } ! 1150: ! 1151: /** ! 1152: * Open NIC ! 1153: * ! 1154: * @v netdev Net device ! 1155: * @ret rc Return status code ! 1156: */ ! 1157: static int phantom_open ( struct net_device *netdev ) { ! 1158: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 1159: int rc; ! 1160: ! 1161: /* Allocate and zero descriptor rings */ ! 1162: phantom->desc = malloc_dma ( sizeof ( *(phantom->desc) ), ! 1163: UNM_DMA_BUFFER_ALIGN ); ! 1164: if ( ! phantom->desc ) { ! 1165: rc = -ENOMEM; ! 1166: goto err_alloc_desc; ! 1167: } ! 1168: memset ( phantom->desc, 0, sizeof ( *(phantom->desc) ) ); ! 1169: ! 1170: /* Create RX context */ ! 1171: if ( ( rc = phantom_create_rx_ctx ( phantom ) ) != 0 ) ! 1172: goto err_create_rx_ctx; ! 1173: ! 1174: /* Create TX context */ ! 1175: if ( ( rc = phantom_create_tx_ctx ( phantom ) ) != 0 ) ! 1176: goto err_create_tx_ctx; ! 1177: ! 1178: /* Fill the RX descriptor ring */ ! 1179: phantom_refill_rx_ring ( netdev ); ! 1180: ! 1181: /* Add MAC addresses ! 1182: * ! 1183: * BUG5583 ! 1184: * ! 1185: * We would like to be able to enable receiving all multicast ! 1186: * packets (or, failing that, promiscuous mode), but the ! 1187: * firmware doesn't currently support this. ! 1188: */ ! 1189: if ( ( rc = phantom_add_macaddr ( phantom, ! 1190: netdev->ll_broadcast ) ) != 0 ) ! 1191: goto err_add_macaddr_broadcast; ! 1192: if ( ( rc = phantom_add_macaddr ( phantom, ! 1193: netdev->ll_addr ) ) != 0 ) ! 1194: goto err_add_macaddr_unicast; ! 1195: ! 1196: return 0; ! 1197: ! 1198: phantom_del_macaddr ( phantom, netdev->ll_addr ); ! 1199: err_add_macaddr_unicast: ! 1200: phantom_del_macaddr ( phantom, netdev->ll_broadcast ); ! 1201: err_add_macaddr_broadcast: ! 1202: phantom_destroy_tx_ctx ( phantom ); ! 1203: err_create_tx_ctx: ! 1204: phantom_destroy_rx_ctx ( phantom ); ! 1205: err_create_rx_ctx: ! 1206: free_dma ( phantom->desc, sizeof ( *(phantom->desc) ) ); ! 1207: phantom->desc = NULL; ! 1208: err_alloc_desc: ! 1209: return rc; ! 1210: } ! 1211: ! 1212: /** ! 1213: * Close NIC ! 1214: * ! 1215: * @v netdev Net device ! 1216: */ ! 1217: static void phantom_close ( struct net_device *netdev ) { ! 1218: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 1219: struct io_buffer *iobuf; ! 1220: unsigned int i; ! 1221: ! 1222: /* Shut down the port */ ! 1223: phantom_del_macaddr ( phantom, netdev->ll_addr ); ! 1224: phantom_del_macaddr ( phantom, netdev->ll_broadcast ); ! 1225: phantom_destroy_tx_ctx ( phantom ); ! 1226: phantom_destroy_rx_ctx ( phantom ); ! 1227: free_dma ( phantom->desc, sizeof ( *(phantom->desc) ) ); ! 1228: phantom->desc = NULL; ! 1229: ! 1230: /* Flush any uncompleted descriptors */ ! 1231: for ( i = 0 ; i < PHN_RDS_MAX_FILL ; i++ ) { ! 1232: iobuf = phantom->rds_iobuf[i]; ! 1233: if ( iobuf ) { ! 1234: free_iob ( iobuf ); ! 1235: phantom->rds_iobuf[i] = NULL; ! 1236: } ! 1237: } ! 1238: for ( i = 0 ; i < PHN_NUM_CDS ; i++ ) { ! 1239: iobuf = phantom->cds_iobuf[i]; ! 1240: if ( iobuf ) { ! 1241: netdev_tx_complete_err ( netdev, iobuf, -ECANCELED ); ! 1242: phantom->cds_iobuf[i] = NULL; ! 1243: } ! 1244: } ! 1245: } ! 1246: ! 1247: /** ! 1248: * Transmit packet ! 1249: * ! 1250: * @v netdev Network device ! 1251: * @v iobuf I/O buffer ! 1252: * @ret rc Return status code ! 1253: */ ! 1254: static int phantom_transmit ( struct net_device *netdev, ! 1255: struct io_buffer *iobuf ) { ! 1256: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 1257: union phantom_cds cds; ! 1258: int index; ! 1259: ! 1260: /* Get descriptor ring entry */ ! 1261: index = phantom_alloc_cds ( phantom ); ! 1262: if ( index < 0 ) ! 1263: return index; ! 1264: ! 1265: /* Fill descriptor ring entry */ ! 1266: memset ( &cds, 0, sizeof ( cds ) ); ! 1267: NX_FILL_3 ( &cds, 0, ! 1268: tx.opcode, UNM_TX_ETHER_PKT, ! 1269: tx.num_buffers, 1, ! 1270: tx.length, iob_len ( iobuf ) ); ! 1271: NX_FILL_2 ( &cds, 2, ! 1272: tx.port, phantom->port, ! 1273: tx.context_id, phantom->port ); ! 1274: NX_FILL_1 ( &cds, 4, ! 1275: tx.buffer1_dma_addr, virt_to_bus ( iobuf->data ) ); ! 1276: NX_FILL_1 ( &cds, 5, ! 1277: tx.buffer1_length, iob_len ( iobuf ) ); ! 1278: ! 1279: /* Record I/O buffer */ ! 1280: assert ( phantom->cds_iobuf[index] == NULL ); ! 1281: phantom->cds_iobuf[index] = iobuf; ! 1282: ! 1283: /* Post descriptor */ ! 1284: phantom_post_cds ( phantom, &cds ); ! 1285: ! 1286: return 0; ! 1287: } ! 1288: ! 1289: /** ! 1290: * Poll for received packets ! 1291: * ! 1292: * @v netdev Network device ! 1293: */ ! 1294: static void phantom_poll ( struct net_device *netdev ) { ! 1295: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 1296: struct io_buffer *iobuf; ! 1297: unsigned int irq_vector; ! 1298: unsigned int irq_state; ! 1299: unsigned int cds_consumer_idx; ! 1300: unsigned int raw_new_cds_consumer_idx; ! 1301: unsigned int new_cds_consumer_idx; ! 1302: unsigned int rds_consumer_idx; ! 1303: unsigned int sds_consumer_idx; ! 1304: struct phantom_sds *sds; ! 1305: unsigned int sds_handle; ! 1306: unsigned int sds_opcode; ! 1307: ! 1308: /* Occasionally poll the link state */ ! 1309: if ( phantom->link_poll_timer-- == 0 ) { ! 1310: phantom_poll_link_state ( netdev ); ! 1311: /* Reset the link poll timer */ ! 1312: phantom->link_poll_timer = PHN_LINK_POLL_FREQUENCY; ! 1313: } ! 1314: ! 1315: /* Check for interrupts */ ! 1316: if ( phantom->sds_irq_enabled ) { ! 1317: ! 1318: /* Do nothing unless an interrupt is asserted */ ! 1319: irq_vector = phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR ); ! 1320: if ( ! ( irq_vector & UNM_PCIE_IRQ_VECTOR_BIT( phantom->port ))) ! 1321: return; ! 1322: ! 1323: /* Do nothing unless interrupt state machine has stabilised */ ! 1324: irq_state = phantom_readl ( phantom, UNM_PCIE_IRQ_STATE ); ! 1325: if ( ! UNM_PCIE_IRQ_STATE_TRIGGERED ( irq_state ) ) ! 1326: return; ! 1327: ! 1328: /* Acknowledge interrupt */ ! 1329: phantom_writel ( phantom, UNM_PCIE_IRQ_STATUS_MAGIC, ! 1330: phantom_irq_status_reg[phantom->port] ); ! 1331: phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR ); ! 1332: } ! 1333: ! 1334: /* Check for TX completions */ ! 1335: cds_consumer_idx = phantom->cds_consumer_idx; ! 1336: raw_new_cds_consumer_idx = phantom->desc->cmd_cons; ! 1337: new_cds_consumer_idx = le32_to_cpu ( raw_new_cds_consumer_idx ); ! 1338: while ( cds_consumer_idx != new_cds_consumer_idx ) { ! 1339: DBGC2 ( phantom, "Phantom %p CDS %d complete\n", ! 1340: phantom, cds_consumer_idx ); ! 1341: /* Completions may be for commands other than TX, so ! 1342: * there may not always be an associated I/O buffer. ! 1343: */ ! 1344: if ( ( iobuf = phantom->cds_iobuf[cds_consumer_idx] ) ) { ! 1345: netdev_tx_complete ( netdev, iobuf ); ! 1346: phantom->cds_iobuf[cds_consumer_idx] = NULL; ! 1347: } ! 1348: cds_consumer_idx = ( ( cds_consumer_idx + 1 ) % PHN_NUM_CDS ); ! 1349: phantom->cds_consumer_idx = cds_consumer_idx; ! 1350: } ! 1351: ! 1352: /* Check for received packets */ ! 1353: rds_consumer_idx = phantom->rds_consumer_idx; ! 1354: sds_consumer_idx = phantom->sds_consumer_idx; ! 1355: while ( 1 ) { ! 1356: sds = &phantom->desc->sds[sds_consumer_idx]; ! 1357: if ( NX_GET ( sds, owner ) == 0 ) ! 1358: break; ! 1359: ! 1360: DBGC2 ( phantom, "Phantom %p SDS %d status:\n", ! 1361: phantom, sds_consumer_idx ); ! 1362: DBGC2_HDA ( phantom, virt_to_bus ( sds ), sds, sizeof (*sds) ); ! 1363: ! 1364: /* Check received opcode */ ! 1365: sds_opcode = NX_GET ( sds, opcode ); ! 1366: if ( ( sds_opcode == UNM_RXPKT_DESC ) || ! 1367: ( sds_opcode == UNM_SYN_OFFLOAD ) ) { ! 1368: ! 1369: /* Sanity check: ensure that all of the SDS ! 1370: * descriptor has been written. ! 1371: */ ! 1372: if ( NX_GET ( sds, total_length ) == 0 ) { ! 1373: DBGC ( phantom, "Phantom %p SDS %d " ! 1374: "incomplete; deferring\n", ! 1375: phantom, sds_consumer_idx ); ! 1376: /* Leave for next poll() */ ! 1377: break; ! 1378: } ! 1379: ! 1380: /* Process received packet */ ! 1381: sds_handle = NX_GET ( sds, handle ); ! 1382: iobuf = phantom->rds_iobuf[sds_handle]; ! 1383: assert ( iobuf != NULL ); ! 1384: iob_put ( iobuf, NX_GET ( sds, total_length ) ); ! 1385: iob_pull ( iobuf, NX_GET ( sds, pkt_offset ) ); ! 1386: DBGC2 ( phantom, "Phantom %p RDS %d complete\n", ! 1387: phantom, sds_handle ); ! 1388: netdev_rx ( netdev, iobuf ); ! 1389: phantom->rds_iobuf[sds_handle] = NULL; ! 1390: ! 1391: /* Update RDS consumer counter. This is a ! 1392: * lower bound for the number of descriptors ! 1393: * that have been read by the hardware, since ! 1394: * the hardware must have read at least one ! 1395: * descriptor for each completion that we ! 1396: * receive. ! 1397: */ ! 1398: rds_consumer_idx = ! 1399: ( ( rds_consumer_idx + 1 ) % PHN_NUM_RDS ); ! 1400: phantom->rds_consumer_idx = rds_consumer_idx; ! 1401: ! 1402: } else { ! 1403: ! 1404: DBGC ( phantom, "Phantom %p unexpected SDS opcode " ! 1405: "%02x\n", phantom, sds_opcode ); ! 1406: DBGC_HDA ( phantom, virt_to_bus ( sds ), ! 1407: sds, sizeof ( *sds ) ); ! 1408: } ! 1409: ! 1410: /* Clear status descriptor */ ! 1411: memset ( sds, 0, sizeof ( *sds ) ); ! 1412: ! 1413: /* Update SDS consumer index */ ! 1414: sds_consumer_idx = ( ( sds_consumer_idx + 1 ) % PHN_NUM_SDS ); ! 1415: phantom->sds_consumer_idx = sds_consumer_idx; ! 1416: wmb(); ! 1417: phantom_writel ( phantom, phantom->sds_consumer_idx, ! 1418: phantom->sds_consumer_crb ); ! 1419: } ! 1420: ! 1421: /* Refill the RX descriptor ring */ ! 1422: phantom_refill_rx_ring ( netdev ); ! 1423: } ! 1424: ! 1425: /** ! 1426: * Enable/disable interrupts ! 1427: * ! 1428: * @v netdev Network device ! 1429: * @v enable Interrupts should be enabled ! 1430: */ ! 1431: static void phantom_irq ( struct net_device *netdev, int enable ) { ! 1432: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 1433: ! 1434: phantom_writel ( phantom, ( enable ? 1 : 0 ), ! 1435: phantom->sds_irq_mask_crb ); ! 1436: phantom_writel ( phantom, UNM_PCIE_IRQ_MASK_MAGIC, ! 1437: phantom_irq_mask_reg[phantom->port] ); ! 1438: phantom->sds_irq_enabled = enable; ! 1439: } ! 1440: ! 1441: /** Phantom net device operations */ ! 1442: static struct net_device_operations phantom_operations = { ! 1443: .open = phantom_open, ! 1444: .close = phantom_close, ! 1445: .transmit = phantom_transmit, ! 1446: .poll = phantom_poll, ! 1447: .irq = phantom_irq, ! 1448: }; ! 1449: ! 1450: /*************************************************************************** ! 1451: * ! 1452: * CLP settings ! 1453: * ! 1454: */ ! 1455: ! 1456: /** Phantom CLP settings tag magic */ ! 1457: #define PHN_CLP_TAG_MAGIC 0xc19c1900UL ! 1458: ! 1459: /** Phantom CLP settings tag magic mask */ ! 1460: #define PHN_CLP_TAG_MAGIC_MASK 0xffffff00UL ! 1461: ! 1462: /** Phantom CLP data ! 1463: * ! 1464: */ ! 1465: union phantom_clp_data { ! 1466: /** Data bytes ! 1467: * ! 1468: * This field is right-aligned; if only N bytes are present ! 1469: * then bytes[0]..bytes[7-N] should be zero, and the data ! 1470: * should be in bytes[7-N+1] to bytes[7]; ! 1471: */ ! 1472: uint8_t bytes[8]; ! 1473: /** Dwords for the CLP interface */ ! 1474: struct { ! 1475: /** High dword, in network byte order */ ! 1476: uint32_t hi; ! 1477: /** Low dword, in network byte order */ ! 1478: uint32_t lo; ! 1479: } dwords; ! 1480: }; ! 1481: #define PHN_CLP_BLKSIZE ( sizeof ( union phantom_clp_data ) ) ! 1482: ! 1483: /** ! 1484: * Wait for Phantom CLP command to complete ! 1485: * ! 1486: * @v phantom Phantom NIC ! 1487: * @ret rc Return status code ! 1488: */ ! 1489: static int phantom_clp_wait ( struct phantom_nic *phantom ) { ! 1490: unsigned int retries; ! 1491: uint32_t status; ! 1492: ! 1493: for ( retries = 0 ; retries < PHN_CLP_CMD_TIMEOUT_MS ; retries++ ) { ! 1494: status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS ); ! 1495: if ( status & UNM_CAM_RAM_CLP_STATUS_DONE ) ! 1496: return 0; ! 1497: mdelay ( 1 ); ! 1498: } ! 1499: ! 1500: DBGC ( phantom, "Phantom %p timed out waiting for CLP command\n", ! 1501: phantom ); ! 1502: return -ETIMEDOUT; ! 1503: } ! 1504: ! 1505: /** ! 1506: * Issue Phantom CLP command ! 1507: * ! 1508: * @v phantom Phantom NIC ! 1509: * @v port Virtual port number ! 1510: * @v opcode Opcode ! 1511: * @v data_in Data in, or NULL ! 1512: * @v data_out Data out, or NULL ! 1513: * @v offset Offset within data ! 1514: * @v len Data buffer length ! 1515: * @ret len Total transfer length (for reads), or negative error ! 1516: */ ! 1517: static int phantom_clp_cmd ( struct phantom_nic *phantom, unsigned int port, ! 1518: unsigned int opcode, const void *data_in, ! 1519: void *data_out, size_t offset, size_t len ) { ! 1520: union phantom_clp_data data; ! 1521: unsigned int index = ( offset / sizeof ( data ) ); ! 1522: unsigned int last = 0; ! 1523: size_t in_frag_len; ! 1524: uint8_t *in_frag; ! 1525: uint32_t command; ! 1526: uint32_t status; ! 1527: size_t read_len; ! 1528: unsigned int error; ! 1529: size_t out_frag_len; ! 1530: uint8_t *out_frag; ! 1531: int rc; ! 1532: ! 1533: /* Sanity checks */ ! 1534: assert ( ( offset % sizeof ( data ) ) == 0 ); ! 1535: if ( len > 255 ) { ! 1536: DBGC ( phantom, "Phantom %p invalid CLP length %zd\n", ! 1537: phantom, len ); ! 1538: return -EINVAL; ! 1539: } ! 1540: ! 1541: /* Check that CLP interface is ready */ ! 1542: if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 ) ! 1543: return rc; ! 1544: ! 1545: /* Copy data in */ ! 1546: memset ( &data, 0, sizeof ( data ) ); ! 1547: if ( data_in ) { ! 1548: assert ( offset < len ); ! 1549: in_frag_len = ( len - offset ); ! 1550: if ( in_frag_len > sizeof ( data ) ) { ! 1551: in_frag_len = sizeof ( data ); ! 1552: } else { ! 1553: last = 1; ! 1554: } ! 1555: in_frag = &data.bytes[ sizeof ( data ) - in_frag_len ]; ! 1556: memcpy ( in_frag, ( data_in + offset ), in_frag_len ); ! 1557: phantom_writel ( phantom, be32_to_cpu ( data.dwords.lo ), ! 1558: UNM_CAM_RAM_CLP_DATA_LO ); ! 1559: phantom_writel ( phantom, be32_to_cpu ( data.dwords.hi ), ! 1560: UNM_CAM_RAM_CLP_DATA_HI ); ! 1561: } ! 1562: ! 1563: /* Issue CLP command */ ! 1564: command = ( ( index << 24 ) | ( ( data_in ? len : 0 ) << 16 ) | ! 1565: ( port << 8 ) | ( last << 7 ) | ( opcode << 0 ) ); ! 1566: phantom_writel ( phantom, command, UNM_CAM_RAM_CLP_COMMAND ); ! 1567: mb(); ! 1568: phantom_writel ( phantom, UNM_CAM_RAM_CLP_STATUS_START, ! 1569: UNM_CAM_RAM_CLP_STATUS ); ! 1570: ! 1571: /* Wait for command to complete */ ! 1572: if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 ) ! 1573: return rc; ! 1574: ! 1575: /* Get command status */ ! 1576: status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS ); ! 1577: read_len = ( ( status >> 16 ) & 0xff ); ! 1578: error = ( ( status >> 8 ) & 0xff ); ! 1579: if ( error ) { ! 1580: DBGC ( phantom, "Phantom %p CLP command error %02x\n", ! 1581: phantom, error ); ! 1582: return -EIO; ! 1583: } ! 1584: ! 1585: /* Copy data out */ ! 1586: if ( data_out ) { ! 1587: data.dwords.lo = cpu_to_be32 ( phantom_readl ( phantom, ! 1588: UNM_CAM_RAM_CLP_DATA_LO ) ); ! 1589: data.dwords.hi = cpu_to_be32 ( phantom_readl ( phantom, ! 1590: UNM_CAM_RAM_CLP_DATA_HI ) ); ! 1591: out_frag_len = ( read_len - offset ); ! 1592: if ( out_frag_len > sizeof ( data ) ) ! 1593: out_frag_len = sizeof ( data ); ! 1594: out_frag = &data.bytes[ sizeof ( data ) - out_frag_len ]; ! 1595: if ( out_frag_len > ( len - offset ) ) ! 1596: out_frag_len = ( len - offset ); ! 1597: memcpy ( ( data_out + offset ), out_frag, out_frag_len ); ! 1598: } ! 1599: ! 1600: return read_len; ! 1601: } ! 1602: ! 1603: /** ! 1604: * Store Phantom CLP setting ! 1605: * ! 1606: * @v phantom Phantom NIC ! 1607: * @v port Virtual port number ! 1608: * @v setting Setting number ! 1609: * @v data Data buffer ! 1610: * @v len Length of data buffer ! 1611: * @ret rc Return status code ! 1612: */ ! 1613: static int phantom_clp_store ( struct phantom_nic *phantom, unsigned int port, ! 1614: unsigned int setting, const void *data, ! 1615: size_t len ) { ! 1616: unsigned int opcode = setting; ! 1617: size_t offset; ! 1618: int rc; ! 1619: ! 1620: for ( offset = 0 ; offset < len ; offset += PHN_CLP_BLKSIZE ) { ! 1621: if ( ( rc = phantom_clp_cmd ( phantom, port, opcode, data, ! 1622: NULL, offset, len ) ) < 0 ) ! 1623: return rc; ! 1624: } ! 1625: return 0; ! 1626: } ! 1627: ! 1628: /** ! 1629: * Fetch Phantom CLP setting ! 1630: * ! 1631: * @v phantom Phantom NIC ! 1632: * @v port Virtual port number ! 1633: * @v setting Setting number ! 1634: * @v data Data buffer ! 1635: * @v len Length of data buffer ! 1636: * @ret len Length of setting, or negative error ! 1637: */ ! 1638: static int phantom_clp_fetch ( struct phantom_nic *phantom, unsigned int port, ! 1639: unsigned int setting, void *data, size_t len ) { ! 1640: unsigned int opcode = ( setting + 1 ); ! 1641: size_t offset = 0; ! 1642: int read_len; ! 1643: ! 1644: while ( 1 ) { ! 1645: read_len = phantom_clp_cmd ( phantom, port, opcode, NULL, ! 1646: data, offset, len ); ! 1647: if ( read_len < 0 ) ! 1648: return read_len; ! 1649: offset += PHN_CLP_BLKSIZE; ! 1650: if ( offset >= ( unsigned ) read_len ) ! 1651: break; ! 1652: if ( offset >= len ) ! 1653: break; ! 1654: } ! 1655: return read_len; ! 1656: } ! 1657: ! 1658: /** A Phantom CLP setting */ ! 1659: struct phantom_clp_setting { ! 1660: /** iPXE setting */ ! 1661: struct setting *setting; ! 1662: /** Setting number */ ! 1663: unsigned int clp_setting; ! 1664: }; ! 1665: ! 1666: /** Phantom CLP settings */ ! 1667: static struct phantom_clp_setting clp_settings[] = { ! 1668: { &mac_setting, 0x01 }, ! 1669: }; ! 1670: ! 1671: /** ! 1672: * Find Phantom CLP setting ! 1673: * ! 1674: * @v setting iPXE setting ! 1675: * @v clp_setting Setting number, or 0 if not found ! 1676: */ ! 1677: static unsigned int ! 1678: phantom_clp_setting ( struct phantom_nic *phantom, struct setting *setting ) { ! 1679: struct phantom_clp_setting *clp_setting; ! 1680: unsigned int i; ! 1681: ! 1682: /* Search the list of explicitly-defined settings */ ! 1683: for ( i = 0 ; i < ( sizeof ( clp_settings ) / ! 1684: sizeof ( clp_settings[0] ) ) ; i++ ) { ! 1685: clp_setting = &clp_settings[i]; ! 1686: if ( setting_cmp ( setting, clp_setting->setting ) == 0 ) ! 1687: return clp_setting->clp_setting; ! 1688: } ! 1689: ! 1690: /* Allow for use of numbered settings */ ! 1691: if ( ( setting->tag & PHN_CLP_TAG_MAGIC_MASK ) == PHN_CLP_TAG_MAGIC ) ! 1692: return ( setting->tag & ~PHN_CLP_TAG_MAGIC_MASK ); ! 1693: ! 1694: DBGC2 ( phantom, "Phantom %p has no \"%s\" setting\n", ! 1695: phantom, setting->name ); ! 1696: ! 1697: return 0; ! 1698: } ! 1699: ! 1700: /** ! 1701: * Check applicability of Phantom CLP setting ! 1702: * ! 1703: * @v settings Settings block ! 1704: * @v setting Setting ! 1705: * @ret applies Setting applies within this settings block ! 1706: */ ! 1707: static int phantom_setting_applies ( struct settings *settings, ! 1708: struct setting *setting ) { ! 1709: struct phantom_nic *phantom = ! 1710: container_of ( settings, struct phantom_nic, settings ); ! 1711: unsigned int clp_setting; ! 1712: ! 1713: /* Find Phantom setting equivalent to iPXE setting */ ! 1714: clp_setting = phantom_clp_setting ( phantom, setting ); ! 1715: return ( clp_setting != 0 ); ! 1716: } ! 1717: ! 1718: /** ! 1719: * Store Phantom CLP setting ! 1720: * ! 1721: * @v settings Settings block ! 1722: * @v setting Setting to store ! 1723: * @v data Setting data, or NULL to clear setting ! 1724: * @v len Length of setting data ! 1725: * @ret rc Return status code ! 1726: */ ! 1727: static int phantom_store_setting ( struct settings *settings, ! 1728: struct setting *setting, ! 1729: const void *data, size_t len ) { ! 1730: struct phantom_nic *phantom = ! 1731: container_of ( settings, struct phantom_nic, settings ); ! 1732: unsigned int clp_setting; ! 1733: int rc; ! 1734: ! 1735: /* Find Phantom setting equivalent to iPXE setting */ ! 1736: clp_setting = phantom_clp_setting ( phantom, setting ); ! 1737: assert ( clp_setting != 0 ); ! 1738: ! 1739: /* Store setting */ ! 1740: if ( ( rc = phantom_clp_store ( phantom, phantom->port, ! 1741: clp_setting, data, len ) ) != 0 ) { ! 1742: DBGC ( phantom, "Phantom %p could not store setting \"%s\": " ! 1743: "%s\n", phantom, setting->name, strerror ( rc ) ); ! 1744: return rc; ! 1745: } ! 1746: ! 1747: return 0; ! 1748: } ! 1749: ! 1750: /** ! 1751: * Fetch Phantom CLP setting ! 1752: * ! 1753: * @v settings Settings block ! 1754: * @v setting Setting to fetch ! 1755: * @v data Buffer to fill with setting data ! 1756: * @v len Length of buffer ! 1757: * @ret len Length of setting data, or negative error ! 1758: */ ! 1759: static int phantom_fetch_setting ( struct settings *settings, ! 1760: struct setting *setting, ! 1761: void *data, size_t len ) { ! 1762: struct phantom_nic *phantom = ! 1763: container_of ( settings, struct phantom_nic, settings ); ! 1764: unsigned int clp_setting; ! 1765: int read_len; ! 1766: int rc; ! 1767: ! 1768: /* Find Phantom setting equivalent to iPXE setting */ ! 1769: clp_setting = phantom_clp_setting ( phantom, setting ); ! 1770: assert ( clp_setting != 0 ); ! 1771: ! 1772: /* Fetch setting */ ! 1773: if ( ( read_len = phantom_clp_fetch ( phantom, phantom->port, ! 1774: clp_setting, data, len ) ) < 0 ){ ! 1775: rc = read_len; ! 1776: DBGC ( phantom, "Phantom %p could not fetch setting \"%s\": " ! 1777: "%s\n", phantom, setting->name, strerror ( rc ) ); ! 1778: return rc; ! 1779: } ! 1780: ! 1781: return read_len; ! 1782: } ! 1783: ! 1784: /** Phantom CLP settings operations */ ! 1785: static struct settings_operations phantom_settings_operations = { ! 1786: .applies = phantom_setting_applies, ! 1787: .store = phantom_store_setting, ! 1788: .fetch = phantom_fetch_setting, ! 1789: }; ! 1790: ! 1791: /*************************************************************************** ! 1792: * ! 1793: * Initialisation ! 1794: * ! 1795: */ ! 1796: ! 1797: /** ! 1798: * Map Phantom CRB window ! 1799: * ! 1800: * @v phantom Phantom NIC ! 1801: * @ret rc Return status code ! 1802: */ ! 1803: static int phantom_map_crb ( struct phantom_nic *phantom, ! 1804: struct pci_device *pci ) { ! 1805: unsigned long bar0_start; ! 1806: unsigned long bar0_size; ! 1807: ! 1808: bar0_start = pci_bar_start ( pci, PCI_BASE_ADDRESS_0 ); ! 1809: bar0_size = pci_bar_size ( pci, PCI_BASE_ADDRESS_0 ); ! 1810: DBGC ( phantom, "Phantom %p is " PCI_FMT " with BAR0 at %08lx+%lx\n", ! 1811: phantom, PCI_ARGS ( pci ), bar0_start, bar0_size ); ! 1812: ! 1813: if ( ! bar0_start ) { ! 1814: DBGC ( phantom, "Phantom %p BAR not assigned; ignoring\n", ! 1815: phantom ); ! 1816: return -EINVAL; ! 1817: } ! 1818: ! 1819: switch ( bar0_size ) { ! 1820: case ( 128 * 1024 * 1024 ) : ! 1821: DBGC ( phantom, "Phantom %p has 128MB BAR\n", phantom ); ! 1822: phantom->crb_access = phantom_crb_access_128m; ! 1823: break; ! 1824: case ( 32 * 1024 * 1024 ) : ! 1825: DBGC ( phantom, "Phantom %p has 32MB BAR\n", phantom ); ! 1826: phantom->crb_access = phantom_crb_access_32m; ! 1827: break; ! 1828: case ( 2 * 1024 * 1024 ) : ! 1829: DBGC ( phantom, "Phantom %p has 2MB BAR\n", phantom ); ! 1830: phantom->crb_access = phantom_crb_access_2m; ! 1831: break; ! 1832: default: ! 1833: DBGC ( phantom, "Phantom %p has bad BAR size\n", phantom ); ! 1834: return -EINVAL; ! 1835: } ! 1836: ! 1837: phantom->bar0 = ioremap ( bar0_start, bar0_size ); ! 1838: if ( ! phantom->bar0 ) { ! 1839: DBGC ( phantom, "Phantom %p could not map BAR0\n", phantom ); ! 1840: return -EIO; ! 1841: } ! 1842: ! 1843: /* Mark current CRB window as invalid, so that the first ! 1844: * read/write will set the current window. ! 1845: */ ! 1846: phantom->crb_window = -1UL; ! 1847: ! 1848: return 0; ! 1849: } ! 1850: ! 1851: /** ! 1852: * Unhalt all PEGs ! 1853: * ! 1854: * @v phantom Phantom NIC ! 1855: */ ! 1856: static void phantom_unhalt_pegs ( struct phantom_nic *phantom ) { ! 1857: uint32_t halt_status; ! 1858: ! 1859: halt_status = phantom_readl ( phantom, UNM_PEG_0_HALT_STATUS ); ! 1860: phantom_writel ( phantom, halt_status, UNM_PEG_0_HALT_STATUS ); ! 1861: halt_status = phantom_readl ( phantom, UNM_PEG_1_HALT_STATUS ); ! 1862: phantom_writel ( phantom, halt_status, UNM_PEG_1_HALT_STATUS ); ! 1863: halt_status = phantom_readl ( phantom, UNM_PEG_2_HALT_STATUS ); ! 1864: phantom_writel ( phantom, halt_status, UNM_PEG_2_HALT_STATUS ); ! 1865: halt_status = phantom_readl ( phantom, UNM_PEG_3_HALT_STATUS ); ! 1866: phantom_writel ( phantom, halt_status, UNM_PEG_3_HALT_STATUS ); ! 1867: halt_status = phantom_readl ( phantom, UNM_PEG_4_HALT_STATUS ); ! 1868: phantom_writel ( phantom, halt_status, UNM_PEG_4_HALT_STATUS ); ! 1869: } ! 1870: ! 1871: /** ! 1872: * Initialise the Phantom command PEG ! 1873: * ! 1874: * @v phantom Phantom NIC ! 1875: * @ret rc Return status code ! 1876: */ ! 1877: static int phantom_init_cmdpeg ( struct phantom_nic *phantom ) { ! 1878: uint32_t cold_boot; ! 1879: uint32_t sw_reset; ! 1880: unsigned int retries; ! 1881: uint32_t cmdpeg_state; ! 1882: uint32_t last_cmdpeg_state = 0; ! 1883: ! 1884: /* Check for a previous initialisation. This could have ! 1885: * happened if, for example, the BIOS used the UNDI API to ! 1886: * drive the NIC prior to a full PXE boot. ! 1887: */ ! 1888: cmdpeg_state = phantom_readl ( phantom, UNM_NIC_REG_CMDPEG_STATE ); ! 1889: if ( cmdpeg_state == UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK ) { ! 1890: DBGC ( phantom, "Phantom %p command PEG already initialized\n", ! 1891: phantom ); ! 1892: /* Unhalt the PEGs. Previous firmware (e.g. BOFM) may ! 1893: * have halted the PEGs to prevent internal bus ! 1894: * collisions when the BIOS re-reads the expansion ROM. ! 1895: */ ! 1896: phantom_unhalt_pegs ( phantom ); ! 1897: return 0; ! 1898: } ! 1899: ! 1900: /* If this was a cold boot, check that the hardware came up ok */ ! 1901: cold_boot = phantom_readl ( phantom, UNM_CAM_RAM_COLD_BOOT ); ! 1902: if ( cold_boot == UNM_CAM_RAM_COLD_BOOT_MAGIC ) { ! 1903: DBGC ( phantom, "Phantom %p coming up from cold boot\n", ! 1904: phantom ); ! 1905: sw_reset = phantom_readl ( phantom, UNM_ROMUSB_GLB_SW_RESET ); ! 1906: if ( sw_reset != UNM_ROMUSB_GLB_SW_RESET_MAGIC ) { ! 1907: DBGC ( phantom, "Phantom %p reset failed: %08x\n", ! 1908: phantom, sw_reset ); ! 1909: return -EIO; ! 1910: } ! 1911: } else { ! 1912: DBGC ( phantom, "Phantom %p coming up from warm boot " ! 1913: "(%08x)\n", phantom, cold_boot ); ! 1914: } ! 1915: /* Clear cold-boot flag */ ! 1916: phantom_writel ( phantom, 0, UNM_CAM_RAM_COLD_BOOT ); ! 1917: ! 1918: /* Set port modes */ ! 1919: phantom_writel ( phantom, UNM_CAM_RAM_PORT_MODE_AUTO_NEG_1G, ! 1920: UNM_CAM_RAM_WOL_PORT_MODE ); ! 1921: ! 1922: /* Pass dummy DMA area to card */ ! 1923: phantom_write_hilo ( phantom, 0, ! 1924: UNM_NIC_REG_DUMMY_BUF_ADDR_LO, ! 1925: UNM_NIC_REG_DUMMY_BUF_ADDR_HI ); ! 1926: phantom_writel ( phantom, UNM_NIC_REG_DUMMY_BUF_INIT, ! 1927: UNM_NIC_REG_DUMMY_BUF ); ! 1928: ! 1929: /* Tell the hardware that tuning is complete */ ! 1930: phantom_writel ( phantom, UNM_ROMUSB_GLB_PEGTUNE_DONE_MAGIC, ! 1931: UNM_ROMUSB_GLB_PEGTUNE_DONE ); ! 1932: ! 1933: /* Wait for command PEG to finish initialising */ ! 1934: DBGC ( phantom, "Phantom %p initialising command PEG (will take up to " ! 1935: "%d seconds)...\n", phantom, PHN_CMDPEG_INIT_TIMEOUT_SEC ); ! 1936: for ( retries = 0; retries < PHN_CMDPEG_INIT_TIMEOUT_SEC; retries++ ) { ! 1937: cmdpeg_state = phantom_readl ( phantom, ! 1938: UNM_NIC_REG_CMDPEG_STATE ); ! 1939: if ( cmdpeg_state != last_cmdpeg_state ) { ! 1940: DBGC ( phantom, "Phantom %p command PEG state is " ! 1941: "%08x after %d seconds...\n", ! 1942: phantom, cmdpeg_state, retries ); ! 1943: last_cmdpeg_state = cmdpeg_state; ! 1944: } ! 1945: if ( cmdpeg_state == UNM_NIC_REG_CMDPEG_STATE_INITIALIZED ) { ! 1946: /* Acknowledge the PEG initialisation */ ! 1947: phantom_writel ( phantom, ! 1948: UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK, ! 1949: UNM_NIC_REG_CMDPEG_STATE ); ! 1950: return 0; ! 1951: } ! 1952: mdelay ( 1000 ); ! 1953: } ! 1954: ! 1955: DBGC ( phantom, "Phantom %p timed out waiting for command PEG to " ! 1956: "initialise (status %08x)\n", phantom, cmdpeg_state ); ! 1957: return -ETIMEDOUT; ! 1958: } ! 1959: ! 1960: /** ! 1961: * Read Phantom MAC address ! 1962: * ! 1963: * @v phanton_port Phantom NIC ! 1964: * @v hw_addr Buffer to fill with MAC address ! 1965: */ ! 1966: static void phantom_get_macaddr ( struct phantom_nic *phantom, ! 1967: uint8_t *hw_addr ) { ! 1968: union { ! 1969: uint8_t mac_addr[2][ETH_ALEN]; ! 1970: uint32_t dwords[3]; ! 1971: } u; ! 1972: unsigned long offset; ! 1973: int i; ! 1974: ! 1975: /* Read the three dwords that include this MAC address and one other */ ! 1976: offset = ( UNM_CAM_RAM_MAC_ADDRS + ! 1977: ( 12 * ( phantom->port / 2 ) ) ); ! 1978: for ( i = 0 ; i < 3 ; i++, offset += 4 ) { ! 1979: u.dwords[i] = phantom_readl ( phantom, offset ); ! 1980: } ! 1981: ! 1982: /* Copy out the relevant MAC address */ ! 1983: for ( i = 0 ; i < ETH_ALEN ; i++ ) { ! 1984: hw_addr[ ETH_ALEN - i - 1 ] = ! 1985: u.mac_addr[ phantom->port & 1 ][i]; ! 1986: } ! 1987: DBGC ( phantom, "Phantom %p MAC address is %s\n", ! 1988: phantom, eth_ntoa ( hw_addr ) ); ! 1989: } ! 1990: ! 1991: /** ! 1992: * Check Phantom is enabled for boot ! 1993: * ! 1994: * @v phanton_port Phantom NIC ! 1995: * @ret rc Return status code ! 1996: * ! 1997: * This is something of an ugly hack to accommodate an OEM ! 1998: * requirement. The NIC has only one expansion ROM BAR, rather than ! 1999: * one per port. To allow individual ports to be selectively ! 2000: * enabled/disabled for PXE boot (as required), we must therefore ! 2001: * leave the expansion ROM always enabled, and place the per-port ! 2002: * enable/disable logic within the iPXE driver. ! 2003: */ ! 2004: static int phantom_check_boot_enable ( struct phantom_nic *phantom ) { ! 2005: unsigned long boot_enable; ! 2006: ! 2007: boot_enable = phantom_readl ( phantom, UNM_CAM_RAM_BOOT_ENABLE ); ! 2008: if ( ! ( boot_enable & ( 1 << phantom->port ) ) ) { ! 2009: DBGC ( phantom, "Phantom %p PXE boot is disabled\n", ! 2010: phantom ); ! 2011: return -ENOTSUP; ! 2012: } ! 2013: ! 2014: return 0; ! 2015: } ! 2016: ! 2017: /** ! 2018: * Initialise Phantom receive PEG ! 2019: * ! 2020: * @v phantom Phantom NIC ! 2021: * @ret rc Return status code ! 2022: */ ! 2023: static int phantom_init_rcvpeg ( struct phantom_nic *phantom ) { ! 2024: unsigned int retries; ! 2025: uint32_t rcvpeg_state; ! 2026: uint32_t last_rcvpeg_state = 0; ! 2027: ! 2028: DBGC ( phantom, "Phantom %p initialising receive PEG (will take up to " ! 2029: "%d seconds)...\n", phantom, PHN_RCVPEG_INIT_TIMEOUT_SEC ); ! 2030: for ( retries = 0; retries < PHN_RCVPEG_INIT_TIMEOUT_SEC; retries++ ) { ! 2031: rcvpeg_state = phantom_readl ( phantom, ! 2032: UNM_NIC_REG_RCVPEG_STATE ); ! 2033: if ( rcvpeg_state != last_rcvpeg_state ) { ! 2034: DBGC ( phantom, "Phantom %p receive PEG state is " ! 2035: "%08x after %d seconds...\n", ! 2036: phantom, rcvpeg_state, retries ); ! 2037: last_rcvpeg_state = rcvpeg_state; ! 2038: } ! 2039: if ( rcvpeg_state == UNM_NIC_REG_RCVPEG_STATE_INITIALIZED ) ! 2040: return 0; ! 2041: mdelay ( 1000 ); ! 2042: } ! 2043: ! 2044: DBGC ( phantom, "Phantom %p timed out waiting for receive PEG to " ! 2045: "initialise (status %08x)\n", phantom, rcvpeg_state ); ! 2046: return -ETIMEDOUT; ! 2047: } ! 2048: ! 2049: /** ! 2050: * Probe PCI device ! 2051: * ! 2052: * @v pci PCI device ! 2053: * @v id PCI ID ! 2054: * @ret rc Return status code ! 2055: */ ! 2056: static int phantom_probe ( struct pci_device *pci ) { ! 2057: struct net_device *netdev; ! 2058: struct phantom_nic *phantom; ! 2059: struct settings *parent_settings; ! 2060: int rc; ! 2061: ! 2062: /* Allocate Phantom device */ ! 2063: netdev = alloc_etherdev ( sizeof ( *phantom ) ); ! 2064: if ( ! netdev ) { ! 2065: rc = -ENOMEM; ! 2066: goto err_alloc_etherdev; ! 2067: } ! 2068: netdev_init ( netdev, &phantom_operations ); ! 2069: phantom = netdev_priv ( netdev ); ! 2070: pci_set_drvdata ( pci, netdev ); ! 2071: netdev->dev = &pci->dev; ! 2072: memset ( phantom, 0, sizeof ( *phantom ) ); ! 2073: phantom->port = PCI_FUNC ( pci->busdevfn ); ! 2074: assert ( phantom->port < PHN_MAX_NUM_PORTS ); ! 2075: settings_init ( &phantom->settings, ! 2076: &phantom_settings_operations, ! 2077: &netdev->refcnt, PHN_CLP_TAG_MAGIC ); ! 2078: ! 2079: /* Fix up PCI device */ ! 2080: adjust_pci_device ( pci ); ! 2081: ! 2082: /* Map CRB */ ! 2083: if ( ( rc = phantom_map_crb ( phantom, pci ) ) != 0 ) ! 2084: goto err_map_crb; ! 2085: ! 2086: /* BUG5945 - need to hack PCI config space on P3 B1 silicon. ! 2087: * B2 will have this fixed; remove this hack when B1 is no ! 2088: * longer in use. ! 2089: */ ! 2090: if ( PCI_FUNC ( pci->busdevfn ) == 0 ) { ! 2091: unsigned int i; ! 2092: for ( i = 0 ; i < 8 ; i++ ) { ! 2093: uint32_t temp; ! 2094: pci->busdevfn = ! 2095: PCI_BUSDEVFN ( PCI_BUS ( pci->busdevfn ), ! 2096: PCI_SLOT ( pci->busdevfn ), i ); ! 2097: pci_read_config_dword ( pci, 0xc8, &temp ); ! 2098: pci_read_config_dword ( pci, 0xc8, &temp ); ! 2099: pci_write_config_dword ( pci, 0xc8, 0xf1000 ); ! 2100: } ! 2101: pci->busdevfn = PCI_BUSDEVFN ( PCI_BUS ( pci->busdevfn ), ! 2102: PCI_SLOT ( pci->busdevfn ), 0 ); ! 2103: } ! 2104: ! 2105: /* Initialise the command PEG */ ! 2106: if ( ( rc = phantom_init_cmdpeg ( phantom ) ) != 0 ) ! 2107: goto err_init_cmdpeg; ! 2108: ! 2109: /* Initialise the receive PEG */ ! 2110: if ( ( rc = phantom_init_rcvpeg ( phantom ) ) != 0 ) ! 2111: goto err_init_rcvpeg; ! 2112: ! 2113: /* Read MAC addresses */ ! 2114: phantom_get_macaddr ( phantom, netdev->hw_addr ); ! 2115: ! 2116: /* Skip if boot disabled on NIC */ ! 2117: if ( ( rc = phantom_check_boot_enable ( phantom ) ) != 0 ) ! 2118: goto err_check_boot_enable; ! 2119: ! 2120: /* Register network devices */ ! 2121: if ( ( rc = register_netdev ( netdev ) ) != 0 ) { ! 2122: DBGC ( phantom, "Phantom %p could not register net device: " ! 2123: "%s\n", phantom, strerror ( rc ) ); ! 2124: goto err_register_netdev; ! 2125: } ! 2126: ! 2127: /* Register settings blocks */ ! 2128: parent_settings = netdev_settings ( netdev ); ! 2129: if ( ( rc = register_settings ( &phantom->settings, ! 2130: parent_settings, "clp" ) ) != 0 ) { ! 2131: DBGC ( phantom, "Phantom %p could not register settings: " ! 2132: "%s\n", phantom, strerror ( rc ) ); ! 2133: goto err_register_settings; ! 2134: } ! 2135: ! 2136: return 0; ! 2137: ! 2138: unregister_settings ( &phantom->settings ); ! 2139: err_register_settings: ! 2140: unregister_netdev ( netdev ); ! 2141: err_register_netdev: ! 2142: err_check_boot_enable: ! 2143: err_init_rcvpeg: ! 2144: err_init_cmdpeg: ! 2145: err_map_crb: ! 2146: netdev_nullify ( netdev ); ! 2147: netdev_put ( netdev ); ! 2148: err_alloc_etherdev: ! 2149: return rc; ! 2150: } ! 2151: ! 2152: /** ! 2153: * Remove PCI device ! 2154: * ! 2155: * @v pci PCI device ! 2156: */ ! 2157: static void phantom_remove ( struct pci_device *pci ) { ! 2158: struct net_device *netdev = pci_get_drvdata ( pci ); ! 2159: struct phantom_nic *phantom = netdev_priv ( netdev ); ! 2160: ! 2161: unregister_settings ( &phantom->settings ); ! 2162: unregister_netdev ( netdev ); ! 2163: netdev_nullify ( netdev ); ! 2164: netdev_put ( netdev ); ! 2165: } ! 2166: ! 2167: /** Phantom PCI IDs */ ! 2168: static struct pci_device_id phantom_nics[] = { ! 2169: PCI_ROM ( 0x4040, 0x0100, "nx", "NX", 0 ), ! 2170: }; ! 2171: ! 2172: /** Phantom PCI driver */ ! 2173: struct pci_driver phantom_driver __pci_driver = { ! 2174: .ids = phantom_nics, ! 2175: .id_count = ( sizeof ( phantom_nics ) / sizeof ( phantom_nics[0] ) ), ! 2176: .probe = phantom_probe, ! 2177: .remove = phantom_remove, ! 2178: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.