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

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: };

unix.superglobalmegacorp.com

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