phantom.c File Reference

NetXen Phantom NICs. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <assert.h>
#include <byteswap.h>
#include <gpxe/pci.h>
#include <gpxe/io.h>
#include <gpxe/malloc.h>
#include <gpxe/iobuf.h>
#include <gpxe/netdevice.h>
#include <gpxe/if_ether.h>
#include <gpxe/ethernet.h>
#include <gpxe/spi.h>
#include <gpxe/settings.h>
#include "phantom.h"

Go to the source code of this file.

Data Structures

struct  phantom_descriptor_rings
 A Phantom descriptor ring set. More...
struct  phantom_create_rx_ctx_rqrsp
 RX context creation request and response buffers. More...
struct  phantom_create_tx_ctx_rqrsp
 TX context creation request and response buffers. More...
struct  phantom_nic
 A Phantom NIC. More...
union  phantom_clp_data
 Phantom CLP data. More...
struct  phantom_clp_setting
 A Phantom CLP setting. More...

Defines

#define PHN_MAX_NUM_PORTS   8
 Maximum number of ports.
#define PHN_CMDPEG_INIT_TIMEOUT_SEC   50
 Maximum time to wait for command PEG to initialise.
#define PHN_RCVPEG_INIT_TIMEOUT_SEC   2
 Maximum time to wait for receive PEG to initialise.
#define PHN_ISSUE_CMD_TIMEOUT_MS   2000
 Maximum time to wait for firmware to accept a command.
#define PHN_TEST_MEM_TIMEOUT_MS   100
 Maximum time to wait for test memory.
#define PHN_CLP_CMD_TIMEOUT_MS   500
 Maximum time to wait for CLP command to be issued.
#define PHN_LINK_POLL_FREQUENCY   4096
 Link state poll frequency.
#define PHN_NUM_RDS   32
 Number of RX descriptors.
#define PHN_RDS_MAX_FILL   16
 RX maximum fill level.
#define PHN_RX_BUFSIZE
 RX buffer size.
#define PHN_NUM_SDS   32
 Number of RX status descriptors.
#define PHN_NUM_CDS   8
 Number of TX descriptors.
#define PHN_CLP_TAG_MAGIC   0xc19c1900UL
 Phantom CLP settings tag magic.
#define PHN_CLP_TAG_MAGIC_MASK   0xffffff00UL
 Phantom CLP settings tag magic mask.
#define PHN_CLP_BLKSIZE   ( sizeof ( union phantom_clp_data ) )

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static unsigned long phantom_crb_access_128m (struct phantom_nic *phantom, unsigned long reg)
 Prepare for access to CRB register via 128MB BAR.
static unsigned long phantom_crb_access_32m (struct phantom_nic *phantom, unsigned long reg)
 Prepare for access to CRB register via 32MB BAR.
static unsigned long phantom_crb_access_2m (struct phantom_nic *phantom, unsigned long reg)
 Prepare for access to CRB register via 2MB BAR.
static uint32_t phantom_readl (struct phantom_nic *phantom, unsigned long reg)
 Read from Phantom CRB register.
static void phantom_writel (struct phantom_nic *phantom, uint32_t value, unsigned long reg)
 Write to Phantom CRB register.
static void phantom_write_hilo (struct phantom_nic *phantom, uint64_t value, unsigned long lo_offset, unsigned long hi_offset)
 Write to Phantom CRB HI/LO register pair.
static int phantom_read_test_mem_block (struct phantom_nic *phantom, unsigned long offset, uint32_t buf[2])
 Read from Phantom test memory.
static int phantom_read_test_mem (struct phantom_nic *phantom, unsigned long offset)
 Read single byte from Phantom test memory.
static int phantom_dmesg (struct phantom_nic *phantom, unsigned int log, unsigned int max_lines)
 Dump Phantom firmware dmesg log.
static void phantom_dmesg_all (struct phantom_nic *phantom, unsigned int max_lines)
 Dump Phantom firmware dmesg logs.
static int phantom_wait_for_cmd (struct phantom_nic *phantom)
 Wait for firmware to accept command.
static int phantom_issue_cmd (struct phantom_nic *phantom, uint32_t command, uint32_t arg1, uint32_t arg2, uint32_t arg3)
 Issue command to firmware.
static int phantom_issue_buf_cmd (struct phantom_nic *phantom, uint32_t command, void *buffer, size_t len)
 Issue buffer-format command to firmware.
static int phantom_create_rx_ctx (struct phantom_nic *phantom)
 Create Phantom RX context.
static void phantom_destroy_rx_ctx (struct phantom_nic *phantom)
 Destroy Phantom RX context.
static int phantom_create_tx_ctx (struct phantom_nic *phantom)
 Create Phantom TX context.
static void phantom_destroy_tx_ctx (struct phantom_nic *phantom)
 Destroy Phantom TX context.
static int phantom_alloc_rds (struct phantom_nic *phantom)
 Allocate Phantom RX descriptor.
static void phantom_post_rds (struct phantom_nic *phantom, struct phantom_rds *rds)
 Post Phantom RX descriptor.
static int phantom_alloc_cds (struct phantom_nic *phantom)
 Allocate Phantom TX descriptor.
static void phantom_post_cds (struct phantom_nic *phantom, union phantom_cds *cds)
 Post Phantom TX descriptor.
static int phantom_update_macaddr (struct phantom_nic *phantom, const uint8_t *ll_addr, unsigned int opcode)
 Add/remove MAC address.
static int phantom_add_macaddr (struct phantom_nic *phantom, const uint8_t *ll_addr)
 Add MAC address.
static int phantom_del_macaddr (struct phantom_nic *phantom, const uint8_t *ll_addr)
 Remove MAC address.
static void phantom_poll_link_state (struct net_device *netdev)
 Poll link state.
static void phantom_refill_rx_ring (struct net_device *netdev)
 Refill descriptor ring.
static int phantom_open (struct net_device *netdev)
 Open NIC.
static void phantom_close (struct net_device *netdev)
 Close NIC.
static int phantom_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void phantom_poll (struct net_device *netdev)
 Poll for received packets.
static void phantom_irq (struct net_device *netdev, int enable)
 Enable/disable interrupts.
static int phantom_clp_wait (struct phantom_nic *phantom)
 Wait for Phantom CLP command to complete.
static int phantom_clp_cmd (struct phantom_nic *phantom, unsigned int port, unsigned int opcode, const void *data_in, void *data_out, size_t offset, size_t len)
 Issue Phantom CLP command.
static int phantom_clp_store (struct phantom_nic *phantom, unsigned int port, unsigned int setting, const void *data, size_t len)
 Store Phantom CLP setting.
static int phantom_clp_fetch (struct phantom_nic *phantom, unsigned int port, unsigned int setting, void *data, size_t len)
 Fetch Phantom CLP setting.
static unsigned int phantom_clp_setting (struct phantom_nic *phantom, struct setting *setting)
 Find Phantom CLP setting.
static int phantom_store_setting (struct settings *settings, struct setting *setting, const void *data, size_t len)
 Store Phantom CLP setting.
static int phantom_fetch_setting (struct settings *settings, struct setting *setting, void *data, size_t len)
 Fetch Phantom CLP setting.
static int phantom_map_crb (struct phantom_nic *phantom, struct pci_device *pci)
 Map Phantom CRB window.
static void phantom_unhalt_pegs (struct phantom_nic *phantom)
 Unhalt all PEGs.
static int phantom_init_cmdpeg (struct phantom_nic *phantom)
 Initialise the Phantom command PEG.
static void phantom_get_macaddr (struct phantom_nic *phantom, uint8_t *hw_addr)
 Read Phantom MAC address.
static int phantom_check_boot_enable (struct phantom_nic *phantom)
 Check Phantom is enabled for boot.
static int phantom_init_rcvpeg (struct phantom_nic *phantom)
 Initialise Phantom receive PEG.
static int phantom_probe (struct pci_device *pci, const struct pci_device_id *id __unused)
 Probe PCI device.
static void phantom_remove (struct pci_device *pci)
 Remove PCI device.

Variables

static const unsigned long phantom_irq_mask_reg [PHN_MAX_NUM_PORTS]
 Interrupt mask registers.
static const unsigned long phantom_irq_status_reg [PHN_MAX_NUM_PORTS]
 Interrupt status registers.
static struct net_device_operations phantom_operations
 Phantom net device operations.
static struct phantom_clp_setting clp_settings []
 Phantom CLP settings.
static struct settings_operations phantom_settings_operations
 Phantom CLP settings operations.
static struct pci_device_id phantom_nics []
 Phantom PCI IDs.
struct pci_driver phantom_driver __pci_driver
 Phantom PCI driver.


Detailed Description

NetXen Phantom NICs.

Definition in file phantom.c.


Define Documentation

#define PHN_MAX_NUM_PORTS   8

Maximum number of ports.

Definition at line 48 of file phantom.c.

Referenced by phantom_probe().

#define PHN_CMDPEG_INIT_TIMEOUT_SEC   50

Maximum time to wait for command PEG to initialise.

BUGxxxx

The command PEG will currently report initialisation complete only when at least one PHY has detected a link (so that the global PHY clock can be set to 10G/1G as appropriate). This can take a very, very long time.

A future firmware revision should decouple PHY initialisation from firmware initialisation, at which point the command PEG will report initialisation complete much earlier, and this timeout can be reduced.

Definition at line 64 of file phantom.c.

Referenced by phantom_init_cmdpeg().

#define PHN_RCVPEG_INIT_TIMEOUT_SEC   2

Maximum time to wait for receive PEG to initialise.

Definition at line 67 of file phantom.c.

Referenced by phantom_init_rcvpeg().

#define PHN_ISSUE_CMD_TIMEOUT_MS   2000

Maximum time to wait for firmware to accept a command.

Definition at line 70 of file phantom.c.

Referenced by phantom_wait_for_cmd().

#define PHN_TEST_MEM_TIMEOUT_MS   100

Maximum time to wait for test memory.

Definition at line 73 of file phantom.c.

Referenced by phantom_read_test_mem_block().

#define PHN_CLP_CMD_TIMEOUT_MS   500

Maximum time to wait for CLP command to be issued.

Definition at line 76 of file phantom.c.

Referenced by phantom_clp_wait().

#define PHN_LINK_POLL_FREQUENCY   4096

Link state poll frequency.

The link state will be checked once in every N calls to poll().

Definition at line 82 of file phantom.c.

Referenced by phantom_poll().

#define PHN_NUM_RDS   32

Number of RX descriptors.

Definition at line 85 of file phantom.c.

Referenced by phantom_alloc_rds(), phantom_create_rx_ctx(), phantom_poll(), phantom_post_rds(), and phantom_refill_rx_ring().

#define PHN_RDS_MAX_FILL   16

RX maximum fill level.

Must be strictly less than PHN_NUM_RDS.

Definition at line 88 of file phantom.c.

Referenced by phantom_close(), and phantom_refill_rx_ring().

#define PHN_RX_BUFSIZE

Value:

( 32 /* max LL padding added by card */ + \
                         ETH_FRAME_LEN )
RX buffer size.

Definition at line 91 of file phantom.c.

Referenced by phantom_create_rx_ctx(), and phantom_refill_rx_ring().

#define PHN_NUM_SDS   32

Number of RX status descriptors.

Definition at line 95 of file phantom.c.

Referenced by phantom_create_rx_ctx(), and phantom_poll().

#define PHN_NUM_CDS   8

Number of TX descriptors.

Definition at line 98 of file phantom.c.

Referenced by phantom_alloc_cds(), phantom_close(), phantom_create_tx_ctx(), phantom_poll(), and phantom_post_cds().

#define PHN_CLP_TAG_MAGIC   0xc19c1900UL

Phantom CLP settings tag magic.

Definition at line 1459 of file phantom.c.

Referenced by phantom_clp_setting(), and phantom_probe().

#define PHN_CLP_TAG_MAGIC_MASK   0xffffff00UL

Phantom CLP settings tag magic mask.

Definition at line 1462 of file phantom.c.

Referenced by phantom_clp_setting().

#define PHN_CLP_BLKSIZE   ( sizeof ( union phantom_clp_data ) )

Definition at line 1483 of file phantom.c.

Referenced by phantom_clp_fetch(), and phantom_clp_store().


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static unsigned long phantom_crb_access_128m ( struct phantom_nic phantom,
unsigned long  reg 
) [static]

Prepare for access to CRB register via 128MB BAR.

Parameters:
phantom Phantom NIC
reg Register offset within abstract address space
Return values:
offset Register offset within PCI BAR0

Definition at line 236 of file phantom.c.

References assert, phantom_nic::bar0, phantom_nic::crb_window, offset, readl, UNM_128M_CRB_WINDOW, and writel.

Referenced by phantom_map_crb().

00237                                                                    {
00238         unsigned long offset = ( 0x6000000 + ( reg & 0x1ffffff ) );
00239         uint32_t window = ( reg & 0x2000000 );
00240         uint32_t verify_window;
00241 
00242         if ( phantom->crb_window != window ) {
00243 
00244                 /* Write to the CRB window register */
00245                 writel ( window, phantom->bar0 + UNM_128M_CRB_WINDOW );
00246 
00247                 /* Ensure that the write has reached the card */
00248                 verify_window = readl ( phantom->bar0 + UNM_128M_CRB_WINDOW );
00249                 assert ( verify_window == window );
00250 
00251                 /* Record new window */
00252                 phantom->crb_window = window;
00253         }
00254 
00255         return offset;
00256 }

static unsigned long phantom_crb_access_32m ( struct phantom_nic phantom,
unsigned long  reg 
) [static]

Prepare for access to CRB register via 32MB BAR.

Parameters:
phantom Phantom NIC
reg Register offset within abstract address space
Return values:
offset Register offset within PCI BAR0

Definition at line 265 of file phantom.c.

References assert, phantom_nic::bar0, phantom_nic::crb_window, offset, readl, UNM_32M_CRB_WINDOW, and writel.

Referenced by phantom_map_crb().

00266                                                                   {
00267         unsigned long offset = ( reg & 0x1ffffff );
00268         uint32_t window = ( reg & 0x2000000 );
00269         uint32_t verify_window;
00270 
00271         if ( phantom->crb_window != window ) {
00272 
00273                 /* Write to the CRB window register */
00274                 writel ( window, phantom->bar0 + UNM_32M_CRB_WINDOW );
00275 
00276                 /* Ensure that the write has reached the card */
00277                 verify_window = readl ( phantom->bar0 + UNM_32M_CRB_WINDOW );
00278                 assert ( verify_window == window );
00279 
00280                 /* Record new window */
00281                 phantom->crb_window = window;
00282         }
00283 
00284         return offset;
00285 }

static unsigned long phantom_crb_access_2m ( struct phantom_nic phantom,
unsigned long  reg 
) [static]

Prepare for access to CRB register via 2MB BAR.

Parameters:
phantom Phantom NIC
reg Register offset within abstract address space
Return values:
offset Register offset within PCI BAR0

Definition at line 294 of file phantom.c.

References assert, phantom_nic::bar0, phantom_nic::crb_window, offset, readl, UNM_2M_CRB_WINDOW, UNM_CRB_BLK, UNM_CRB_BLK_CAM, UNM_CRB_BLK_PCIE, UNM_CRB_BLK_PEG_0, UNM_CRB_BLK_PEG_1, UNM_CRB_BLK_PEG_2, UNM_CRB_BLK_PEG_3, UNM_CRB_BLK_PEG_4, UNM_CRB_BLK_ROMUSB, UNM_CRB_BLK_TEST, UNM_CRB_OFFSET, and writel.

Referenced by phantom_map_crb().

00295                                                                  {
00296         static const struct {
00297                 uint8_t block;
00298                 uint16_t window_hi;
00299         } reg_window_hi[] = {
00300                 { UNM_CRB_BLK_PCIE,     0x773 },
00301                 { UNM_CRB_BLK_CAM,      0x416 },
00302                 { UNM_CRB_BLK_ROMUSB,   0x421 },
00303                 { UNM_CRB_BLK_TEST,     0x295 },
00304                 { UNM_CRB_BLK_PEG_0,    0x340 },
00305                 { UNM_CRB_BLK_PEG_1,    0x341 },
00306                 { UNM_CRB_BLK_PEG_2,    0x342 },
00307                 { UNM_CRB_BLK_PEG_3,    0x343 },
00308                 { UNM_CRB_BLK_PEG_4,    0x34b },
00309         };
00310         unsigned int block = UNM_CRB_BLK ( reg );
00311         unsigned long offset = UNM_CRB_OFFSET ( reg );
00312         uint32_t window;
00313         uint32_t verify_window;
00314         unsigned int i;
00315 
00316         for ( i = 0 ; i < ( sizeof ( reg_window_hi ) /
00317                             sizeof ( reg_window_hi[0] ) ) ; i++ ) {
00318 
00319                 if ( reg_window_hi[i].block != block )
00320                         continue;
00321 
00322                 window = ( ( reg_window_hi[i].window_hi << 20 ) |
00323                            ( offset & 0x000f0000 ) );
00324 
00325                 if ( phantom->crb_window != window ) {
00326 
00327                         /* Write to the CRB window register */
00328                         writel ( window, phantom->bar0 + UNM_2M_CRB_WINDOW );
00329 
00330                         /* Ensure that the write has reached the card */
00331                         verify_window = readl ( phantom->bar0 +
00332                                                 UNM_2M_CRB_WINDOW );
00333                         assert ( verify_window == window );
00334 
00335                         /* Record new window */
00336                         phantom->crb_window = window;
00337                 }
00338 
00339                 return ( 0x1e0000 + ( offset & 0xffff ) );
00340         }
00341 
00342         assert ( 0 );
00343         return 0;
00344 }

static uint32_t phantom_readl ( struct phantom_nic phantom,
unsigned long  reg 
) [static]

Read from Phantom CRB register.

Parameters:
phantom Phantom NIC
reg Register offset within abstract address space
Return values:
value Register value

Definition at line 353 of file phantom.c.

References phantom_nic::bar0, phantom_nic::crb_access, offset, and readl.

Referenced by phantom_check_boot_enable(), phantom_clp_cmd(), phantom_clp_wait(), phantom_dmesg(), phantom_get_macaddr(), phantom_init_cmdpeg(), phantom_init_rcvpeg(), phantom_poll(), phantom_poll_link_state(), phantom_read_test_mem_block(), phantom_unhalt_pegs(), and phantom_wait_for_cmd().

00354                                                     {
00355         unsigned long offset;
00356 
00357         offset = phantom->crb_access ( phantom, reg );
00358         return readl ( phantom->bar0 + offset );
00359 }

static void phantom_writel ( struct phantom_nic phantom,
uint32_t  value,
unsigned long  reg 
) [static]

Write to Phantom CRB register.

Parameters:
phantom Phantom NIC
value Register value
reg Register offset within abstract address space

Definition at line 368 of file phantom.c.

References phantom_nic::bar0, phantom_nic::crb_access, offset, and writel.

Referenced by phantom_clp_cmd(), phantom_init_cmdpeg(), phantom_irq(), phantom_issue_cmd(), phantom_poll(), phantom_post_cds(), phantom_post_rds(), phantom_read_test_mem_block(), phantom_unhalt_pegs(), and phantom_write_hilo().

00369                                                  {
00370         unsigned long offset;
00371 
00372         offset = phantom->crb_access ( phantom, reg );
00373         writel ( value, phantom->bar0 + offset );
00374 }

static void phantom_write_hilo ( struct phantom_nic phantom,
uint64_t  value,
unsigned long  lo_offset,
unsigned long  hi_offset 
) [inline, static]

Write to Phantom CRB HI/LO register pair.

Parameters:
phantom Phantom NIC
value Register value
lo_offset LO register offset within CRB
hi_offset HI register offset within CRB

Definition at line 384 of file phantom.c.

References phantom_writel().

Referenced by phantom_init_cmdpeg(), and phantom_read_test_mem_block().

00387                                                                   {
00388         uint32_t lo = ( value & 0xffffffffUL );
00389         uint32_t hi = ( value >> 32 );
00390 
00391         phantom_writel ( phantom, lo, lo_offset );
00392         phantom_writel ( phantom, hi, hi_offset );
00393 }

static int phantom_read_test_mem_block ( struct phantom_nic phantom,
unsigned long  offset,
uint32_t  buf[2] 
) [static]

Read from Phantom test memory.

Parameters:
phantom Phantom NIC
offset Offset within test memory
buf 8-byte buffer to fill
Return values:
rc Return status code

Definition at line 409 of file phantom.c.

References DBGC, ETIMEDOUT, mdelay(), phantom_readl(), phantom_write_hilo(), phantom_writel(), PHN_TEST_MEM_TIMEOUT_MS, UNM_TEST_ADDR_HI, UNM_TEST_ADDR_LO, UNM_TEST_CONTROL, UNM_TEST_CONTROL_BUSY, UNM_TEST_CONTROL_ENABLE, UNM_TEST_CONTROL_START, UNM_TEST_RDDATA_HI, and UNM_TEST_RDDATA_LO.

Referenced by phantom_read_test_mem().

00411                                                            {
00412         unsigned int retries;
00413         uint32_t test_control;
00414 
00415         phantom_write_hilo ( phantom, offset, UNM_TEST_ADDR_LO,
00416                              UNM_TEST_ADDR_HI );
00417         phantom_writel ( phantom, UNM_TEST_CONTROL_ENABLE, UNM_TEST_CONTROL );
00418         phantom_writel ( phantom,
00419                          ( UNM_TEST_CONTROL_ENABLE | UNM_TEST_CONTROL_START ),
00420                          UNM_TEST_CONTROL );
00421         
00422         for ( retries = 0 ; retries < PHN_TEST_MEM_TIMEOUT_MS ; retries++ ) {
00423                 test_control = phantom_readl ( phantom, UNM_TEST_CONTROL );
00424                 if ( ( test_control & UNM_TEST_CONTROL_BUSY ) == 0 ) {
00425                         buf[0] = phantom_readl ( phantom, UNM_TEST_RDDATA_LO );
00426                         buf[1] = phantom_readl ( phantom, UNM_TEST_RDDATA_HI );
00427                         return 0;
00428                 }
00429                 mdelay ( 1 );
00430         }
00431 
00432         DBGC ( phantom, "Phantom %p timed out waiting for test memory\n",
00433                phantom );
00434         return -ETIMEDOUT;
00435 }

static int phantom_read_test_mem ( struct phantom_nic phantom,
unsigned long  offset 
) [static]

Read single byte from Phantom test memory.

Parameters:
phantom Phantom NIC
offset Offset within test memory
Return values:
byte Byte read, or negative error

Definition at line 444 of file phantom.c.

References phantom_read_test_mem_block().

Referenced by phantom_dmesg().

00445                                                           {
00446         static union {
00447                 uint8_t bytes[8];
00448                 uint32_t dwords[2];
00449         } cache;
00450         static unsigned long cache_offset = -1UL;
00451         unsigned long sub_offset;
00452         int rc;
00453 
00454         sub_offset = ( offset & ( sizeof ( cache ) - 1 ) );
00455         offset = ( offset & ~( sizeof ( cache ) - 1 ) );
00456 
00457         if ( cache_offset != offset ) {
00458                 if ( ( rc = phantom_read_test_mem_block ( phantom, offset,
00459                                                           cache.dwords )) !=0 )
00460                         return rc;
00461                 cache_offset = offset;
00462         }
00463 
00464         return cache.bytes[sub_offset];
00465 }

static int phantom_dmesg ( struct phantom_nic phantom,
unsigned int  log,
unsigned int  max_lines 
) [static]

Dump Phantom firmware dmesg log.

Parameters:
phantom Phantom NIC
log Log number
max_lines Maximum number of lines to show, or -1 to show all
Return values:
rc Return status code

Definition at line 475 of file phantom.c.

References assert, DBG, DBG_LOG, DBGC, offset, phantom_read_test_mem(), phantom_readl(), UNM_CAM_RAM_DMESG_HEAD, UNM_CAM_RAM_DMESG_LEN, UNM_CAM_RAM_DMESG_SIG, UNM_CAM_RAM_DMESG_SIG_MAGIC, and UNM_CAM_RAM_DMESG_TAIL.

Referenced by phantom_dmesg_all().

00476                                                      {
00477         uint32_t head;
00478         uint32_t tail;
00479         uint32_t len;
00480         uint32_t sig;
00481         uint32_t offset;
00482         int byte;
00483 
00484         /* Optimise out for non-debug builds */
00485         if ( ! DBG_LOG )
00486                 return 0;
00487 
00488         /* Locate log */
00489         head = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_HEAD ( log ) );
00490         len = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_LEN ( log ) );
00491         tail = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_TAIL ( log ) );
00492         sig = phantom_readl ( phantom, UNM_CAM_RAM_DMESG_SIG ( log ) );
00493         DBGC ( phantom, "Phantom %p firmware dmesg buffer %d (%08x-%08x)\n",
00494                phantom, log, head, tail );
00495         assert ( ( head & 0x07 ) == 0 );
00496         if ( sig != UNM_CAM_RAM_DMESG_SIG_MAGIC ) {
00497                 DBGC ( phantom, "Warning: bad signature %08x (want %08lx)\n",
00498                        sig, UNM_CAM_RAM_DMESG_SIG_MAGIC );
00499         }
00500 
00501         /* Locate start of last (max_lines) lines */
00502         for ( offset = tail ; offset > head ; offset-- ) {
00503                 if ( ( byte = phantom_read_test_mem ( phantom,
00504                                                       ( offset - 1 ) ) ) < 0 )
00505                         return byte;
00506                 if ( ( byte == '\n' ) && ( max_lines-- == 0 ) )
00507                         break;
00508         }
00509 
00510         /* Print lines */
00511         for ( ; offset < tail ; offset++ ) {
00512                 if ( ( byte = phantom_read_test_mem ( phantom, offset ) ) < 0 )
00513                         return byte;
00514                 DBG ( "%c", byte );
00515         }
00516         DBG ( "\n" );
00517         return 0;
00518 }

static void phantom_dmesg_all ( struct phantom_nic phantom,
unsigned int  max_lines 
) [static]

Dump Phantom firmware dmesg logs.

Parameters:
phantom Phantom NIC
max_lines Maximum number of lines to show, or -1 to show all

Definition at line 527 of file phantom.c.

References phantom_dmesg(), and UNM_CAM_RAM_NUM_DMESG_BUFFERS.

00527                                                                           {
00528         unsigned int i;
00529 
00530         for ( i = 0 ; i < UNM_CAM_RAM_NUM_DMESG_BUFFERS ; i++ )
00531                 phantom_dmesg ( phantom, i, max_lines );
00532 }

static int phantom_wait_for_cmd ( struct phantom_nic phantom  )  [static]

Wait for firmware to accept command.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 546 of file phantom.c.

References DBGC, EIO, EPROTO, ETIMEDOUT, mdelay(), NX_CDRP_FORM_RSP, NX_CDRP_IS_RSP, NX_CDRP_RSP_FAIL, NX_CDRP_RSP_OK, NX_CDRP_RSP_TIMEOUT, phantom_readl(), PHN_ISSUE_CMD_TIMEOUT_MS, and UNM_NIC_REG_NX_CDRP.

Referenced by phantom_issue_cmd().

00546                                                                 {
00547         unsigned int retries;
00548         uint32_t cdrp;
00549 
00550         for ( retries = 0 ; retries < PHN_ISSUE_CMD_TIMEOUT_MS ; retries++ ) {
00551                 mdelay ( 1 );
00552                 cdrp = phantom_readl ( phantom, UNM_NIC_REG_NX_CDRP );
00553                 if ( NX_CDRP_IS_RSP ( cdrp ) ) {
00554                         switch ( NX_CDRP_FORM_RSP ( cdrp ) ) {
00555                         case NX_CDRP_RSP_OK:
00556                                 return 0;
00557                         case NX_CDRP_RSP_FAIL:
00558                                 return -EIO;
00559                         case NX_CDRP_RSP_TIMEOUT:
00560                                 return -ETIMEDOUT;
00561                         default:
00562                                 return -EPROTO;
00563                         }
00564                 }
00565         }
00566 
00567         DBGC ( phantom, "Phantom %p timed out waiting for firmware to accept "
00568                "command\n", phantom );
00569         return -ETIMEDOUT;
00570 }

static int phantom_issue_cmd ( struct phantom_nic phantom,
uint32_t  command,
uint32_t  arg1,
uint32_t  arg2,
uint32_t  arg3 
) [static]

Issue command to firmware.

Parameters:
phantom Phantom NIC
command Firmware command
arg1 Argument 1
arg2 Argument 2
arg3 Argument 3
Return values:
rc Return status code

Definition at line 582 of file phantom.c.

References DBGC, DBGC2, NX_CDRP_FORM_CMD, NX_CDRP_SIGNATURE_MAKE, NXHAL_VERSION, phantom_wait_for_cmd(), phantom_writel(), phantom_nic::port, strerror(), UNM_NIC_REG_NX_ARG1, UNM_NIC_REG_NX_ARG2, UNM_NIC_REG_NX_ARG3, UNM_NIC_REG_NX_CDRP, and UNM_NIC_REG_NX_SIGN.

Referenced by phantom_destroy_rx_ctx(), phantom_destroy_tx_ctx(), and phantom_issue_buf_cmd().

00584                                                {
00585         uint32_t signature;
00586         int rc;
00587 
00588         /* Issue command */
00589         signature = NX_CDRP_SIGNATURE_MAKE ( phantom->port,
00590                                              NXHAL_VERSION );
00591         DBGC2 ( phantom, "Phantom %p issuing command %08x (%08x, %08x, "
00592                 "%08x)\n", phantom, command, arg1, arg2, arg3 );
00593         phantom_writel ( phantom, signature, UNM_NIC_REG_NX_SIGN );
00594         phantom_writel ( phantom, arg1, UNM_NIC_REG_NX_ARG1 );
00595         phantom_writel ( phantom, arg2, UNM_NIC_REG_NX_ARG2 );
00596         phantom_writel ( phantom, arg3, UNM_NIC_REG_NX_ARG3 );
00597         phantom_writel ( phantom, NX_CDRP_FORM_CMD ( command ),
00598                          UNM_NIC_REG_NX_CDRP );
00599 
00600         /* Wait for command to be accepted */
00601         if ( ( rc = phantom_wait_for_cmd ( phantom ) ) != 0 ) {
00602                 DBGC ( phantom, "Phantom %p could not issue command: %s\n",
00603                        phantom, strerror ( rc ) );
00604                 return rc;
00605         }
00606 
00607         return 0;
00608 }

static int phantom_issue_buf_cmd ( struct phantom_nic phantom,
uint32_t  command,
void *  buffer,
size_t  len 
) [static]

Issue buffer-format command to firmware.

Parameters:
phantom Phantom NIC
command Firmware command
buffer Buffer to pass to firmware
len Length of buffer
Return values:
rc Return status code

Definition at line 619 of file phantom.c.

References phantom_issue_cmd(), and virt_to_bus().

Referenced by phantom_create_rx_ctx(), and phantom_create_tx_ctx().

00621                                                 {
00622         uint64_t physaddr;
00623 
00624         physaddr = virt_to_bus ( buffer );
00625         return phantom_issue_cmd ( phantom, command, ( physaddr >> 32 ),
00626                                    ( physaddr & 0xffffffffUL ), len );
00627 }

static int phantom_create_rx_ctx ( struct phantom_nic phantom  )  [static]

Create Phantom RX context.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 635 of file phantom.c.

References nx_hostrq_rds_ring_s::buff_size, nx_hostrq_rx_ctx_s::capabilities, phantom_create_rx_ctx_rqrsp::cardrsp, cpu_to_le16, cpu_to_le32, cpu_to_le64, DBGC, DBGC2_HDA, DBGC_HDA, phantom_nic::desc, ENOMEM, free_dma(), nx_hostrq_rx_ctx_s::host_int_crb_mode, nx_hostrq_sds_ring_s::host_phys_addr, nx_hostrq_rds_ring_s::host_phys_addr, nx_hostrq_rx_ctx_s::host_rds_crb_mode, nx_hostrq_rx_ctx_s::host_rsp_dma_addr, phantom_create_rx_ctx_rqrsp::hostrq, le16_to_cpu, le32_to_cpu, malloc_dma(), memset(), nx_hostrq_rx_ctx_s::num_rds_rings, nx_hostrq_rx_ctx_s::num_sds_rings, NX_CAP0_LEGACY_CONTEXT, NX_CAP0_LEGACY_MN, NX_CDRP_CMD_CREATE_RX_CTX, NX_HOST_INT_CRB_MODE_SHARED, NX_HOST_RDS_CRB_MODE_UNIQUE, NX_RDS_RING_TYPE_NORMAL, phantom_issue_buf_cmd(), PHN_NUM_RDS, PHN_NUM_SDS, PHN_RX_BUFSIZE, phantom_descriptor_rings::rds, phantom_create_rx_ctx_rqrsp::rds, phantom_nic::rds_producer_crb, nx_hostrq_rx_ctx_s::rds_ring_offset, nx_hostrq_rds_ring_s::ring_kind, nx_hostrq_sds_ring_s::ring_size, nx_hostrq_rds_ring_s::ring_size, phantom_nic::rx_context_id, phantom_create_rx_ctx_rqrsp::rx_ctx, phantom_descriptor_rings::sds, phantom_create_rx_ctx_rqrsp::sds, phantom_nic::sds_consumer_crb, phantom_nic::sds_irq_mask_crb, nx_hostrq_rx_ctx_s::sds_ring_offset, strerror(), UNM_CAM_RAM, UNM_DMA_BUFFER_ALIGN, and virt_to_bus().

Referenced by phantom_open().

00635                                                                  {
00636         struct phantom_create_rx_ctx_rqrsp *buf;
00637         int rc;
00638 
00639         /* Allocate context creation buffer */
00640         buf = malloc_dma ( sizeof ( *buf ), UNM_DMA_BUFFER_ALIGN );
00641         if ( ! buf ) {
00642                 rc = -ENOMEM;
00643                 goto out;
00644         }
00645         memset ( buf, 0, sizeof ( *buf ) );
00646         
00647         /* Prepare request */
00648         buf->hostrq.rx_ctx.host_rsp_dma_addr =
00649                 cpu_to_le64 ( virt_to_bus ( &buf->cardrsp ) );
00650         buf->hostrq.rx_ctx.capabilities[0] =
00651                 cpu_to_le32 ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN );
00652         buf->hostrq.rx_ctx.host_int_crb_mode =
00653                 cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED );
00654         buf->hostrq.rx_ctx.host_rds_crb_mode =
00655                 cpu_to_le32 ( NX_HOST_RDS_CRB_MODE_UNIQUE );
00656         buf->hostrq.rx_ctx.rds_ring_offset = cpu_to_le32 ( 0 );
00657         buf->hostrq.rx_ctx.sds_ring_offset =
00658                 cpu_to_le32 ( sizeof ( buf->hostrq.rds ) );
00659         buf->hostrq.rx_ctx.num_rds_rings = cpu_to_le16 ( 1 );
00660         buf->hostrq.rx_ctx.num_sds_rings = cpu_to_le16 ( 1 );
00661         buf->hostrq.rds.host_phys_addr =
00662                 cpu_to_le64 ( virt_to_bus ( phantom->desc->rds ) );
00663         buf->hostrq.rds.buff_size = cpu_to_le64 ( PHN_RX_BUFSIZE );
00664         buf->hostrq.rds.ring_size = cpu_to_le32 ( PHN_NUM_RDS );
00665         buf->hostrq.rds.ring_kind = cpu_to_le32 ( NX_RDS_RING_TYPE_NORMAL );
00666         buf->hostrq.sds.host_phys_addr =
00667                 cpu_to_le64 ( virt_to_bus ( phantom->desc->sds ) );
00668         buf->hostrq.sds.ring_size = cpu_to_le32 ( PHN_NUM_SDS );
00669 
00670         DBGC ( phantom, "Phantom %p creating RX context\n", phantom );
00671         DBGC2_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
00672                     &buf->hostrq, sizeof ( buf->hostrq ) );
00673 
00674         /* Issue request */
00675         if ( ( rc = phantom_issue_buf_cmd ( phantom,
00676                                             NX_CDRP_CMD_CREATE_RX_CTX,
00677                                             &buf->hostrq,
00678                                             sizeof ( buf->hostrq ) ) ) != 0 ) {
00679                 DBGC ( phantom, "Phantom %p could not create RX context: "
00680                        "%s\n", phantom, strerror ( rc ) );
00681                 DBGC ( phantom, "Request:\n" );
00682                 DBGC_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
00683                            &buf->hostrq, sizeof ( buf->hostrq ) );
00684                 DBGC ( phantom, "Response:\n" );
00685                 DBGC_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
00686                            &buf->cardrsp, sizeof ( buf->cardrsp ) );
00687                 goto out;
00688         }
00689 
00690         /* Retrieve context parameters */
00691         phantom->rx_context_id =
00692                 le16_to_cpu ( buf->cardrsp.rx_ctx.context_id );
00693         phantom->rds_producer_crb =
00694                 ( UNM_CAM_RAM +
00695                   le32_to_cpu ( buf->cardrsp.rds.host_producer_crb ) );
00696         phantom->sds_consumer_crb =
00697                 ( UNM_CAM_RAM +
00698                   le32_to_cpu ( buf->cardrsp.sds.host_consumer_crb ) );
00699         phantom->sds_irq_mask_crb =
00700                 ( UNM_CAM_RAM +
00701                   le32_to_cpu ( buf->cardrsp.sds.interrupt_crb ) );
00702 
00703         DBGC ( phantom, "Phantom %p created RX context (id %04x, port phys "
00704                "%02x virt %02x)\n", phantom, phantom->rx_context_id,
00705                buf->cardrsp.rx_ctx.phys_port, buf->cardrsp.rx_ctx.virt_port );
00706         DBGC2_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
00707                     &buf->cardrsp, sizeof ( buf->cardrsp ) );
00708         DBGC ( phantom, "Phantom %p RDS producer CRB is %08lx\n",
00709                phantom, phantom->rds_producer_crb );
00710         DBGC ( phantom, "Phantom %p SDS consumer CRB is %08lx\n",
00711                phantom, phantom->sds_consumer_crb );
00712         DBGC ( phantom, "Phantom %p SDS interrupt mask CRB is %08lx\n",
00713                phantom, phantom->sds_irq_mask_crb );
00714 
00715  out:
00716         free_dma ( buf, sizeof ( *buf ) );
00717         return rc;
00718 }

static void phantom_destroy_rx_ctx ( struct phantom_nic phantom  )  [static]

Destroy Phantom RX context.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 726 of file phantom.c.

References DBGC, NX_CDRP_CMD_DESTROY_RX_CTX, NX_DESTROY_CTX_RESET, phantom_issue_cmd(), phantom_nic::rds_consumer_idx, phantom_nic::rds_producer_crb, phantom_nic::rds_producer_idx, phantom_nic::rx_context_id, phantom_nic::sds_consumer_crb, phantom_nic::sds_consumer_idx, and strerror().

Referenced by phantom_close(), and phantom_open().

00726                                                                    {
00727         int rc;
00728         
00729         DBGC ( phantom, "Phantom %p destroying RX context (id %04x)\n",
00730                phantom, phantom->rx_context_id );
00731 
00732         /* Issue request */
00733         if ( ( rc = phantom_issue_cmd ( phantom,
00734                                         NX_CDRP_CMD_DESTROY_RX_CTX,
00735                                         phantom->rx_context_id,
00736                                         NX_DESTROY_CTX_RESET, 0 ) ) != 0 ) {
00737                 DBGC ( phantom, "Phantom %p could not destroy RX context: "
00738                        "%s\n", phantom, strerror ( rc ) );
00739                 /* We're probably screwed */
00740                 return;
00741         }
00742 
00743         /* Clear context parameters */
00744         phantom->rx_context_id = 0;
00745         phantom->rds_producer_crb = 0;
00746         phantom->sds_consumer_crb = 0;
00747 
00748         /* Reset software counters */
00749         phantom->rds_producer_idx = 0;
00750         phantom->rds_consumer_idx = 0;
00751         phantom->sds_consumer_idx = 0;
00752 }

static int phantom_create_tx_ctx ( struct phantom_nic phantom  )  [static]

Create Phantom TX context.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 760 of file phantom.c.

References nx_hostrq_tx_ctx_s::capabilities, phantom_create_tx_ctx_rqrsp::cardrsp, phantom_descriptor_rings::cds, phantom_nic::cds_producer_crb, nx_hostrq_tx_ctx_s::cds_ring, phantom_descriptor_rings::cmd_cons, nx_hostrq_tx_ctx_s::cmd_cons_dma_addr, cpu_to_le32, cpu_to_le64, DBGC, DBGC2_HDA, DBGC_HDA, phantom_nic::desc, ENOMEM, free_dma(), nx_hostrq_tx_ctx_s::host_int_crb_mode, nx_hostrq_cds_ring_s::host_phys_addr, nx_hostrq_tx_ctx_s::host_rsp_dma_addr, phantom_create_tx_ctx_rqrsp::hostrq, le16_to_cpu, le32_to_cpu, malloc_dma(), memset(), NX_CAP0_LEGACY_CONTEXT, NX_CAP0_LEGACY_MN, NX_CDRP_CMD_CREATE_TX_CTX, NX_HOST_INT_CRB_MODE_SHARED, phantom_issue_buf_cmd(), PHN_NUM_CDS, nx_hostrq_cds_ring_s::ring_size, strerror(), phantom_nic::tx_context_id, phantom_create_tx_ctx_rqrsp::tx_ctx, UNM_CAM_RAM, UNM_DMA_BUFFER_ALIGN, and virt_to_bus().

Referenced by phantom_open().

00760                                                                  {
00761         struct phantom_create_tx_ctx_rqrsp *buf;
00762         int rc;
00763 
00764         /* Allocate context creation buffer */
00765         buf = malloc_dma ( sizeof ( *buf ), UNM_DMA_BUFFER_ALIGN );
00766         if ( ! buf ) {
00767                 rc = -ENOMEM;
00768                 goto out;
00769         }
00770         memset ( buf, 0, sizeof ( *buf ) );
00771 
00772         /* Prepare request */
00773         buf->hostrq.tx_ctx.host_rsp_dma_addr =
00774                 cpu_to_le64 ( virt_to_bus ( &buf->cardrsp ) );
00775         buf->hostrq.tx_ctx.cmd_cons_dma_addr =
00776                 cpu_to_le64 ( virt_to_bus ( &phantom->desc->cmd_cons ) );
00777         buf->hostrq.tx_ctx.capabilities[0] =
00778                 cpu_to_le32 ( NX_CAP0_LEGACY_CONTEXT | NX_CAP0_LEGACY_MN );
00779         buf->hostrq.tx_ctx.host_int_crb_mode =
00780                 cpu_to_le32 ( NX_HOST_INT_CRB_MODE_SHARED );
00781         buf->hostrq.tx_ctx.cds_ring.host_phys_addr =
00782                 cpu_to_le64 ( virt_to_bus ( phantom->desc->cds ) );
00783         buf->hostrq.tx_ctx.cds_ring.ring_size = cpu_to_le32 ( PHN_NUM_CDS );
00784 
00785         DBGC ( phantom, "Phantom %p creating TX context\n", phantom );
00786         DBGC2_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
00787                     &buf->hostrq, sizeof ( buf->hostrq ) );
00788 
00789         /* Issue request */
00790         if ( ( rc = phantom_issue_buf_cmd ( phantom,
00791                                             NX_CDRP_CMD_CREATE_TX_CTX,
00792                                             &buf->hostrq,
00793                                             sizeof ( buf->hostrq ) ) ) != 0 ) {
00794                 DBGC ( phantom, "Phantom %p could not create TX context: "
00795                        "%s\n", phantom, strerror ( rc ) );
00796                 DBGC ( phantom, "Request:\n" );
00797                 DBGC_HDA ( phantom, virt_to_bus ( &buf->hostrq ),
00798                            &buf->hostrq, sizeof ( buf->hostrq ) );
00799                 DBGC ( phantom, "Response:\n" );
00800                 DBGC_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
00801                            &buf->cardrsp, sizeof ( buf->cardrsp ) );
00802                 goto out;
00803         }
00804 
00805         /* Retrieve context parameters */
00806         phantom->tx_context_id =
00807                 le16_to_cpu ( buf->cardrsp.tx_ctx.context_id );
00808         phantom->cds_producer_crb =
00809                 ( UNM_CAM_RAM +
00810                   le32_to_cpu(buf->cardrsp.tx_ctx.cds_ring.host_producer_crb));
00811 
00812         DBGC ( phantom, "Phantom %p created TX context (id %04x, port phys "
00813                "%02x virt %02x)\n", phantom, phantom->tx_context_id,
00814                buf->cardrsp.tx_ctx.phys_port, buf->cardrsp.tx_ctx.virt_port );
00815         DBGC2_HDA ( phantom, virt_to_bus ( &buf->cardrsp ),
00816                     &buf->cardrsp, sizeof ( buf->cardrsp ) );
00817         DBGC ( phantom, "Phantom %p CDS producer CRB is %08lx\n",
00818                phantom, phantom->cds_producer_crb );
00819 
00820  out:
00821         free_dma ( buf, sizeof ( *buf ) );
00822         return rc;
00823 }

static void phantom_destroy_tx_ctx ( struct phantom_nic phantom  )  [static]

Destroy Phantom TX context.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 831 of file phantom.c.

References phantom_nic::cds_consumer_idx, phantom_nic::cds_producer_crb, phantom_nic::cds_producer_idx, DBGC, NX_CDRP_CMD_DESTROY_TX_CTX, NX_DESTROY_CTX_RESET, phantom_issue_cmd(), strerror(), and phantom_nic::tx_context_id.

Referenced by phantom_close(), and phantom_open().

00831                                                                    {
00832         int rc;
00833         
00834         DBGC ( phantom, "Phantom %p destroying TX context (id %04x)\n",
00835                phantom, phantom->tx_context_id );
00836 
00837         /* Issue request */
00838         if ( ( rc = phantom_issue_cmd ( phantom,
00839                                         NX_CDRP_CMD_DESTROY_TX_CTX,
00840                                         phantom->tx_context_id,
00841                                         NX_DESTROY_CTX_RESET, 0 ) ) != 0 ) {
00842                 DBGC ( phantom, "Phantom %p could not destroy TX context: "
00843                        "%s\n", phantom, strerror ( rc ) );
00844                 /* We're probably screwed */
00845                 return;
00846         }
00847 
00848         /* Clear context parameters */
00849         phantom->tx_context_id = 0;
00850         phantom->cds_producer_crb = 0;
00851 
00852         /* Reset software counters */
00853         phantom->cds_producer_idx = 0;
00854         phantom->cds_consumer_idx = 0;
00855 }

static int phantom_alloc_rds ( struct phantom_nic phantom  )  [static]

Allocate Phantom RX descriptor.

Parameters:
phantom Phantom NIC
Return values:
index RX descriptor index, or negative error

Definition at line 869 of file phantom.c.

References DBGC, ENOBUFS, PHN_NUM_RDS, phantom_nic::rds_consumer_idx, and phantom_nic::rds_producer_idx.

Referenced by phantom_refill_rx_ring().

00869                                                              {
00870         unsigned int rds_producer_idx;
00871         unsigned int next_rds_producer_idx;
00872 
00873         /* Check for space in the ring.  RX descriptors are consumed
00874          * out of order, but they are *read* by the hardware in strict
00875          * order.  We maintain a pessimistic consumer index, which is
00876          * guaranteed never to be an overestimate of the number of
00877          * descriptors read by the hardware.
00878          */
00879         rds_producer_idx = phantom->rds_producer_idx;
00880         next_rds_producer_idx = ( ( rds_producer_idx + 1 ) % PHN_NUM_RDS );
00881         if ( next_rds_producer_idx == phantom->rds_consumer_idx ) {
00882                 DBGC ( phantom, "Phantom %p RDS ring full (index %d not "
00883                        "consumed)\n", phantom, next_rds_producer_idx );
00884                 return -ENOBUFS;
00885         }
00886 
00887         return rds_producer_idx;
00888 }

static void phantom_post_rds ( struct phantom_nic phantom,
struct phantom_rds rds 
) [static]

Post Phantom RX descriptor.

Parameters:
phantom Phantom NIC
rds RX descriptor

Definition at line 896 of file phantom.c.

References DBGC2, DBGC2_HDA, phantom_nic::desc, entry, memcpy, NX_GET, phantom_writel(), PHN_NUM_RDS, phantom_descriptor_rings::rds, phantom_nic::rds_producer_crb, phantom_nic::rds_producer_idx, virt_to_bus(), and wmb.

Referenced by phantom_refill_rx_ring().

00897                                                          {
00898         unsigned int rds_producer_idx;
00899         unsigned int next_rds_producer_idx;
00900         struct phantom_rds *entry;
00901 
00902         /* Copy descriptor to ring */
00903         rds_producer_idx = phantom->rds_producer_idx;
00904         entry = &phantom->desc->rds[rds_producer_idx];
00905         memcpy ( entry, rds, sizeof ( *entry ) );
00906         DBGC2 ( phantom, "Phantom %p posting RDS %ld (slot %d):\n",
00907                 phantom, NX_GET ( rds, handle ), rds_producer_idx );
00908         DBGC2_HDA ( phantom, virt_to_bus ( entry ), entry, sizeof ( *entry ) );
00909 
00910         /* Update producer index */
00911         next_rds_producer_idx = ( ( rds_producer_idx + 1 ) % PHN_NUM_RDS );
00912         phantom->rds_producer_idx = next_rds_producer_idx;
00913         wmb();
00914         phantom_writel ( phantom, phantom->rds_producer_idx,
00915                          phantom->rds_producer_crb );
00916 }

static int phantom_alloc_cds ( struct phantom_nic phantom  )  [static]

Allocate Phantom TX descriptor.

Parameters:
phantom Phantom NIC
Return values:
index TX descriptor index, or negative error

Definition at line 924 of file phantom.c.

References phantom_nic::cds_consumer_idx, phantom_nic::cds_producer_idx, DBGC, ENOBUFS, and PHN_NUM_CDS.

Referenced by phantom_transmit(), and phantom_update_macaddr().

00924                                                              {
00925         unsigned int cds_producer_idx;
00926         unsigned int next_cds_producer_idx;
00927 
00928         /* Check for space in the ring.  TX descriptors are consumed
00929          * in strict order, so we just check for a collision against
00930          * the consumer index.
00931          */
00932         cds_producer_idx = phantom->cds_producer_idx;
00933         next_cds_producer_idx = ( ( cds_producer_idx + 1 ) % PHN_NUM_CDS );
00934         if ( next_cds_producer_idx == phantom->cds_consumer_idx ) {
00935                 DBGC ( phantom, "Phantom %p CDS ring full (index %d not "
00936                        "consumed)\n", phantom, next_cds_producer_idx );
00937                 return -ENOBUFS;
00938         }
00939 
00940         return cds_producer_idx;
00941 }

static void phantom_post_cds ( struct phantom_nic phantom,
union phantom_cds cds 
) [static]

Post Phantom TX descriptor.

Parameters:
phantom Phantom NIC
cds TX descriptor

Definition at line 949 of file phantom.c.

References phantom_descriptor_rings::cds, phantom_nic::cds_producer_crb, phantom_nic::cds_producer_idx, DBGC2, DBGC2_HDA, phantom_nic::desc, entry, memcpy, phantom_writel(), PHN_NUM_CDS, virt_to_bus(), and wmb.

Referenced by phantom_transmit(), and phantom_update_macaddr().

00950                                                         {
00951         unsigned int cds_producer_idx;
00952         unsigned int next_cds_producer_idx;
00953         union phantom_cds *entry;
00954 
00955         /* Copy descriptor to ring */
00956         cds_producer_idx = phantom->cds_producer_idx;
00957         entry = &phantom->desc->cds[cds_producer_idx];
00958         memcpy ( entry, cds, sizeof ( *entry ) );
00959         DBGC2 ( phantom, "Phantom %p posting CDS %d:\n",
00960                 phantom, cds_producer_idx );
00961         DBGC2_HDA ( phantom, virt_to_bus ( entry ), entry, sizeof ( *entry ) );
00962 
00963         /* Update producer index */
00964         next_cds_producer_idx = ( ( cds_producer_idx + 1 ) % PHN_NUM_CDS );
00965         phantom->cds_producer_idx = next_cds_producer_idx;
00966         wmb();
00967         phantom_writel ( phantom, phantom->cds_producer_idx,
00968                          phantom->cds_producer_crb );
00969 }

static int phantom_update_macaddr ( struct phantom_nic phantom,
const uint8_t ll_addr,
unsigned int  opcode 
) [static]

Add/remove MAC address.

Parameters:
phantom Phantom NIC
ll_addr MAC address to add or remove
opcode MAC request opcode
Return values:
rc Return status code

Definition at line 985 of file phantom.c.

References index, memset(), NX_FILL_1, NX_FILL_2, NX_FILL_7, phantom_alloc_cds(), phantom_post_cds(), phantom_nic::port, UNM_MAC_EVENT, and UNM_NIC_REQUEST.

Referenced by phantom_add_macaddr(), and phantom_del_macaddr().

00987                                                           {
00988         union phantom_cds cds;
00989         int index;
00990 
00991         /* Get descriptor ring entry */
00992         index = phantom_alloc_cds ( phantom );
00993         if ( index < 0 )
00994                 return index;
00995 
00996         /* Fill descriptor ring entry */
00997         memset ( &cds, 0, sizeof ( cds ) );
00998         NX_FILL_1 ( &cds, 0,
00999                     nic_request.common.opcode, UNM_NIC_REQUEST );
01000         NX_FILL_2 ( &cds, 1,
01001                     nic_request.header.opcode, UNM_MAC_EVENT,
01002                     nic_request.header.context_id, phantom->port );
01003         NX_FILL_7 ( &cds, 2,
01004                     nic_request.body.mac_request.opcode, opcode,
01005                     nic_request.body.mac_request.mac_addr_0, ll_addr[0],
01006                     nic_request.body.mac_request.mac_addr_1, ll_addr[1],
01007                     nic_request.body.mac_request.mac_addr_2, ll_addr[2],
01008                     nic_request.body.mac_request.mac_addr_3, ll_addr[3],
01009                     nic_request.body.mac_request.mac_addr_4, ll_addr[4],
01010                     nic_request.body.mac_request.mac_addr_5, ll_addr[5] );
01011 
01012         /* Post descriptor */
01013         phantom_post_cds ( phantom, &cds );
01014 
01015         return 0;
01016 }

static int phantom_add_macaddr ( struct phantom_nic phantom,
const uint8_t ll_addr 
) [inline, static]

Add MAC address.

Parameters:
phantom Phantom NIC
ll_addr MAC address to add or remove
Return values:
rc Return status code

Definition at line 1025 of file phantom.c.

References DBGC, eth_ntoa(), phantom_update_macaddr(), and UNM_MAC_ADD.

Referenced by phantom_open().

01026                                                                  {
01027 
01028         DBGC ( phantom, "Phantom %p adding MAC address %s\n",
01029                phantom, eth_ntoa ( ll_addr ) );
01030 
01031         return phantom_update_macaddr ( phantom, ll_addr, UNM_MAC_ADD );
01032 }

static int phantom_del_macaddr ( struct phantom_nic phantom,
const uint8_t ll_addr 
) [inline, static]

Remove MAC address.

Parameters:
phantom Phantom NIC
ll_addr MAC address to add or remove
Return values:
rc Return status code

Definition at line 1041 of file phantom.c.

References DBGC, eth_ntoa(), phantom_update_macaddr(), and UNM_MAC_DEL.

Referenced by phantom_close(), and phantom_open().

01042                                                                  {
01043 
01044         DBGC ( phantom, "Phantom %p removing MAC address %s\n",
01045                phantom, eth_ntoa ( ll_addr ) );
01046 
01047         return phantom_update_macaddr ( phantom, ll_addr, UNM_MAC_DEL );
01048 }

static void phantom_poll_link_state ( struct net_device netdev  )  [static]

Poll link state.

Parameters:
netdev Network device

Definition at line 1061 of file phantom.c.

References DBGC, phantom_nic::link_state, netdev_link_down(), netdev_link_up(), netdev_priv(), phantom_readl(), phantom_nic::port, UNM_NIC_REG_XG_STATE_P3, UNM_NIC_REG_XG_STATE_P3_LINK, UNM_NIC_REG_XG_STATE_P3_LINK_DOWN, and UNM_NIC_REG_XG_STATE_P3_LINK_UP.

Referenced by phantom_poll().

01061                                                                   {
01062         struct phantom_nic *phantom = netdev_priv ( netdev );
01063         uint32_t xg_state_p3;
01064         unsigned int link;
01065 
01066         /* Read link state */
01067         xg_state_p3 = phantom_readl ( phantom, UNM_NIC_REG_XG_STATE_P3 );
01068 
01069         /* If there is no change, do nothing */
01070         if ( phantom->link_state == xg_state_p3 )
01071                 return;
01072 
01073         /* Record new link state */
01074         DBGC ( phantom, "Phantom %p new link state %08x (was %08x)\n",
01075                phantom, xg_state_p3, phantom->link_state );
01076         phantom->link_state = xg_state_p3;
01077 
01078         /* Indicate link state to gPXE */
01079         link = UNM_NIC_REG_XG_STATE_P3_LINK ( phantom->port,
01080                                               phantom->link_state );
01081         switch ( link ) {
01082         case UNM_NIC_REG_XG_STATE_P3_LINK_UP:
01083                 DBGC ( phantom, "Phantom %p link is up\n", phantom );
01084                 netdev_link_up ( netdev );
01085                 break;
01086         case UNM_NIC_REG_XG_STATE_P3_LINK_DOWN:
01087                 DBGC ( phantom, "Phantom %p link is down\n", phantom );
01088                 netdev_link_down ( netdev );
01089                 break;
01090         default:
01091                 DBGC ( phantom, "Phantom %p bad link state %d\n",
01092                        phantom, link );
01093                 break;
01094         }
01095 }

static void phantom_refill_rx_ring ( struct net_device netdev  )  [static]

Refill descriptor ring.

Parameters:
netdev Net device

Definition at line 1108 of file phantom.c.

References alloc_iob(), assert, io_buffer::data, ENOMEM, index, iob_len(), memset(), netdev_priv(), netdev_rx_err(), NULL, NX_FILL_1, NX_FILL_2, phantom_alloc_rds(), phantom_post_rds(), PHN_NUM_RDS, PHN_RDS_MAX_FILL, PHN_RX_BUFSIZE, phantom_nic::rds_iobuf, and virt_to_bus().

Referenced by phantom_open(), and phantom_poll().

01108                                                                  {
01109         struct phantom_nic *phantom = netdev_priv ( netdev );
01110         struct io_buffer *iobuf;
01111         struct phantom_rds rds;
01112         unsigned int handle;
01113         int index;
01114 
01115         for ( handle = 0 ; handle < PHN_RDS_MAX_FILL ; handle++ ) {
01116 
01117                 /* Skip this index if the descriptor has not yet been
01118                  * consumed.
01119                  */
01120                 if ( phantom->rds_iobuf[handle] != NULL )
01121                         continue;
01122 
01123                 /* Allocate descriptor ring entry */
01124                 index = phantom_alloc_rds ( phantom );
01125                 assert ( PHN_RDS_MAX_FILL < PHN_NUM_RDS );
01126                 assert ( index >= 0 ); /* Guaranteed by MAX_FILL < NUM_RDS ) */
01127 
01128                 /* Try to allocate an I/O buffer */
01129                 iobuf = alloc_iob ( PHN_RX_BUFSIZE );
01130                 if ( ! iobuf ) {
01131                         /* Failure is non-fatal; we will retry later */
01132                         netdev_rx_err ( netdev, NULL, -ENOMEM );
01133                         break;
01134                 }
01135 
01136                 /* Fill descriptor ring entry */
01137                 memset ( &rds, 0, sizeof ( rds ) );
01138                 NX_FILL_2 ( &rds, 0,
01139                             handle, handle,
01140                             length, iob_len ( iobuf ) );
01141                 NX_FILL_1 ( &rds, 1,
01142                             dma_addr, virt_to_bus ( iobuf->data ) );
01143 
01144                 /* Record I/O buffer */
01145                 assert ( phantom->rds_iobuf[handle] == NULL );
01146                 phantom->rds_iobuf[handle] = iobuf;
01147 
01148                 /* Post descriptor */
01149                 phantom_post_rds ( phantom, &rds );
01150         }
01151 }

static int phantom_open ( struct net_device netdev  )  [static]

Open NIC.

Parameters:
netdev Net device
Return values:
rc Return status code

Definition at line 1159 of file phantom.c.

References phantom_nic::desc, ENOMEM, free_dma(), net_device::ll_addr, net_device::ll_broadcast, malloc_dma(), memset(), netdev_priv(), NULL, phantom_add_macaddr(), phantom_create_rx_ctx(), phantom_create_tx_ctx(), phantom_del_macaddr(), phantom_destroy_rx_ctx(), phantom_destroy_tx_ctx(), phantom_refill_rx_ring(), and UNM_DMA_BUFFER_ALIGN.

01159                                                       {
01160         struct phantom_nic *phantom = netdev_priv ( netdev );
01161         int rc;
01162 
01163         /* Allocate and zero descriptor rings */
01164         phantom->desc = malloc_dma ( sizeof ( *(phantom->desc) ),
01165                                           UNM_DMA_BUFFER_ALIGN );
01166         if ( ! phantom->desc ) {
01167                 rc = -ENOMEM;
01168                 goto err_alloc_desc;
01169         }
01170         memset ( phantom->desc, 0, sizeof ( *(phantom->desc) ) );
01171 
01172         /* Create RX context */
01173         if ( ( rc = phantom_create_rx_ctx ( phantom ) ) != 0 )
01174                 goto err_create_rx_ctx;
01175 
01176         /* Create TX context */
01177         if ( ( rc = phantom_create_tx_ctx ( phantom ) ) != 0 )
01178                 goto err_create_tx_ctx;
01179 
01180         /* Fill the RX descriptor ring */
01181         phantom_refill_rx_ring ( netdev );
01182 
01183         /* Add MAC addresses
01184          *
01185          * BUG5583
01186          *
01187          * We would like to be able to enable receiving all multicast
01188          * packets (or, failing that, promiscuous mode), but the
01189          * firmware doesn't currently support this.
01190          */
01191         if ( ( rc = phantom_add_macaddr ( phantom,
01192                                           netdev->ll_broadcast ) ) != 0 )
01193                 goto err_add_macaddr_broadcast;
01194         if ( ( rc = phantom_add_macaddr ( phantom,
01195                                           netdev->ll_addr ) ) != 0 )
01196                 goto err_add_macaddr_unicast;
01197 
01198         return 0;
01199 
01200         phantom_del_macaddr ( phantom, netdev->ll_addr );
01201  err_add_macaddr_unicast:
01202         phantom_del_macaddr ( phantom, netdev->ll_broadcast );
01203  err_add_macaddr_broadcast:
01204         phantom_destroy_tx_ctx ( phantom );
01205  err_create_tx_ctx:
01206         phantom_destroy_rx_ctx ( phantom );
01207  err_create_rx_ctx:
01208         free_dma ( phantom->desc, sizeof ( *(phantom->desc) ) );
01209         phantom->desc = NULL;
01210  err_alloc_desc:
01211         return rc;
01212 }

static void phantom_close ( struct net_device netdev  )  [static]

Close NIC.

Parameters:
netdev Net device

Definition at line 1219 of file phantom.c.

References phantom_nic::cds_iobuf, phantom_nic::desc, ECANCELED, free_dma(), free_iob(), net_device::ll_addr, net_device::ll_broadcast, netdev_priv(), netdev_tx_complete_err(), NULL, phantom_del_macaddr(), phantom_destroy_rx_ctx(), phantom_destroy_tx_ctx(), PHN_NUM_CDS, PHN_RDS_MAX_FILL, and phantom_nic::rds_iobuf.

01219                                                         {
01220         struct phantom_nic *phantom = netdev_priv ( netdev );
01221         struct io_buffer *iobuf;
01222         unsigned int i;
01223 
01224         /* Shut down the port */
01225         phantom_del_macaddr ( phantom, netdev->ll_addr );
01226         phantom_del_macaddr ( phantom, netdev->ll_broadcast );
01227         phantom_destroy_tx_ctx ( phantom );
01228         phantom_destroy_rx_ctx ( phantom );
01229         free_dma ( phantom->desc, sizeof ( *(phantom->desc) ) );
01230         phantom->desc = NULL;
01231 
01232         /* Flush any uncompleted descriptors */
01233         for ( i = 0 ; i < PHN_RDS_MAX_FILL ; i++ ) {
01234                 iobuf = phantom->rds_iobuf[i];
01235                 if ( iobuf ) {
01236                         free_iob ( iobuf );
01237                         phantom->rds_iobuf[i] = NULL;
01238                 }
01239         }
01240         for ( i = 0 ; i < PHN_NUM_CDS ; i++ ) {
01241                 iobuf = phantom->cds_iobuf[i];
01242                 if ( iobuf ) {
01243                         netdev_tx_complete_err ( netdev, iobuf, -ECANCELED );
01244                         phantom->cds_iobuf[i] = NULL;
01245                 }
01246         }
01247 }

static int phantom_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet.

Parameters:
netdev Network device
iobuf I/O buffer
Return values:
rc Return status code

Definition at line 1256 of file phantom.c.

References assert, phantom_nic::cds_iobuf, io_buffer::data, index, iob_len(), memset(), netdev_priv(), NULL, NX_FILL_1, NX_FILL_2, NX_FILL_3, phantom_alloc_cds(), phantom_post_cds(), phantom_nic::port, UNM_TX_ETHER_PKT, and virt_to_bus().

01257                                                         {
01258         struct phantom_nic *phantom = netdev_priv ( netdev );
01259         union phantom_cds cds;
01260         int index;
01261 
01262         /* Get descriptor ring entry */
01263         index = phantom_alloc_cds ( phantom );
01264         if ( index < 0 )
01265                 return index;
01266 
01267         /* Fill descriptor ring entry */
01268         memset ( &cds, 0, sizeof ( cds ) );
01269         NX_FILL_3 ( &cds, 0,
01270                     tx.opcode, UNM_TX_ETHER_PKT,
01271                     tx.num_buffers, 1,
01272                     tx.length, iob_len ( iobuf ) );
01273         NX_FILL_2 ( &cds, 2,
01274                     tx.port, phantom->port,
01275                     tx.context_id, phantom->port );
01276         NX_FILL_1 ( &cds, 4,
01277                     tx.buffer1_dma_addr, virt_to_bus ( iobuf->data ) );
01278         NX_FILL_1 ( &cds, 5,
01279                     tx.buffer1_length, iob_len ( iobuf ) );
01280 
01281         /* Record I/O buffer */
01282         assert ( phantom->cds_iobuf[index] == NULL );
01283         phantom->cds_iobuf[index] = iobuf;
01284 
01285         /* Post descriptor */
01286         phantom_post_cds ( phantom, &cds );
01287 
01288         return 0;
01289 }

static void phantom_poll ( struct net_device netdev  )  [static]

Poll for received packets.

Parameters:
netdev Network device

Definition at line 1296 of file phantom.c.

References assert, phantom_nic::cds_consumer_idx, phantom_nic::cds_iobuf, phantom_descriptor_rings::cmd_cons, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, phantom_nic::desc, iob_pull, iob_put, le32_to_cpu, phantom_nic::link_poll_timer, memset(), netdev_priv(), netdev_rx(), netdev_tx_complete(), NULL, NX_GET, phantom_irq_status_reg, phantom_poll_link_state(), phantom_readl(), phantom_refill_rx_ring(), phantom_writel(), PHN_LINK_POLL_FREQUENCY, PHN_NUM_CDS, PHN_NUM_RDS, PHN_NUM_SDS, phantom_nic::port, phantom_nic::rds_consumer_idx, phantom_nic::rds_iobuf, phantom_descriptor_rings::sds, phantom_nic::sds_consumer_crb, phantom_nic::sds_consumer_idx, phantom_nic::sds_irq_enabled, UNM_PCIE_IRQ_STATE, UNM_PCIE_IRQ_STATE_TRIGGERED, UNM_PCIE_IRQ_STATUS_MAGIC, UNM_PCIE_IRQ_VECTOR, UNM_PCIE_IRQ_VECTOR_BIT, UNM_RXPKT_DESC, UNM_SYN_OFFLOAD, virt_to_bus(), and wmb.

01296                                                        {
01297         struct phantom_nic *phantom = netdev_priv ( netdev );
01298         struct io_buffer *iobuf;
01299         unsigned int irq_vector;
01300         unsigned int irq_state;
01301         unsigned int cds_consumer_idx;
01302         unsigned int raw_new_cds_consumer_idx;
01303         unsigned int new_cds_consumer_idx;
01304         unsigned int rds_consumer_idx;
01305         unsigned int sds_consumer_idx;
01306         struct phantom_sds *sds;
01307         unsigned int sds_handle;
01308         unsigned int sds_opcode;
01309 
01310         /* Occasionally poll the link state */
01311         if ( phantom->link_poll_timer-- == 0 ) {
01312                 phantom_poll_link_state ( netdev );
01313                 /* Reset the link poll timer */
01314                 phantom->link_poll_timer = PHN_LINK_POLL_FREQUENCY;
01315         }
01316 
01317         /* Check for interrupts */
01318         if ( phantom->sds_irq_enabled ) {
01319 
01320                 /* Do nothing unless an interrupt is asserted */
01321                 irq_vector = phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
01322                 if ( ! ( irq_vector & UNM_PCIE_IRQ_VECTOR_BIT( phantom->port )))
01323                         return;
01324 
01325                 /* Do nothing unless interrupt state machine has stabilised */
01326                 irq_state = phantom_readl ( phantom, UNM_PCIE_IRQ_STATE );
01327                 if ( ! UNM_PCIE_IRQ_STATE_TRIGGERED ( irq_state ) )
01328                         return;
01329 
01330                 /* Acknowledge interrupt */
01331                 phantom_writel ( phantom, UNM_PCIE_IRQ_STATUS_MAGIC,
01332                                  phantom_irq_status_reg[phantom->port] );
01333                 phantom_readl ( phantom, UNM_PCIE_IRQ_VECTOR );
01334         }
01335 
01336         /* Check for TX completions */
01337         cds_consumer_idx = phantom->cds_consumer_idx;
01338         raw_new_cds_consumer_idx = phantom->desc->cmd_cons;
01339         new_cds_consumer_idx = le32_to_cpu ( raw_new_cds_consumer_idx );
01340         while ( cds_consumer_idx != new_cds_consumer_idx ) {
01341                 DBGC2 ( phantom, "Phantom %p CDS %d complete\n",
01342                         phantom, cds_consumer_idx );
01343                 /* Completions may be for commands other than TX, so
01344                  * there may not always be an associated I/O buffer.
01345                  */
01346                 if ( ( iobuf = phantom->cds_iobuf[cds_consumer_idx] ) ) {
01347                         netdev_tx_complete ( netdev, iobuf );
01348                         phantom->cds_iobuf[cds_consumer_idx] = NULL;
01349                 }
01350                 cds_consumer_idx = ( ( cds_consumer_idx + 1 ) % PHN_NUM_CDS );
01351                 phantom->cds_consumer_idx = cds_consumer_idx;
01352         }
01353 
01354         /* Check for received packets */
01355         rds_consumer_idx = phantom->rds_consumer_idx;
01356         sds_consumer_idx = phantom->sds_consumer_idx;
01357         while ( 1 ) {
01358                 sds = &phantom->desc->sds[sds_consumer_idx];
01359                 if ( NX_GET ( sds, owner ) == 0 )
01360                         break;
01361 
01362                 DBGC2 ( phantom, "Phantom %p SDS %d status:\n",
01363                         phantom, sds_consumer_idx );
01364                 DBGC2_HDA ( phantom, virt_to_bus ( sds ), sds, sizeof (*sds) );
01365 
01366                 /* Check received opcode */
01367                 sds_opcode = NX_GET ( sds, opcode );
01368                 if ( ( sds_opcode == UNM_RXPKT_DESC ) ||
01369                      ( sds_opcode == UNM_SYN_OFFLOAD ) ) {
01370 
01371                         /* Sanity check: ensure that all of the SDS
01372                          * descriptor has been written.
01373                          */
01374                         if ( NX_GET ( sds, total_length ) == 0 ) {
01375                                 DBGC ( phantom, "Phantom %p SDS %d "
01376                                        "incomplete; deferring\n",
01377                                        phantom, sds_consumer_idx );
01378                                 /* Leave for next poll() */
01379                                 break;
01380                         }
01381 
01382                         /* Process received packet */
01383                         sds_handle = NX_GET ( sds, handle );
01384                         iobuf = phantom->rds_iobuf[sds_handle];
01385                         assert ( iobuf != NULL );
01386                         iob_put ( iobuf, NX_GET ( sds, total_length ) );
01387                         iob_pull ( iobuf, NX_GET ( sds, pkt_offset ) );
01388                         DBGC2 ( phantom, "Phantom %p RDS %d complete\n",
01389                                 phantom, sds_handle );
01390                         netdev_rx ( netdev, iobuf );
01391                         phantom->rds_iobuf[sds_handle] = NULL;
01392 
01393                         /* Update RDS consumer counter.  This is a
01394                          * lower bound for the number of descriptors
01395                          * that have been read by the hardware, since
01396                          * the hardware must have read at least one
01397                          * descriptor for each completion that we
01398                          * receive.
01399                          */
01400                         rds_consumer_idx =
01401                                 ( ( rds_consumer_idx + 1 ) % PHN_NUM_RDS );
01402                         phantom->rds_consumer_idx = rds_consumer_idx;
01403 
01404                 } else {
01405 
01406                         DBGC ( phantom, "Phantom %p unexpected SDS opcode "
01407                                "%02x\n", phantom, sds_opcode );
01408                         DBGC_HDA ( phantom, virt_to_bus ( sds ),
01409                                    sds, sizeof ( *sds ) );
01410                 }
01411                         
01412                 /* Clear status descriptor */
01413                 memset ( sds, 0, sizeof ( *sds ) );
01414 
01415                 /* Update SDS consumer index */
01416                 sds_consumer_idx = ( ( sds_consumer_idx + 1 ) % PHN_NUM_SDS );
01417                 phantom->sds_consumer_idx = sds_consumer_idx;
01418                 wmb();
01419                 phantom_writel ( phantom, phantom->sds_consumer_idx,
01420                                  phantom->sds_consumer_crb );
01421         }
01422 
01423         /* Refill the RX descriptor ring */
01424         phantom_refill_rx_ring ( netdev );
01425 }

static void phantom_irq ( struct net_device netdev,
int  enable 
) [static]

Enable/disable interrupts.

Parameters:
netdev Network device
enable Interrupts should be enabled

Definition at line 1433 of file phantom.c.

References netdev_priv(), phantom_irq_mask_reg, phantom_writel(), phantom_nic::port, phantom_nic::sds_irq_enabled, phantom_nic::sds_irq_mask_crb, and UNM_PCIE_IRQ_MASK_MAGIC.

01433                                                                   {
01434         struct phantom_nic *phantom = netdev_priv ( netdev );
01435 
01436         phantom_writel ( phantom, ( enable ? 1 : 0 ),
01437                          phantom->sds_irq_mask_crb );
01438         phantom_writel ( phantom, UNM_PCIE_IRQ_MASK_MAGIC,
01439                          phantom_irq_mask_reg[phantom->port] );
01440         phantom->sds_irq_enabled = enable;
01441 }

static int phantom_clp_wait ( struct phantom_nic phantom  )  [static]

Wait for Phantom CLP command to complete.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 1491 of file phantom.c.

References DBGC, ETIMEDOUT, mdelay(), phantom_readl(), PHN_CLP_CMD_TIMEOUT_MS, UNM_CAM_RAM_CLP_STATUS, and UNM_CAM_RAM_CLP_STATUS_DONE.

Referenced by phantom_clp_cmd().

01491                                                             {
01492         unsigned int retries;
01493         uint32_t status;
01494 
01495         for ( retries = 0 ; retries < PHN_CLP_CMD_TIMEOUT_MS ; retries++ ) {
01496                 status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS );
01497                 if ( status & UNM_CAM_RAM_CLP_STATUS_DONE )
01498                         return 0;
01499                 mdelay ( 1 );
01500         }
01501 
01502         DBGC ( phantom, "Phantom %p timed out waiting for CLP command\n",
01503                phantom );
01504         return -ETIMEDOUT;
01505 }

static int phantom_clp_cmd ( struct phantom_nic phantom,
unsigned int  port,
unsigned int  opcode,
const void *  data_in,
void *  data_out,
size_t  offset,
size_t  len 
) [static]

Issue Phantom CLP command.

Parameters:
phantom Phantom NIC
port Virtual port number
opcode Opcode
data_in Data in, or NULL
data_out Data out, or NULL
offset Offset within data
len Data buffer length
Return values:
len Total transfer length (for reads), or negative error

Definition at line 1519 of file phantom.c.

References assert, be32_to_cpu, phantom_clp_data::bytes, cpu_to_be32, DBGC, phantom_clp_data::dwords, EINVAL, EIO, phantom_clp_data::hi, index, phantom_clp_data::lo, mb(), memcpy, memset(), phantom_clp_wait(), phantom_readl(), phantom_writel(), UNM_CAM_RAM_CLP_COMMAND, UNM_CAM_RAM_CLP_DATA_HI, UNM_CAM_RAM_CLP_DATA_LO, UNM_CAM_RAM_CLP_STATUS, and UNM_CAM_RAM_CLP_STATUS_START.

Referenced by phantom_clp_fetch(), and phantom_clp_store().

01521                                                                          {
01522         union phantom_clp_data data;
01523         unsigned int index = ( offset / sizeof ( data ) );
01524         unsigned int last = 0;
01525         size_t in_frag_len;
01526         uint8_t *in_frag;
01527         uint32_t command;
01528         uint32_t status;
01529         size_t read_len;
01530         unsigned int error;
01531         size_t out_frag_len;
01532         uint8_t *out_frag;
01533         int rc;
01534 
01535         /* Sanity checks */
01536         assert ( ( offset % sizeof ( data ) ) == 0 );
01537         if ( len > 255 ) {
01538                 DBGC ( phantom, "Phantom %p invalid CLP length %zd\n",
01539                        phantom, len );
01540                 return -EINVAL;
01541         }
01542 
01543         /* Check that CLP interface is ready */
01544         if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 )
01545                 return rc;
01546 
01547         /* Copy data in */
01548         memset ( &data, 0, sizeof ( data ) );
01549         if ( data_in ) {
01550                 assert ( offset < len );
01551                 in_frag_len = ( len - offset );
01552                 if ( in_frag_len > sizeof ( data ) ) {
01553                         in_frag_len = sizeof ( data );
01554                 } else {
01555                         last = 1;
01556                 }
01557                 in_frag = &data.bytes[ sizeof ( data ) - in_frag_len ];
01558                 memcpy ( in_frag, ( data_in + offset ), in_frag_len );
01559                 phantom_writel ( phantom, be32_to_cpu ( data.dwords.lo ),
01560                                  UNM_CAM_RAM_CLP_DATA_LO );
01561                 phantom_writel ( phantom, be32_to_cpu ( data.dwords.hi ),
01562                                  UNM_CAM_RAM_CLP_DATA_HI );
01563         }
01564 
01565         /* Issue CLP command */
01566         command = ( ( index << 24 ) | ( ( data_in ? len : 0 ) << 16 ) |
01567                     ( port << 8 ) | ( last << 7 ) | ( opcode << 0 ) );
01568         phantom_writel ( phantom, command, UNM_CAM_RAM_CLP_COMMAND );
01569         mb();
01570         phantom_writel ( phantom, UNM_CAM_RAM_CLP_STATUS_START,
01571                          UNM_CAM_RAM_CLP_STATUS );
01572 
01573         /* Wait for command to complete */
01574         if ( ( rc = phantom_clp_wait ( phantom ) ) != 0 )
01575                 return rc;
01576 
01577         /* Get command status */
01578         status = phantom_readl ( phantom, UNM_CAM_RAM_CLP_STATUS );
01579         read_len = ( ( status >> 16 ) & 0xff );
01580         error = ( ( status >> 8 ) & 0xff );
01581         if ( error ) {
01582                 DBGC ( phantom, "Phantom %p CLP command error %02x\n",
01583                        phantom, error );
01584                 return -EIO;
01585         }
01586 
01587         /* Copy data out */
01588         if ( data_out ) {
01589                 data.dwords.lo = cpu_to_be32 ( phantom_readl ( phantom,
01590                                                   UNM_CAM_RAM_CLP_DATA_LO ) );
01591                 data.dwords.hi = cpu_to_be32 ( phantom_readl ( phantom,
01592                                                   UNM_CAM_RAM_CLP_DATA_HI ) );
01593                 out_frag_len = ( read_len - offset );
01594                 if ( out_frag_len > sizeof ( data ) )
01595                         out_frag_len = sizeof ( data );
01596                 out_frag = &data.bytes[ sizeof ( data ) - out_frag_len ];
01597                 if ( out_frag_len > ( len - offset ) )
01598                         out_frag_len = ( len - offset );
01599                 memcpy ( ( data_out + offset ), out_frag, out_frag_len );
01600         }
01601 
01602         return read_len;
01603 }

static int phantom_clp_store ( struct phantom_nic phantom,
unsigned int  port,
unsigned int  setting,
const void *  data,
size_t  len 
) [static]

Store Phantom CLP setting.

Parameters:
phantom Phantom NIC
port Virtual port number
setting Setting number
data Data buffer
len Length of data buffer
Return values:
rc Return status code

Definition at line 1615 of file phantom.c.

References NULL, offset, phantom_clp_cmd(), and PHN_CLP_BLKSIZE.

Referenced by phantom_store_setting().

01617                                             {
01618         unsigned int opcode = setting;
01619         size_t offset;
01620         int rc;
01621 
01622         for ( offset = 0 ; offset < len ; offset += PHN_CLP_BLKSIZE ) {
01623                 if ( ( rc = phantom_clp_cmd ( phantom, port, opcode, data,
01624                                               NULL, offset, len ) ) < 0 )
01625                         return rc;
01626         }
01627         return 0;
01628 }

static int phantom_clp_fetch ( struct phantom_nic phantom,
unsigned int  port,
unsigned int  setting,
void *  data,
size_t  len 
) [static]

Fetch Phantom CLP setting.

Parameters:
phantom Phantom NIC
port Virtual port number
setting Setting number
data Data buffer
len Length of data buffer
Return values:
len Length of setting, or negative error

Definition at line 1640 of file phantom.c.

References NULL, offset, phantom_clp_cmd(), and PHN_CLP_BLKSIZE.

Referenced by phantom_fetch_setting().

01641                                                                               {
01642         unsigned int opcode = ( setting + 1 );
01643         size_t offset = 0;
01644         int read_len;
01645 
01646         while ( 1 ) {
01647                 read_len = phantom_clp_cmd ( phantom, port, opcode, NULL,
01648                                              data, offset, len );
01649                 if ( read_len < 0 )
01650                         return read_len;
01651                 offset += PHN_CLP_BLKSIZE;
01652                 if ( offset >= ( unsigned ) read_len )
01653                         break;
01654                 if ( offset >= len )
01655                         break;
01656         }
01657         return read_len;
01658 }

static unsigned int phantom_clp_setting ( struct phantom_nic phantom,
struct setting setting 
) [static]

Find Phantom CLP setting.

Parameters:
setting gPXE setting
clp_setting Setting number, or 0 if not found

Definition at line 1680 of file phantom.c.

References phantom_clp_setting::clp_setting, DBGC2, setting::name, PHN_CLP_TAG_MAGIC, PHN_CLP_TAG_MAGIC_MASK, phantom_clp_setting::setting, setting_cmp(), and setting::tag.

Referenced by phantom_fetch_setting(), and phantom_store_setting().

01680                                                                              {
01681         struct phantom_clp_setting *clp_setting;
01682         unsigned int i;
01683 
01684         /* Search the list of explicitly-defined settings */
01685         for ( i = 0 ; i < ( sizeof ( clp_settings ) /
01686                             sizeof ( clp_settings[0] ) ) ; i++ ) {
01687                 clp_setting = &clp_settings[i];
01688                 if ( setting_cmp ( setting, clp_setting->setting ) == 0 )
01689                         return clp_setting->clp_setting;
01690         }
01691 
01692         /* Allow for use of numbered settings */
01693         if ( ( setting->tag & PHN_CLP_TAG_MAGIC_MASK ) == PHN_CLP_TAG_MAGIC )
01694                 return ( setting->tag & ~PHN_CLP_TAG_MAGIC_MASK );
01695 
01696         DBGC2 ( phantom, "Phantom %p has no \"%s\" setting\n",
01697                 phantom, setting->name );
01698 
01699         return 0;
01700 }

static int phantom_store_setting ( struct settings settings,
struct setting setting,
const void *  data,
size_t  len 
) [static]

Store Phantom CLP setting.

Parameters:
settings Settings block
setting Setting to store
data Setting data, or NULL to clear setting
len Length of setting data
Return values:
rc Return status code

Definition at line 1711 of file phantom.c.

References container_of, DBGC, ENOTSUP, setting::name, phantom_clp_setting(), phantom_clp_store(), phantom_nic::port, and strerror().

01713                                                                   {
01714         struct phantom_nic *phantom =
01715                 container_of ( settings, struct phantom_nic, settings );
01716         unsigned int clp_setting;
01717         int rc;
01718 
01719         /* Find Phantom setting equivalent to gPXE setting */
01720         clp_setting = phantom_clp_setting ( phantom, setting );
01721         if ( ! clp_setting )
01722                 return -ENOTSUP;
01723 
01724         /* Store setting */
01725         if ( ( rc = phantom_clp_store ( phantom, phantom->port,
01726                                         clp_setting, data, len ) ) != 0 ) {
01727                 DBGC ( phantom, "Phantom %p could not store setting \"%s\": "
01728                        "%s\n", phantom, setting->name, strerror ( rc ) );
01729                 return rc;
01730         }
01731 
01732         return 0;
01733 }

static int phantom_fetch_setting ( struct settings settings,
struct setting setting,
void *  data,
size_t  len 
) [static]

Fetch Phantom CLP setting.

Parameters:
settings Settings block
setting Setting to fetch
data Buffer to fill with setting data
len Length of buffer
Return values:
len Length of setting data, or negative error

Definition at line 1744 of file phantom.c.

References container_of, DBGC, ENOTSUP, setting::name, phantom_clp_fetch(), phantom_clp_setting(), phantom_nic::port, and strerror().

01746                                                             {
01747         struct phantom_nic *phantom =
01748                 container_of ( settings, struct phantom_nic, settings );
01749         unsigned int clp_setting;
01750         int read_len;
01751         int rc;
01752 
01753         /* Find Phantom setting equivalent to gPXE setting */
01754         clp_setting = phantom_clp_setting ( phantom, setting );
01755         if ( ! clp_setting )
01756                 return -ENOTSUP;
01757 
01758         /* Fetch setting */
01759         if ( ( read_len = phantom_clp_fetch ( phantom, phantom->port,
01760                                               clp_setting, data, len ) ) < 0 ){
01761                 rc = read_len;
01762                 DBGC ( phantom, "Phantom %p could not fetch setting \"%s\": "
01763                        "%s\n", phantom, setting->name, strerror ( rc ) );
01764                 return rc;
01765         }
01766 
01767         return read_len;
01768 }

static int phantom_map_crb ( struct phantom_nic phantom,
struct pci_device pci 
) [static]

Map Phantom CRB window.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 1788 of file phantom.c.

References phantom_nic::bar0, pci_device::bus, phantom_nic::crb_access, phantom_nic::crb_window, DBGC, pci_device::devfn, EINVAL, EIO, ioremap(), pci_bar_size(), pci_bar_start(), PCI_BASE_ADDRESS_0, PCI_FUNC, PCI_SLOT, phantom_crb_access_128m(), phantom_crb_access_2m(), and phantom_crb_access_32m().

Referenced by phantom_probe().

01789                                                       {
01790         unsigned long bar0_start;
01791         unsigned long bar0_size;
01792 
01793         bar0_start = pci_bar_start ( pci, PCI_BASE_ADDRESS_0 );
01794         bar0_size = pci_bar_size ( pci, PCI_BASE_ADDRESS_0 );
01795         DBGC ( phantom, "Phantom %p is PCI %02x:%02x.%x with BAR0 at "
01796                "%08lx+%lx\n", phantom, pci->bus, PCI_SLOT ( pci->devfn ),
01797                PCI_FUNC ( pci->devfn ), bar0_start, bar0_size );
01798 
01799         if ( ! bar0_start ) {
01800                 DBGC ( phantom, "Phantom %p BAR not assigned; ignoring\n",
01801                        phantom );
01802                 return -EINVAL;
01803         }
01804 
01805         switch ( bar0_size ) {
01806         case ( 128 * 1024 * 1024 ) :
01807                 DBGC ( phantom, "Phantom %p has 128MB BAR\n", phantom );
01808                 phantom->crb_access = phantom_crb_access_128m;
01809                 break;
01810         case ( 32 * 1024 * 1024 ) :
01811                 DBGC ( phantom, "Phantom %p has 32MB BAR\n", phantom );
01812                 phantom->crb_access = phantom_crb_access_32m;
01813                 break;
01814         case ( 2 * 1024 * 1024 ) :
01815                 DBGC ( phantom, "Phantom %p has 2MB BAR\n", phantom );
01816                 phantom->crb_access = phantom_crb_access_2m;
01817                 break;
01818         default:
01819                 DBGC ( phantom, "Phantom %p has bad BAR size\n", phantom );
01820                 return -EINVAL;
01821         }
01822 
01823         phantom->bar0 = ioremap ( bar0_start, bar0_size );
01824         if ( ! phantom->bar0 ) {
01825                 DBGC ( phantom, "Phantom %p could not map BAR0\n", phantom );
01826                 return -EIO;
01827         }
01828 
01829         /* Mark current CRB window as invalid, so that the first
01830          * read/write will set the current window.
01831          */
01832         phantom->crb_window = -1UL;
01833 
01834         return 0;
01835 }

static void phantom_unhalt_pegs ( struct phantom_nic phantom  )  [static]

Unhalt all PEGs.

Parameters:
phantom Phantom NIC

Definition at line 1842 of file phantom.c.

References phantom_readl(), phantom_writel(), UNM_PEG_0_HALT_STATUS, UNM_PEG_1_HALT_STATUS, UNM_PEG_2_HALT_STATUS, UNM_PEG_3_HALT_STATUS, and UNM_PEG_4_HALT_STATUS.

Referenced by phantom_init_cmdpeg().

01842                                                                 {
01843         uint32_t halt_status;
01844 
01845         halt_status = phantom_readl ( phantom, UNM_PEG_0_HALT_STATUS );
01846         phantom_writel ( phantom, halt_status, UNM_PEG_0_HALT_STATUS );
01847         halt_status = phantom_readl ( phantom, UNM_PEG_1_HALT_STATUS );
01848         phantom_writel ( phantom, halt_status, UNM_PEG_1_HALT_STATUS );
01849         halt_status = phantom_readl ( phantom, UNM_PEG_2_HALT_STATUS );
01850         phantom_writel ( phantom, halt_status, UNM_PEG_2_HALT_STATUS );
01851         halt_status = phantom_readl ( phantom, UNM_PEG_3_HALT_STATUS );
01852         phantom_writel ( phantom, halt_status, UNM_PEG_3_HALT_STATUS );
01853         halt_status = phantom_readl ( phantom, UNM_PEG_4_HALT_STATUS );
01854         phantom_writel ( phantom, halt_status, UNM_PEG_4_HALT_STATUS );
01855 }

static int phantom_init_cmdpeg ( struct phantom_nic phantom  )  [static]

Initialise the Phantom command PEG.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 1863 of file phantom.c.

References DBGC, EIO, ETIMEDOUT, mdelay(), phantom_readl(), phantom_unhalt_pegs(), phantom_write_hilo(), phantom_writel(), PHN_CMDPEG_INIT_TIMEOUT_SEC, UNM_CAM_RAM_COLD_BOOT, UNM_CAM_RAM_COLD_BOOT_MAGIC, UNM_CAM_RAM_PORT_MODE_AUTO_NEG_1G, UNM_CAM_RAM_WOL_PORT_MODE, UNM_NIC_REG_CMDPEG_STATE, UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK, UNM_NIC_REG_CMDPEG_STATE_INITIALIZED, UNM_NIC_REG_DUMMY_BUF, UNM_NIC_REG_DUMMY_BUF_ADDR_HI, UNM_NIC_REG_DUMMY_BUF_ADDR_LO, UNM_NIC_REG_DUMMY_BUF_INIT, UNM_ROMUSB_GLB_PEGTUNE_DONE, UNM_ROMUSB_GLB_PEGTUNE_DONE_MAGIC, UNM_ROMUSB_GLB_SW_RESET, and UNM_ROMUSB_GLB_SW_RESET_MAGIC.

Referenced by phantom_probe().

01863                                                                {
01864         uint32_t cold_boot;
01865         uint32_t sw_reset;
01866         unsigned int retries;
01867         uint32_t cmdpeg_state;
01868         uint32_t last_cmdpeg_state = 0;
01869 
01870         /* Check for a previous initialisation.  This could have
01871          * happened if, for example, the BIOS used the UNDI API to
01872          * drive the NIC prior to a full PXE boot.
01873          */
01874         cmdpeg_state = phantom_readl ( phantom, UNM_NIC_REG_CMDPEG_STATE );
01875         if ( cmdpeg_state == UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK ) {
01876                 DBGC ( phantom, "Phantom %p command PEG already initialized\n",
01877                        phantom );
01878                 /* Unhalt the PEGs.  Previous firmware (e.g. BOFM) may
01879                  * have halted the PEGs to prevent internal bus
01880                  * collisions when the BIOS re-reads the expansion ROM.
01881                  */
01882                 phantom_unhalt_pegs ( phantom );
01883                 return 0;
01884         }
01885 
01886         /* If this was a cold boot, check that the hardware came up ok */
01887         cold_boot = phantom_readl ( phantom, UNM_CAM_RAM_COLD_BOOT );
01888         if ( cold_boot == UNM_CAM_RAM_COLD_BOOT_MAGIC ) {
01889                 DBGC ( phantom, "Phantom %p coming up from cold boot\n",
01890                        phantom );
01891                 sw_reset = phantom_readl ( phantom, UNM_ROMUSB_GLB_SW_RESET );
01892                 if ( sw_reset != UNM_ROMUSB_GLB_SW_RESET_MAGIC ) {
01893                         DBGC ( phantom, "Phantom %p reset failed: %08x\n",
01894                                phantom, sw_reset );
01895                         return -EIO;
01896                 }
01897         } else {
01898                 DBGC ( phantom, "Phantom %p coming up from warm boot "
01899                        "(%08x)\n", phantom, cold_boot );
01900         }
01901         /* Clear cold-boot flag */
01902         phantom_writel ( phantom, 0, UNM_CAM_RAM_COLD_BOOT );
01903 
01904         /* Set port modes */
01905         phantom_writel ( phantom, UNM_CAM_RAM_PORT_MODE_AUTO_NEG_1G,
01906                          UNM_CAM_RAM_WOL_PORT_MODE );
01907 
01908         /* Pass dummy DMA area to card */
01909         phantom_write_hilo ( phantom, 0,
01910                              UNM_NIC_REG_DUMMY_BUF_ADDR_LO,
01911                              UNM_NIC_REG_DUMMY_BUF_ADDR_HI );
01912         phantom_writel ( phantom, UNM_NIC_REG_DUMMY_BUF_INIT,
01913                          UNM_NIC_REG_DUMMY_BUF );
01914 
01915         /* Tell the hardware that tuning is complete */
01916         phantom_writel ( phantom, UNM_ROMUSB_GLB_PEGTUNE_DONE_MAGIC,
01917                          UNM_ROMUSB_GLB_PEGTUNE_DONE );
01918 
01919         /* Wait for command PEG to finish initialising */
01920         DBGC ( phantom, "Phantom %p initialising command PEG (will take up to "
01921                "%d seconds)...\n", phantom, PHN_CMDPEG_INIT_TIMEOUT_SEC );
01922         for ( retries = 0; retries < PHN_CMDPEG_INIT_TIMEOUT_SEC; retries++ ) {
01923                 cmdpeg_state = phantom_readl ( phantom,
01924                                                UNM_NIC_REG_CMDPEG_STATE );
01925                 if ( cmdpeg_state != last_cmdpeg_state ) {
01926                         DBGC ( phantom, "Phantom %p command PEG state is "
01927                                "%08x after %d seconds...\n",
01928                                phantom, cmdpeg_state, retries );
01929                         last_cmdpeg_state = cmdpeg_state;
01930                 }
01931                 if ( cmdpeg_state == UNM_NIC_REG_CMDPEG_STATE_INITIALIZED ) {
01932                         /* Acknowledge the PEG initialisation */
01933                         phantom_writel ( phantom,
01934                                        UNM_NIC_REG_CMDPEG_STATE_INITIALIZE_ACK,
01935                                        UNM_NIC_REG_CMDPEG_STATE );
01936                         return 0;
01937                 }
01938                 mdelay ( 1000 );
01939         }
01940 
01941         DBGC ( phantom, "Phantom %p timed out waiting for command PEG to "
01942                "initialise (status %08x)\n", phantom, cmdpeg_state );
01943         return -ETIMEDOUT;
01944 }

static void phantom_get_macaddr ( struct phantom_nic phantom,
uint8_t hw_addr 
) [static]

Read Phantom MAC address.

Parameters:
phanton_port Phantom NIC
hw_addr Buffer to fill with MAC address

Definition at line 1952 of file phantom.c.

References DBGC, ETH_ALEN, eth_ntoa(), offset, phantom_readl(), phantom_nic::port, and UNM_CAM_RAM_MAC_ADDRS.

Referenced by phantom_probe().

01953                                                      {
01954         union {
01955                 uint8_t mac_addr[2][ETH_ALEN];
01956                 uint32_t dwords[3];
01957         } u;
01958         unsigned long offset;
01959         int i;
01960 
01961         /* Read the three dwords that include this MAC address and one other */
01962         offset = ( UNM_CAM_RAM_MAC_ADDRS +
01963                    ( 12 * ( phantom->port / 2 ) ) );
01964         for ( i = 0 ; i < 3 ; i++, offset += 4 ) {
01965                 u.dwords[i] = phantom_readl ( phantom, offset );
01966         }
01967 
01968         /* Copy out the relevant MAC address */
01969         for ( i = 0 ; i < ETH_ALEN ; i++ ) {
01970                 hw_addr[ ETH_ALEN - i - 1 ] =
01971                         u.mac_addr[ phantom->port & 1 ][i];
01972         }
01973         DBGC ( phantom, "Phantom %p MAC address is %s\n",
01974                phantom, eth_ntoa ( hw_addr ) );
01975 }

static int phantom_check_boot_enable ( struct phantom_nic phantom  )  [static]

Check Phantom is enabled for boot.

Parameters:
phanton_port Phantom NIC
Return values:
rc Return status code
This is something of an ugly hack to accommodate an OEM requirement. The NIC has only one expansion ROM BAR, rather than one per port. To allow individual ports to be selectively enabled/disabled for PXE boot (as required), we must therefore leave the expansion ROM always enabled, and place the per-port enable/disable logic within the gPXE driver.

Definition at line 1990 of file phantom.c.

References DBGC, ENOTSUP, phantom_readl(), phantom_nic::port, and UNM_CAM_RAM_BOOT_ENABLE.

Referenced by phantom_probe().

01990                                                                      {
01991         unsigned long boot_enable;
01992 
01993         boot_enable = phantom_readl ( phantom, UNM_CAM_RAM_BOOT_ENABLE );
01994         if ( ! ( boot_enable & ( 1 << phantom->port ) ) ) {
01995                 DBGC ( phantom, "Phantom %p PXE boot is disabled\n",
01996                        phantom );
01997                 return -ENOTSUP;
01998         }
01999 
02000         return 0;
02001 }

static int phantom_init_rcvpeg ( struct phantom_nic phantom  )  [static]

Initialise Phantom receive PEG.

Parameters:
phantom Phantom NIC
Return values:
rc Return status code

Definition at line 2009 of file phantom.c.

References DBGC, ETIMEDOUT, mdelay(), phantom_readl(), PHN_RCVPEG_INIT_TIMEOUT_SEC, UNM_NIC_REG_RCVPEG_STATE, and UNM_NIC_REG_RCVPEG_STATE_INITIALIZED.

Referenced by phantom_probe().

02009                                                                {
02010         unsigned int retries;
02011         uint32_t rcvpeg_state;
02012         uint32_t last_rcvpeg_state = 0;
02013 
02014         DBGC ( phantom, "Phantom %p initialising receive PEG (will take up to "
02015                "%d seconds)...\n", phantom, PHN_RCVPEG_INIT_TIMEOUT_SEC );
02016         for ( retries = 0; retries < PHN_RCVPEG_INIT_TIMEOUT_SEC; retries++ ) {
02017                 rcvpeg_state = phantom_readl ( phantom,
02018                                                UNM_NIC_REG_RCVPEG_STATE );
02019                 if ( rcvpeg_state != last_rcvpeg_state ) {
02020                         DBGC ( phantom, "Phantom %p receive PEG state is "
02021                                "%08x after %d seconds...\n",
02022                                phantom, rcvpeg_state, retries );
02023                         last_rcvpeg_state = rcvpeg_state;
02024                 }
02025                 if ( rcvpeg_state == UNM_NIC_REG_RCVPEG_STATE_INITIALIZED )
02026                         return 0;
02027                 mdelay ( 1000 );
02028         }
02029 
02030         DBGC ( phantom, "Phantom %p timed out waiting for receive PEG to "
02031                "initialise (status %08x)\n", phantom, rcvpeg_state );
02032         return -ETIMEDOUT;
02033 }

static int phantom_probe ( struct pci_device pci,
const struct pci_device_id *id  __unused 
) [static]

Probe PCI device.

Parameters:
pci PCI device
id PCI ID
Return values:
rc Return status code

Definition at line 2042 of file phantom.c.

References adjust_pci_device(), alloc_etherdev(), assert, DBGC, pci_device::dev, net_device::dev, pci_device::devfn, ENOMEM, net_device::hw_addr, memset(), netdev, netdev_init(), netdev_nullify(), netdev_priv(), netdev_put(), netdev_settings(), PCI_DEVFN, PCI_FUNC, pci_read_config_dword(), pci_set_drvdata(), PCI_SLOT, pci_write_config_dword(), phantom_check_boot_enable(), phantom_get_macaddr(), phantom_init_cmdpeg(), phantom_init_rcvpeg(), phantom_map_crb(), PHN_CLP_TAG_MAGIC, PHN_MAX_NUM_PORTS, phantom_nic::port, net_device::refcnt, register_netdev(), register_settings(), phantom_nic::settings, settings_init(), strerror(), unregister_netdev(), and unregister_settings().

02043                                                                      {
02044         struct net_device *netdev;
02045         struct phantom_nic *phantom;
02046         struct settings *parent_settings;
02047         int rc;
02048 
02049         /* Allocate Phantom device */
02050         netdev = alloc_etherdev ( sizeof ( *phantom ) );
02051         if ( ! netdev ) {
02052                 rc = -ENOMEM;
02053                 goto err_alloc_etherdev;
02054         }
02055         netdev_init ( netdev, &phantom_operations );
02056         phantom = netdev_priv ( netdev );
02057         pci_set_drvdata ( pci, netdev );
02058         netdev->dev = &pci->dev;
02059         memset ( phantom, 0, sizeof ( *phantom ) );
02060         phantom->port = PCI_FUNC ( pci->devfn );
02061         assert ( phantom->port < PHN_MAX_NUM_PORTS );
02062         settings_init ( &phantom->settings,
02063                         &phantom_settings_operations,
02064                         &netdev->refcnt, "clp", PHN_CLP_TAG_MAGIC );
02065 
02066         /* Fix up PCI device */
02067         adjust_pci_device ( pci );
02068 
02069         /* Map CRB */
02070         if ( ( rc = phantom_map_crb ( phantom, pci ) ) != 0 )
02071                 goto err_map_crb;
02072 
02073         /* BUG5945 - need to hack PCI config space on P3 B1 silicon.
02074          * B2 will have this fixed; remove this hack when B1 is no
02075          * longer in use.
02076          */
02077         if ( PCI_FUNC ( pci->devfn ) == 0 ) {
02078                 unsigned int i;
02079                 for ( i = 0 ; i < 8 ; i++ ) {
02080                         uint32_t temp;
02081                         pci->devfn = PCI_DEVFN ( PCI_SLOT ( pci->devfn ), i );
02082                         pci_read_config_dword ( pci, 0xc8, &temp );
02083                         pci_read_config_dword ( pci, 0xc8, &temp );
02084                         pci_write_config_dword ( pci, 0xc8, 0xf1000 );
02085                 }
02086                 pci->devfn = PCI_DEVFN ( PCI_SLOT ( pci->devfn ), 0 );
02087         }
02088 
02089         /* Initialise the command PEG */
02090         if ( ( rc = phantom_init_cmdpeg ( phantom ) ) != 0 )
02091                 goto err_init_cmdpeg;
02092 
02093         /* Initialise the receive PEG */
02094         if ( ( rc = phantom_init_rcvpeg ( phantom ) ) != 0 )
02095                 goto err_init_rcvpeg;
02096 
02097         /* Read MAC addresses */
02098         phantom_get_macaddr ( phantom, netdev->hw_addr );
02099 
02100         /* Skip if boot disabled on NIC */
02101         if ( ( rc = phantom_check_boot_enable ( phantom ) ) != 0 )
02102                 goto err_check_boot_enable;
02103 
02104         /* Register network devices */
02105         if ( ( rc = register_netdev ( netdev ) ) != 0 ) {
02106                 DBGC ( phantom, "Phantom %p could not register net device: "
02107                        "%s\n", phantom, strerror ( rc ) );
02108                 goto err_register_netdev;
02109         }
02110 
02111         /* Register settings blocks */
02112         parent_settings = netdev_settings ( netdev );
02113         if ( ( rc = register_settings ( &phantom->settings,
02114                                         parent_settings ) ) != 0 ) {
02115                 DBGC ( phantom, "Phantom %p could not register settings: "
02116                        "%s\n", phantom, strerror ( rc ) );
02117                 goto err_register_settings;
02118         }
02119 
02120         return 0;
02121 
02122         unregister_settings ( &phantom->settings );
02123  err_register_settings:
02124         unregister_netdev ( netdev );
02125  err_register_netdev:
02126  err_check_boot_enable:
02127  err_init_rcvpeg:
02128  err_init_cmdpeg:
02129  err_map_crb:
02130         netdev_nullify ( netdev );
02131         netdev_put ( netdev );
02132  err_alloc_etherdev:
02133         return rc;
02134 }

static void phantom_remove ( struct pci_device pci  )  [static]

Remove PCI device.

Parameters:
pci PCI device

Definition at line 2141 of file phantom.c.

References netdev, netdev_nullify(), netdev_priv(), netdev_put(), pci_get_drvdata(), phantom_nic::settings, unregister_netdev(), and unregister_settings().

02141                                                       {
02142         struct net_device *netdev = pci_get_drvdata ( pci );
02143         struct phantom_nic *phantom = netdev_priv ( netdev );
02144 
02145         unregister_settings ( &phantom->settings );
02146         unregister_netdev ( netdev );
02147         netdev_nullify ( netdev );
02148         netdev_put ( netdev );
02149 }


Variable Documentation

const unsigned long phantom_irq_mask_reg[PHN_MAX_NUM_PORTS] [static]

const unsigned long phantom_irq_status_reg[PHN_MAX_NUM_PORTS] [static]

Initial value:

 {
        .open           = phantom_open,
        .close          = phantom_close,
        .transmit       = phantom_transmit,
        .poll           = phantom_poll,
        .irq            = phantom_irq,
}
Phantom net device operations.

Definition at line 1444 of file phantom.c.

struct phantom_clp_setting clp_settings[] [static]

Initial value:

 {
        { &mac_setting, 0x01 },
}
Phantom CLP settings.

Definition at line 1669 of file phantom.c.

Initial value:

Phantom CLP settings operations.

Definition at line 1771 of file phantom.c.

struct pci_device_id phantom_nics[] [static]

Initial value:

 {
        PCI_ROM ( 0x4040, 0x0100, "nx", "NX", 0 ),
}
Phantom PCI IDs.

Definition at line 2152 of file phantom.c.

struct pci_driver phantom_driver __pci_driver

Initial value:

 {
        .ids = phantom_nics,
        .id_count = ( sizeof ( phantom_nics ) / sizeof ( phantom_nics[0] ) ),
        .probe = phantom_probe,
        .remove = phantom_remove,
}
Phantom PCI driver.

Definition at line 2157 of file phantom.c.


Generated on Tue Apr 6 20:01:37 2010 for gPXE by  doxygen 1.5.7.1