iPXE
Functions | Variables
axge.c File Reference

Asix 10/100/1000 USB Ethernet driver. More...

#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <ipxe/netdevice.h>
#include <ipxe/ethernet.h>
#include <ipxe/if_ether.h>
#include <ipxe/profile.h>
#include <ipxe/usb.h>
#include "axge.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int axge_read_register (struct axge_device *axge, unsigned int offset, void *data, size_t len)
 Read register.
static int axge_read_byte (struct axge_device *axge, unsigned int offset, uint8_t *value)
 Read one-byte register.
static int axge_read_word (struct axge_device *axge, unsigned int offset, uint16_t *value)
 Read two-byte register.
static int axge_read_dword (struct axge_device *axge, unsigned int offset, uint32_t *value)
 Read four-byte register.
static int axge_write_register (struct axge_device *axge, unsigned int offset, void *data, size_t len)
 Write register.
static int axge_write_byte (struct axge_device *axge, unsigned int offset, uint8_t value)
 Write one-byte register.
static int axge_write_word (struct axge_device *axge, unsigned int offset, uint16_t value)
 Write two-byte register.
static int axge_write_dword (struct axge_device *axge, unsigned int offset, uint32_t value)
 Write one-byte register.
static int axge_check_link (struct axge_device *axge)
 Get link status.
static void axge_intr_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete interrupt transfer.
static void axge_in_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete bulk IN transfer.
static int axge_out_transmit (struct axge_device *axge, struct io_buffer *iobuf)
 Transmit packet.
static void axge_out_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete bulk OUT transfer.
static int axge_open (struct net_device *netdev)
 Open network device.
static void axge_close (struct net_device *netdev)
 Close network device.
static int axge_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void axge_poll (struct net_device *netdev)
 Poll for completed and received packets.
static int axge_probe (struct usb_function *func, struct usb_configuration_descriptor *config)
 Probe device.
static void axge_remove (struct usb_function *func)
 Remove device.

Variables

static struct profiler
axge_intr_profiler 
__profiler
 Interrupt completion profiler.
static struct axge_bulk_in_control axge_bicr
 Default bulk IN configuration.
static struct
usb_endpoint_driver_operations 
axge_intr_operations
 Interrupt endpoint operations.
static struct
usb_endpoint_driver_operations 
axge_in_operations
 Bulk IN endpoint operations.
static struct
usb_endpoint_driver_operations 
axge_out_operations
 Bulk OUT endpoint operations.
static struct net_device_operations axge_operations
 AXGE network device operations.
static struct usb_device_id axge_ids []
 AXGE device IDs.
struct usb_driver axge_driver __usb_driver
 AXGE driver.

Detailed Description

Asix 10/100/1000 USB Ethernet driver.

Large chunks of functionality are undocumented in the available datasheets. The gaps are deduced from combinations of the Linux driver, the FreeBSD driver, and experimentation with the hardware.

Definition in file axge.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int axge_read_register ( struct axge_device axge,
unsigned int  offset,
void *  data,
size_t  len 
) [inline, static]

Read register.

Parameters:
asixAXGE device
offsetRegister offset
dataData buffer
lenLength of data
Return values:
rcReturn status code

Definition at line 91 of file axge.c.

References AXGE_READ_MAC_REGISTER, axge_device::usb, and usb_control().

Referenced by axge_probe(), axge_read_byte(), axge_read_dword(), and axge_read_word().

                                                    {

        return usb_control ( axge->usb, AXGE_READ_MAC_REGISTER,
                             offset, len, data, len );
}
static int axge_read_byte ( struct axge_device axge,
unsigned int  offset,
uint8_t value 
) [inline, static]

Read one-byte register.

Parameters:
asixAXGE device
offsetRegister offset
valueValue to fill in
Return values:
rcReturn status code

Definition at line 107 of file axge.c.

References axge_read_register().

Referenced by axge_check_link().

                                                                         {

        return axge_read_register ( axge, offset, value, sizeof ( *value ) );
}
static int axge_read_word ( struct axge_device axge,
unsigned int  offset,
uint16_t value 
) [inline, static]

Read two-byte register.

Parameters:
asixAXGE device
offsetRegister offset
valueValue to fill in
Return values:
rcReturn status code

Definition at line 121 of file axge.c.

References axge_read_register().

                                                                          {

        return axge_read_register ( axge, offset, value, sizeof ( *value ) );
}
static int axge_read_dword ( struct axge_device axge,
unsigned int  offset,
uint32_t value 
) [inline, static]

Read four-byte register.

Parameters:
asixAXGE device
offsetRegister offset
valueValue to fill in
Return values:
rcReturn status code

Definition at line 135 of file axge.c.

References axge_read_register().

                                                                           {

        return axge_read_register ( axge, offset, value, sizeof ( *value ) );
}
static int axge_write_register ( struct axge_device axge,
unsigned int  offset,
void *  data,
size_t  len 
) [inline, static]

Write register.

Parameters:
asixAXGE device
offsetRegister offset
dataData buffer
lenLength of data
Return values:
rcReturn status code

Definition at line 150 of file axge.c.

References AXGE_WRITE_MAC_REGISTER, axge_device::usb, and usb_control().

Referenced by axge_open(), axge_probe(), axge_write_byte(), axge_write_dword(), and axge_write_word().

static int axge_write_byte ( struct axge_device axge,
unsigned int  offset,
uint8_t  value 
) [inline, static]

Write one-byte register.

Parameters:
asixAXGE device
offsetRegister offset
valueValue
Return values:
rcReturn status code

Definition at line 166 of file axge.c.

References axge_write_register().

Referenced by axge_probe().

                                                                         {

        return axge_write_register ( axge, offset, &value, sizeof ( value ));
}
static int axge_write_word ( struct axge_device axge,
unsigned int  offset,
uint16_t  value 
) [inline, static]

Write two-byte register.

Parameters:
asixAXGE device
offsetRegister offset
valueValue
Return values:
rcReturn status code

Definition at line 180 of file axge.c.

References axge_write_register().

Referenced by axge_close(), axge_open(), and axge_probe().

                                                                          {

        return axge_write_register ( axge, offset, &value, sizeof ( value ));
}
static int axge_write_dword ( struct axge_device axge,
unsigned int  offset,
uint32_t  value 
) [inline, static]

Write one-byte register.

Parameters:
asixAXGE device
offsetRegister offset
valueValue
Return values:
rcReturn status code

Definition at line 194 of file axge.c.

References axge_write_register().

                                                                           {

        return axge_write_register ( axge, offset, &value, sizeof ( value ));
}
static int axge_check_link ( struct axge_device axge) [static]

Get link status.

Parameters:
asixAXGE device
Return values:
rcReturn status code

Definition at line 213 of file axge.c.

References AXGE_PLSR, AXGE_PLSR_EPHY_ANY, axge_read_byte(), DBGC, netdev, axge_device::netdev, netdev_link_down(), netdev_link_up(), rc, and strerror().

Referenced by axge_open(), and axge_probe().

                                                        {
        struct net_device *netdev = axge->netdev;
        uint8_t plsr;
        int rc;

        /* Read physical link status register */
        if ( ( rc = axge_read_byte ( axge, AXGE_PLSR, &plsr ) ) != 0 ) {
                DBGC ( axge, "AXGE %p could not read PLSR: %s\n",
                       axge, strerror ( rc ) );
                return rc;
        }

        /* Update link status */
        if ( plsr & AXGE_PLSR_EPHY_ANY ) {
                DBGC ( axge, "AXGE %p link up (PLSR %02x)\n", axge, plsr );
                netdev_link_up ( netdev );
        } else {
                DBGC ( axge, "AXGE %p link down (PLSR %02x)\n", axge, plsr );
                netdev_link_down ( netdev );
        }

        return 0;
}
static void axge_intr_complete ( struct usb_endpoint ep,
struct io_buffer iobuf,
int  rc 
) [static]

Complete interrupt transfer.

Parameters:
epUSB endpoint
iobufI/O buffer
rcCompletion status code

Definition at line 251 of file axge.c.

References AXGE_INTR_LINK_PPLS, AXGE_INTR_MAGIC, container_of, cpu_to_le16, io_buffer::data, DBGC, DBGC_HDA, EINVAL, error, free_iob(), usbnet_device::intr, intr, iob_disown, iob_len(), len, axge_interrupt::link, axge_interrupt::magic, netdev, axge_device::netdev, netdev_link_down(), netdev_link_ok(), netdev_link_up(), netdev_rx_err(), usb_endpoint::open, profile_start(), profile_stop(), strerror(), and axge_device::usbnet.

                                                                   {
        struct axge_device *axge = container_of ( ep, struct axge_device,
                                                  usbnet.intr );
        struct net_device *netdev = axge->netdev;
        struct axge_interrupt *intr;
        size_t len = iob_len ( iobuf );
        unsigned int link_ok;

        /* Profile completions */
        profile_start ( &axge_intr_profiler );

        /* Ignore packets cancelled when the endpoint closes */
        if ( ! ep->open )
                goto ignore;

        /* Drop packets with errors */
        if ( rc != 0 ) {
                DBGC ( axge, "AXGE %p interrupt failed: %s\n",
                       axge, strerror ( rc ) );
                DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
                goto error;
        }

        /* Extract message header */
        if ( len < sizeof ( *intr ) ) {
                DBGC ( axge, "AXGE %p underlength interrupt:\n", axge );
                DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EINVAL;
                goto error;
        }
        intr = iobuf->data;

        /* Check magic signature */
        if ( intr->magic != cpu_to_le16 ( AXGE_INTR_MAGIC ) ) {
                DBGC ( axge, "AXGE %p malformed interrupt:\n", axge );
                DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EINVAL;
                goto error;
        }

        /* Extract link status */
        link_ok = ( intr->link & cpu_to_le16 ( AXGE_INTR_LINK_PPLS ) );
        if ( link_ok && ! netdev_link_ok ( netdev ) ) {
                DBGC ( axge, "AXGE %p link up\n", axge );
                netdev_link_up ( netdev );
        } else if ( netdev_link_ok ( netdev ) && ! link_ok ) {
                DBGC ( axge, "AXGE %p link down\n", axge );
                netdev_link_down ( netdev );
        }

        /* Free I/O buffer */
        free_iob ( iobuf );
        profile_stop ( &axge_intr_profiler );

        return;

 error:
        netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
 ignore:
        free_iob ( iobuf );
        return;
}
static void axge_in_complete ( struct usb_endpoint ep,
struct io_buffer iobuf,
int  rc 
) [static]

Complete bulk IN transfer.

Parameters:
epUSB endpoint
iobufI/O buffer
rcCompletion status code

Definition at line 334 of file axge.c.

References alloc_iob(), assert, AXGE_IN_RESERVE, AXGE_RX_CRC_ERROR, AXGE_RX_DROP_ERROR, AXGE_RX_LEN_MASK, AXGE_RX_LEN_PAD_ALIGN, container_of, axge_rx_footer::count, count, cpu_to_le16, io_buffer::data, DBGC, DBGC_HDA, EINVAL, EIO, ENOBUFS, ENOMEM, error, free_iob(), usbnet_device::in, iob_disown, iob_len(), iob_pull, iob_put, iob_reserve, iob_unput, le16_to_cpu, len, axge_rx_descriptor::len_flags, memcpy(), netdev, axge_device::netdev, netdev_rx(), netdev_rx_err(), NULL, axge_rx_footer::offset, offset, usb_endpoint::open, profile_start(), profile_stop(), strerror(), and axge_device::usbnet.

                                                                 {
        struct axge_device *axge = container_of ( ep, struct axge_device,
                                                  usbnet.in );
        struct net_device *netdev = axge->netdev;
        struct axge_rx_footer *ftr;
        struct axge_rx_descriptor *desc;
        struct io_buffer *pkt;
        unsigned int count;
        unsigned int offset;
        size_t len;
        size_t padded_len;

        /* Profile receive completions */
        profile_start ( &axge_in_profiler );

        /* Ignore packets cancelled when the endpoint closes */
        if ( ! ep->open )
                goto ignore;

        /* Record USB errors against the network device */
        if ( rc != 0 ) {
                DBGC ( axge, "AXGE %p bulk IN failed: %s\n",
                       axge, strerror ( rc ) );
                goto error;
        }

        /* Sanity check */
        if ( iob_len ( iobuf ) < sizeof ( *ftr ) ) {
                DBGC ( axge, "AXGE %p underlength bulk IN:\n", axge );
                DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EINVAL;
                goto error;
        }

        /* Parse ftr, strip ftr and descriptors */
        iob_unput ( iobuf, sizeof ( *ftr ) );
        ftr = ( iobuf->data + iob_len ( iobuf ) );
        count = le16_to_cpu ( ftr->count );
        if ( count == 0 ) {
                DBGC ( axge, "AXGE %p zero-packet bulk IN:\n", axge );
                DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
                goto ignore;
        }
        offset = le16_to_cpu ( ftr->offset );
        if ( ( iob_len ( iobuf ) < offset ) ||
             ( ( iob_len ( iobuf ) - offset ) < ( count * sizeof ( *desc ) ) )){
                DBGC ( axge, "AXGE %p malformed bulk IN footer:\n", axge );
                DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EINVAL;
                goto error;
        }
        desc = ( iobuf->data + offset );
        iob_unput ( iobuf, ( iob_len ( iobuf ) - offset ) );

        /* Process packets */
        for ( ; count-- ; desc++ ) {

                /* Parse descriptor */
                len = ( le16_to_cpu ( desc->len_flags ) & AXGE_RX_LEN_MASK );
                padded_len = ( ( len + AXGE_RX_LEN_PAD_ALIGN - 1 ) &
                               ~( AXGE_RX_LEN_PAD_ALIGN - 1 ) );
                if ( iob_len ( iobuf ) < padded_len ) {
                        DBGC ( axge, "AXGE %p malformed bulk IN descriptor:\n",
                               axge );
                        DBGC_HDA ( axge, 0, iobuf->data, iob_len ( iobuf ) );
                        rc = -EINVAL;
                        goto error;
                }

                /* Check for previous dropped packets */
                if ( desc->len_flags & cpu_to_le16 ( AXGE_RX_CRC_ERROR ) )
                        netdev_rx_err ( netdev, NULL, -EIO );
                if ( desc->len_flags & cpu_to_le16 ( AXGE_RX_DROP_ERROR ) )
                        netdev_rx_err ( netdev, NULL, -ENOBUFS );

                /* Allocate new I/O buffer, if applicable */
                if ( count ) {

                        /* More packets remain: allocate a new buffer */
                        pkt = alloc_iob ( AXGE_IN_RESERVE + len );
                        if ( ! pkt ) {
                                /* Record error and continue */
                                netdev_rx_err ( netdev, NULL, -ENOMEM );
                                iob_pull ( iobuf, padded_len );
                                continue;
                        }
                        iob_reserve ( pkt, AXGE_IN_RESERVE );
                        memcpy ( iob_put ( pkt, len ), iobuf->data, len );
                        iob_pull ( iobuf, padded_len );

                } else {

                        /* This is the last (or only) packet: use this buffer */
                        iob_unput ( iobuf, ( padded_len - len ) );
                        pkt = iob_disown ( iobuf );
                }

                /* Hand off to network stack */
                netdev_rx ( netdev, iob_disown ( pkt ) );
        }

        assert ( iobuf == NULL );
        profile_stop ( &axge_in_profiler );
        return;

 error:
        netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
 ignore:
        free_iob ( iobuf );
}
static int axge_out_transmit ( struct axge_device axge,
struct io_buffer iobuf 
) [static]

Transmit packet.

Parameters:
asixAXGE device
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 458 of file axge.c.

References cpu_to_le32, hdr, iob_ensure_headroom(), iob_len(), iob_push, axge_tx_header::len, len, usbnet_device::out, profile_start(), profile_stop(), rc, usb_stream(), axge_device::usbnet, and axge_tx_header::wtf.

Referenced by axge_transmit().

                                                         {
        struct axge_tx_header *hdr;
        size_t len = iob_len ( iobuf );
        int rc;

        /* Profile transmissions */
        profile_start ( &axge_out_profiler );

        /* Prepend header */
        if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *hdr ) ) ) != 0 )
                return rc;
        hdr = iob_push ( iobuf, sizeof ( *hdr ) );
        hdr->len = cpu_to_le32 ( len );
        hdr->wtf = 0;

        /* Enqueue I/O buffer */
        if ( ( rc = usb_stream ( &axge->usbnet.out, iobuf, 0 ) ) != 0 )
                return rc;

        profile_stop ( &axge_out_profiler );
        return 0;
}
static void axge_out_complete ( struct usb_endpoint ep,
struct io_buffer iobuf,
int  rc 
) [static]

Complete bulk OUT transfer.

Parameters:
epUSB endpoint
iobufI/O buffer
rcCompletion status code

Definition at line 489 of file axge.c.

References container_of, netdev, axge_device::netdev, netdev_tx_complete_err(), usbnet_device::out, and axge_device::usbnet.

                                                                  {
        struct axge_device *axge = container_of ( ep, struct axge_device,
                                                  usbnet.out );
        struct net_device *netdev = axge->netdev;

        /* Report TX completion */
        netdev_tx_complete_err ( netdev, iobuf, rc );
}
static int axge_open ( struct net_device netdev) [static]

Open network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 517 of file axge.c.

References axge_check_link(), AXGE_NIDR, AXGE_RCR, AXGE_RCR_AB, AXGE_RCR_AMALL, AXGE_RCR_PRO, AXGE_RCR_SO, axge_write_register(), axge_write_word(), cpu_to_le16, DBGC, ETH_ALEN, net_device::ll_addr, net_device::priv, rc, strerror(), axge_device::usbnet, usbnet_close(), and usbnet_open().

                                                   {
        struct axge_device *axge = netdev->priv;
        uint16_t rcr;
        int rc;

        /* Open USB network device */
        if ( ( rc = usbnet_open ( &axge->usbnet ) ) != 0 ) {
                DBGC ( axge, "AXGE %p could not open: %s\n",
                       axge, strerror ( rc ) );
                goto err_open;
        }

        /* Set MAC address */
        if ( ( rc = axge_write_register ( axge, AXGE_NIDR,
                                          netdev->ll_addr, ETH_ALEN ) ) !=0){
                DBGC ( axge, "AXGE %p could not set MAC address: %s\n",
                       axge, strerror ( rc ) );
                goto err_write_mac;
        }

        /* Enable receiver */
        rcr = cpu_to_le16 ( AXGE_RCR_PRO | AXGE_RCR_AMALL |
                            AXGE_RCR_AB | AXGE_RCR_SO );
        if ( ( rc = axge_write_word ( axge, AXGE_RCR, rcr ) ) != 0 ) {
                DBGC ( axge, "AXGE %p could not write RCR: %s\n",
                       axge, strerror ( rc ) );
                goto err_write_rcr;
        }

        /* Update link status */
        axge_check_link ( axge );

        return 0;

        axge_write_word ( axge, AXGE_RCR, 0 );
 err_write_rcr:
 err_write_mac:
        usbnet_close ( &axge->usbnet );
 err_open:
        return rc;
}
static void axge_close ( struct net_device netdev) [static]

Close network device.

Parameters:
netdevNetwork device

Definition at line 564 of file axge.c.

References AXGE_RCR, axge_write_word(), net_device::priv, axge_device::usbnet, and usbnet_close().

                                                     {
        struct axge_device *axge = netdev->priv;

        /* Disable receiver */
        axge_write_word ( axge, AXGE_RCR, 0 );

        /* Close USB network device */
        usbnet_close ( &axge->usbnet );
}
static int axge_transmit ( struct net_device netdev,
struct io_buffer iobuf 
) [static]

Transmit packet.

Parameters:
netdevNetwork device
iobufI/O buffer
Return values:
rcReturn status code

Definition at line 581 of file axge.c.

References axge_out_transmit(), net_device::priv, and rc.

                                                     {
        struct axge_device *axge = netdev->priv;
        int rc;

        /* Transmit packet */
        if ( ( rc = axge_out_transmit ( axge, iobuf ) ) != 0 )
                return rc;

        return 0;
}
static void axge_poll ( struct net_device netdev) [static]

Poll for completed and received packets.

Parameters:
netdevNetwork device

Definition at line 598 of file axge.c.

References axge_device::bus, netdev_rx_err(), NULL, net_device::priv, rc, usb_poll(), axge_device::usbnet, and usbnet_refill().

                                                    {
        struct axge_device *axge = netdev->priv;
        int rc;

        /* Poll USB bus */
        usb_poll ( axge->bus );

        /* Refill endpoints */
        if ( ( rc = usbnet_refill ( &axge->usbnet ) ) != 0 )
                netdev_rx_err ( netdev, NULL, rc );
}
static int axge_probe ( struct usb_function func,
struct usb_configuration_descriptor config 
) [static]

Probe device.

Parameters:
funcUSB function
configConfiguration descriptor
Return values:
rcReturn status code

Definition at line 632 of file axge.c.

References alloc_etherdev(), AXGE_BICR, axge_check_link(), AXGE_CSR, AXGE_CSR_ACS, AXGE_CSR_BCS, AXGE_CSR_DELAY_MS, AXGE_EPPRCR, AXGE_EPPRCR_DELAY_MS, AXGE_EPPRCR_IPRL, AXGE_IN_MAX_FILL, AXGE_IN_MTU, AXGE_IN_RESERVE, AXGE_INTR_MAX_FILL, AXGE_MSR, AXGE_MSR_FD, AXGE_MSR_GM, AXGE_MSR_RE, AXGE_MSR_RFC, AXGE_MSR_TFC, AXGE_NIDR, axge_read_register(), axge_write_byte(), axge_write_register(), axge_write_word(), axge_device::bus, usb_hub::bus, cpu_to_le16, DBGC, net_device::dev, usb_function::dev, ENOMEM, ETH_ALEN, usb_port::hub, net_device::hw_addr, usbnet_device::in, usbnet_device::intr, mdelay(), memset(), usb_function::name, netdev, axge_device::netdev, netdev_init(), netdev_nullify(), netdev_put(), usb_device::port, net_device::priv, rc, register_netdev(), strerror(), unregister_netdev(), axge_device::usb, usb_function::usb, usb_func_set_drvdata(), usb_refill_init(), axge_device::usbnet, usbnet_describe(), and usbnet_init().

                                                                      {
        struct usb_device *usb = func->usb;
        struct net_device *netdev;
        struct axge_device *axge;
        uint16_t epprcr;
        uint16_t msr;
        uint8_t csr;
        int rc;

        /* Allocate and initialise structure */
        netdev = alloc_etherdev ( sizeof ( *axge ) );
        if ( ! netdev ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        netdev_init ( netdev, &axge_operations );
        netdev->dev = &func->dev;
        axge = netdev->priv;
        memset ( axge, 0, sizeof ( *axge ) );
        axge->usb = usb;
        axge->bus = usb->port->hub->bus;
        axge->netdev = netdev;
        usbnet_init ( &axge->usbnet, func, &axge_intr_operations,
                      &axge_in_operations, &axge_out_operations );
        usb_refill_init ( &axge->usbnet.intr, 0, 0, AXGE_INTR_MAX_FILL );
        usb_refill_init ( &axge->usbnet.in, AXGE_IN_RESERVE,
                          AXGE_IN_MTU, AXGE_IN_MAX_FILL );
        DBGC ( axge, "AXGE %p on %s\n", axge, func->name );

        /* Describe USB network device */
        if ( ( rc = usbnet_describe ( &axge->usbnet, config ) ) != 0 ) {
                DBGC ( axge, "AXGE %p could not describe: %s\n",
                       axge, strerror ( rc ) );
                goto err_describe;
        }

        /* Fetch MAC address */
        if ( ( rc = axge_read_register ( axge, AXGE_NIDR, netdev->hw_addr,
                                         ETH_ALEN ) ) != 0 ) {
                DBGC ( axge, "AXGE %p could not fetch MAC address: %s\n",
                       axge, strerror ( rc ) );
                goto err_read_mac;
        }

        /* Power up PHY */
        if ( ( rc = axge_write_word ( axge, AXGE_EPPRCR, 0 ) ) != 0 ) {
                DBGC ( axge, "AXGE %p could not write EPPRCR: %s\n",
                       axge, strerror ( rc ) );
                goto err_write_epprcr_off;
        }
        epprcr = cpu_to_le16 ( AXGE_EPPRCR_IPRL );
        if ( ( rc = axge_write_word ( axge, AXGE_EPPRCR, epprcr ) ) != 0){
                DBGC ( axge, "AXGE %p could not write EPPRCR: %s\n",
                       axge, strerror ( rc ) );
                goto err_write_epprcr_on;
        }
        mdelay ( AXGE_EPPRCR_DELAY_MS );

        /* Select clocks */
        csr = ( AXGE_CSR_BCS | AXGE_CSR_ACS );
        if ( ( rc = axge_write_byte ( axge, AXGE_CSR, csr ) ) != 0){
                DBGC ( axge, "AXGE %p could not write CSR: %s\n",
                       axge, strerror ( rc ) );
                goto err_write_csr;
        }
        mdelay ( AXGE_CSR_DELAY_MS );

        /* Configure bulk IN pipeline */
        if ( ( rc = axge_write_register ( axge, AXGE_BICR, &axge_bicr,
                                          sizeof ( axge_bicr ) ) ) != 0 ){
                DBGC ( axge, "AXGE %p could not write BICR: %s\n",
                       axge, strerror ( rc ) );
                goto err_write_bicr;
        }

        /* Set medium status */
        msr = cpu_to_le16 ( AXGE_MSR_GM | AXGE_MSR_FD | AXGE_MSR_RFC |
                            AXGE_MSR_TFC | AXGE_MSR_RE );
        if ( ( rc = axge_write_word ( axge, AXGE_MSR, msr ) ) != 0 ) {
                DBGC ( axge, "AXGE %p could not write MSR: %s\n",
                       axge, strerror ( rc ) );
                goto err_write_msr;
        }

        /* Register network device */
        if ( ( rc = register_netdev ( netdev ) ) != 0 )
                goto err_register;

        /* Update link status */
        axge_check_link ( axge );

        usb_func_set_drvdata ( func, axge );
        return 0;

        unregister_netdev ( netdev );
 err_register:
 err_write_msr:
 err_write_bicr:
 err_write_csr:
 err_write_epprcr_on:
 err_write_epprcr_off:
 err_read_mac:
 err_describe:
        netdev_nullify ( netdev );
        netdev_put ( netdev );
 err_alloc:
        return rc;
}
static void axge_remove ( struct usb_function func) [static]

Remove device.

Parameters:
funcUSB function

Definition at line 747 of file axge.c.

References netdev, axge_device::netdev, netdev_nullify(), netdev_put(), unregister_netdev(), and usb_func_get_drvdata().

                                                      {
        struct axge_device *axge = usb_func_get_drvdata ( func );
        struct net_device *netdev = axge->netdev;

        unregister_netdev ( netdev );
        netdev_nullify ( netdev );
        netdev_put ( netdev );
}

Variable Documentation

struct profiler axge_out_profiler __profiler [static]
Initial value:
        { .name = "axge.intr" }

Interrupt completion profiler.

Bulk OUT profiler.

Bulk IN completion profiler.

Definition at line 47 of file axge.c.

Initial value:
 {
        .ctrl = 7,
        .timer = cpu_to_le16 ( 0 ),
        .size = 0,
        .ifg = 0,
}

Default bulk IN configuration.

The Linux and FreeBSD drivers have set of magic constants which are chosen based on both the Ethernet and USB link speeds.

Experimentation shows that setting the "timer" value to zero seems to prevent the device from ever coalescing multiple packets into a single bulk IN transfer. This allows us to get away with using a 2kB receive I/O buffer and a zerocopy receive path.

Definition at line 68 of file axge.c.

Initial value:
 {
        .complete = axge_intr_complete,
}

Interrupt endpoint operations.

Definition at line 316 of file axge.c.

Initial value:
 {
        .complete = axge_in_complete,
}

Bulk IN endpoint operations.

Definition at line 447 of file axge.c.

Initial value:
 {
        .complete = axge_out_complete,
}

Bulk OUT endpoint operations.

Definition at line 500 of file axge.c.

Initial value:
 {
        .open           = axge_open,
        .close          = axge_close,
        .transmit       = axge_transmit,
        .poll           = axge_poll,
}

AXGE network device operations.

Definition at line 611 of file axge.c.

struct usb_device_id axge_ids[] [static]

AXGE device IDs.

Definition at line 757 of file axge.c.

struct usb_driver axge_driver __usb_driver
Initial value:
 {
        .ids = axge_ids,
        .id_count = ( sizeof ( axge_ids ) / sizeof ( axge_ids[0] ) ),
        .class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ),
        .score = USB_SCORE_NORMAL,
        .probe = axge_probe,
        .remove = axge_remove,
}

AXGE driver.

Definition at line 791 of file axge.c.