iPXE
Functions | Variables
smscusb.c File Reference

SMSC USB Ethernet drivers. More...

#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <ipxe/usb.h>
#include <ipxe/usbnet.h>
#include <ipxe/ethernet.h>
#include <ipxe/profile.h>
#include "smscusb.h"

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
int smscusb_raw_writel (struct smscusb_device *smscusb, unsigned int address, uint32_t value)
 Write register (without byte-swapping)
int smscusb_raw_readl (struct smscusb_device *smscusb, unsigned int address, uint32_t *value)
 Read register (without byte-swapping)
static int smscusb_eeprom_wait (struct smscusb_device *smscusb, unsigned int e2p_base)
 Wait for EEPROM to become idle.
static int smscusb_eeprom_read_byte (struct smscusb_device *smscusb, unsigned int e2p_base, unsigned int address)
 Read byte from EEPROM.
static int smscusb_eeprom_read (struct smscusb_device *smscusb, unsigned int e2p_base, unsigned int address, void *data, size_t len)
 Read data from EEPROM.
int smscusb_eeprom_fetch_mac (struct smscusb_device *smscusb, unsigned int e2p_base)
 Fetch MAC address from EEPROM.
static int smscusb_otp_power_up (struct smscusb_device *smscusb, unsigned int otp_base)
 Power up OTP.
static int smscusb_otp_wait (struct smscusb_device *smscusb, unsigned int otp_base)
 Wait for OTP to become idle.
static int smscusb_otp_read_byte (struct smscusb_device *smscusb, unsigned int otp_base, unsigned int address)
 Read byte from OTP.
static int smscusb_otp_read (struct smscusb_device *smscusb, unsigned int otp_base, unsigned int address, void *data, size_t len)
 Read data from OTP.
int smscusb_otp_fetch_mac (struct smscusb_device *smscusb, unsigned int otp_base)
 Fetch MAC address from OTP.
static int smscusb_mii_wait (struct smscusb_device *smscusb)
 Wait for MII to become idle.
static int smscusb_mii_read (struct mii_interface *mdio, unsigned int phy __unused, unsigned int reg)
 Read from MII register.
static int smscusb_mii_write (struct mii_interface *mdio, unsigned int phy __unused, unsigned int reg, unsigned int data)
 Write to MII register.
int smscusb_mii_check_link (struct smscusb_device *smscusb)
 Check link status.
int smscusb_mii_open (struct smscusb_device *smscusb, unsigned int phy_mask, unsigned int intrs)
 Enable PHY interrupts and update link status.
int smscusb_set_address (struct smscusb_device *smscusb, unsigned int addr_base)
 Set receive address.
int smscusb_set_filter (struct smscusb_device *smscusb, unsigned int filt_base)
 Set receive filter.
static void smscusb_intr_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete interrupt transfer.
static void smscusb_out_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete bulk OUT transfer.

Variables

static struct profiler
smscusb_intr_profiler 
__profiler
 Interrupt completion profiler.
struct mii_operations smscusb_mii_operations
 MII operations.
struct
usb_endpoint_driver_operations 
smscusb_intr_operations
 Interrupt endpoint operations.
struct
usb_endpoint_driver_operations 
smscusb_out_operations
 Bulk OUT endpoint operations.

Detailed Description

SMSC USB Ethernet drivers.

Definition in file smscusb.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
int smscusb_raw_writel ( struct smscusb_device smscusb,
unsigned int  address,
uint32_t  value 
)

Write register (without byte-swapping)

Parameters:
smscusbSmscusb device
addressRegister address
valueRegister value
Return values:
rcReturn status code

Definition at line 60 of file smscusb.c.

References DBGC, DBGCIO, le32_to_cpu, rc, SMSCUSB_REGISTER_WRITE, strerror(), smscusb_device::usb, and usb_control().

Referenced by smscusb_set_address(), and smscusb_set_filter().

                                          {
        int rc;

        /* Write register */
        DBGCIO ( smscusb, "SMSCUSB %p [%03x] <= %08x\n",
                 smscusb, address, le32_to_cpu ( value ) );
        if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_REGISTER_WRITE, 0,
                                  address, &value, sizeof ( value ) ) ) != 0 ) {
                DBGC ( smscusb, "SMSCUSB %p could not write %03x: %s\n",
                       smscusb, address, strerror ( rc ) );
                return rc;
        }

        return 0;
}
int smscusb_raw_readl ( struct smscusb_device smscusb,
unsigned int  address,
uint32_t value 
)

Read register (without byte-swapping)

Parameters:
smscusbSMSC USB device
addressRegister address
Return values:
valueRegister value
rcReturn status code

Definition at line 85 of file smscusb.c.

References DBGC, DBGCIO, le32_to_cpu, rc, SMSCUSB_REGISTER_READ, strerror(), smscusb_device::usb, and usb_control().

                                          {
        int rc;

        /* Read register */
        if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_REGISTER_READ, 0,
                                  address, value, sizeof ( *value ) ) ) != 0 ) {
                DBGC ( smscusb, "SMSCUSB %p could not read %03x: %s\n",
                       smscusb, address, strerror ( rc ) );
                return rc;
        }
        DBGCIO ( smscusb, "SMSCUSB %p [%03x] => %08x\n",
                 smscusb, address, le32_to_cpu ( *value ) );

        return 0;
}
static int smscusb_eeprom_wait ( struct smscusb_device smscusb,
unsigned int  e2p_base 
) [static]

Wait for EEPROM to become idle.

Parameters:
smscusbSMSC USB device
e2p_baseE2P register base
Return values:
rcReturn status code

Definition at line 116 of file smscusb.c.

References DBGC, ETIMEDOUT, mdelay(), rc, SMSCUSB_E2P_CMD, SMSCUSB_E2P_CMD_EPC_BSY, SMSCUSB_EEPROM_MAX_WAIT_MS, and smscusb_readl().

Referenced by smscusb_eeprom_read_byte().

                                                         {
        uint32_t e2p_cmd;
        unsigned int i;
        int rc;

        /* Wait for EPC_BSY to become clear */
        for ( i = 0 ; i < SMSCUSB_EEPROM_MAX_WAIT_MS ; i++ ) {

                /* Read E2P_CMD and check EPC_BSY */
                if ( ( rc = smscusb_readl ( smscusb,
                                            ( e2p_base + SMSCUSB_E2P_CMD ),
                                            &e2p_cmd ) ) != 0 )
                        return rc;
                if ( ! ( e2p_cmd & SMSCUSB_E2P_CMD_EPC_BSY ) )
                        return 0;

                /* Delay */
                mdelay ( 1 );
        }

        DBGC ( smscusb, "SMSCUSB %p timed out waiting for EEPROM\n",
               smscusb );
        return -ETIMEDOUT;
}
static int smscusb_eeprom_read_byte ( struct smscusb_device smscusb,
unsigned int  e2p_base,
unsigned int  address 
) [static]

Read byte from EEPROM.

Parameters:
smscusbSMSC USB device
e2p_baseE2P register base
addressEEPROM address
Return values:
byteByte read, or negative error

Definition at line 150 of file smscusb.c.

References rc, SMSCUSB_E2P_CMD, SMSCUSB_E2P_CMD_EPC_ADDR, SMSCUSB_E2P_CMD_EPC_BSY, SMSCUSB_E2P_CMD_EPC_CMD_READ, SMSCUSB_E2P_DATA, SMSCUSB_E2P_DATA_GET, smscusb_eeprom_wait(), smscusb_readl(), and smscusb_writel().

Referenced by smscusb_eeprom_read().

                                                             {
        uint32_t e2p_cmd;
        uint32_t e2p_data;
        int rc;

        /* Wait for EEPROM to become idle */
        if ( ( rc = smscusb_eeprom_wait ( smscusb, e2p_base ) ) != 0 )
                return rc;

        /* Initiate read command */
        e2p_cmd = ( SMSCUSB_E2P_CMD_EPC_BSY | SMSCUSB_E2P_CMD_EPC_CMD_READ |
                    SMSCUSB_E2P_CMD_EPC_ADDR ( address ) );
        if ( ( rc = smscusb_writel ( smscusb, ( e2p_base + SMSCUSB_E2P_CMD ),
                                     e2p_cmd ) ) != 0 )
                return rc;

        /* Wait for command to complete */
        if ( ( rc = smscusb_eeprom_wait ( smscusb, e2p_base ) ) != 0 )
                return rc;

        /* Read EEPROM data */
        if ( ( rc = smscusb_readl ( smscusb, ( e2p_base + SMSCUSB_E2P_DATA ),
                                    &e2p_data ) ) != 0 )
                return rc;

        return SMSCUSB_E2P_DATA_GET ( e2p_data );
}
static int smscusb_eeprom_read ( struct smscusb_device smscusb,
unsigned int  e2p_base,
unsigned int  address,
void *  data,
size_t  len 
) [static]

Read data from EEPROM.

Parameters:
smscusbSMSC USB device
e2p_baseE2P register base
addressEEPROM address
dataData buffer
lenLength of data
Return values:
rcReturn status code

Definition at line 190 of file smscusb.c.

References byte, bytes, and smscusb_eeprom_read_byte().

Referenced by smscusb_eeprom_fetch_mac().

                                                          {
        uint8_t *bytes;
        int byte;

        /* Read bytes */
        for ( bytes = data ; len-- ; address++, bytes++ ) {
                byte = smscusb_eeprom_read_byte ( smscusb, e2p_base, address );
                if ( byte < 0 )
                        return byte;
                *bytes = byte;
        }

        return 0;
}
int smscusb_eeprom_fetch_mac ( struct smscusb_device smscusb,
unsigned int  e2p_base 
)

Fetch MAC address from EEPROM.

Parameters:
smscusbSMSC USB device
e2p_baseE2P register base
Return values:
rcReturn status code

Definition at line 214 of file smscusb.c.

References DBGC, ENODEV, ETH_ALEN, eth_ntoa(), net_device::hw_addr, is_valid_ether_addr(), netdev, smscusb_device::netdev, rc, SMSCUSB_EEPROM_MAC, and smscusb_eeprom_read().

Referenced by lan78xx_eeprom_fetch_mac(), smsc75xx_probe(), and smsc95xx_fetch_mac().

                                                       {
        struct net_device *netdev = smscusb->netdev;
        int rc;

        /* Read MAC address from EEPROM */
        if ( ( rc = smscusb_eeprom_read ( smscusb, e2p_base, SMSCUSB_EEPROM_MAC,
                                          netdev->hw_addr, ETH_ALEN ) ) != 0 )
                return rc;

        /* Check that EEPROM is physically present */
        if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
                DBGC ( smscusb, "SMSCUSB %p has no EEPROM MAC (%s)\n",
                       smscusb, eth_ntoa ( netdev->hw_addr ) );
                return -ENODEV;
        }

        DBGC ( smscusb, "SMSCUSB %p using EEPROM MAC %s\n",
               smscusb, eth_ntoa ( netdev->hw_addr ) );
        return 0;
}
static int smscusb_otp_power_up ( struct smscusb_device smscusb,
unsigned int  otp_base 
) [static]

Power up OTP.

Parameters:
smscusbSMSC USB device
otp_baseOTP register base
Return values:
rcReturn status code

Definition at line 250 of file smscusb.c.

References DBGC, ETIMEDOUT, mdelay(), rc, SMSCUSB_OTP_MAX_WAIT_MS, SMSCUSB_OTP_POWER, SMSCUSB_OTP_POWER_DOWN, smscusb_readl(), and smscusb_writel().

Referenced by smscusb_otp_read().

                                                          {
        uint32_t otp_power;
        unsigned int i;
        int rc;

        /* Power up OTP */
        if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_POWER ),
                                     0 ) ) != 0 )
                return rc;

        /* Wait for OTP_POWER_DOWN to become clear */
        for ( i = 0 ; i < SMSCUSB_OTP_MAX_WAIT_MS ; i++ ) {

                /* Read OTP_POWER and check OTP_POWER_DOWN */
                if ( ( rc = smscusb_readl ( smscusb,
                                            ( otp_base + SMSCUSB_OTP_POWER ),
                                            &otp_power ) ) != 0 )
                        return rc;
                if ( ! ( otp_power & SMSCUSB_OTP_POWER_DOWN ) )
                        return 0;

                /* Delay */
                mdelay ( 1 );
        }

        DBGC ( smscusb, "SMSCUSB %p timed out waiting for OTP power up\n",
               smscusb );
        return -ETIMEDOUT;
}
static int smscusb_otp_wait ( struct smscusb_device smscusb,
unsigned int  otp_base 
) [static]

Wait for OTP to become idle.

Parameters:
smscusbSMSC USB device
otp_baseOTP register base
Return values:
rcReturn status code

Definition at line 288 of file smscusb.c.

References DBGC, ETIMEDOUT, mdelay(), rc, SMSCUSB_OTP_MAX_WAIT_MS, SMSCUSB_OTP_STATUS, SMSCUSB_OTP_STATUS_BUSY, and smscusb_readl().

Referenced by smscusb_otp_read_byte().

                                                      {
        uint32_t otp_status;
        unsigned int i;
        int rc;

        /* Wait for OTP_STATUS_BUSY to become clear */
        for ( i = 0 ; i < SMSCUSB_OTP_MAX_WAIT_MS ; i++ ) {

                /* Read OTP_STATUS and check OTP_STATUS_BUSY */
                if ( ( rc = smscusb_readl ( smscusb,
                                            ( otp_base + SMSCUSB_OTP_STATUS ),
                                            &otp_status ) ) != 0 )
                        return rc;
                if ( ! ( otp_status & SMSCUSB_OTP_STATUS_BUSY ) )
                        return 0;

                /* Delay */
                mdelay ( 1 );
        }

        DBGC ( smscusb, "SMSCUSB %p timed out waiting for OTP\n",
               smscusb );
        return -ETIMEDOUT;
}
static int smscusb_otp_read_byte ( struct smscusb_device smscusb,
unsigned int  otp_base,
unsigned int  address 
) [static]

Read byte from OTP.

Parameters:
smscusbSMSC USB device
otp_baseOTP register base
addressOTP address
Return values:
byteByte read, or negative error

Definition at line 322 of file smscusb.c.

References rc, SMSCUSB_OTP_ADDRH, SMSCUSB_OTP_ADDRL, SMSCUSB_OTP_CMD, SMSCUSB_OTP_CMD_READ, SMSCUSB_OTP_DATA, SMSCUSB_OTP_DATA_GET, SMSCUSB_OTP_GO, SMSCUSB_OTP_GO_GO, smscusb_otp_wait(), smscusb_readl(), and smscusb_writel().

Referenced by smscusb_otp_read().

                                                          {
        uint8_t addrh = ( address >> 8 );
        uint8_t addrl = ( address >> 0 );
        uint32_t otp_data;
        int rc;

        /* Wait for OTP to become idle */
        if ( ( rc = smscusb_otp_wait ( smscusb, otp_base ) ) != 0 )
                return rc;

        /* Initiate read command */
        if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_ADDRH ),
                                     addrh ) ) != 0 )
                return rc;
        if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_ADDRL ),
                                     addrl ) ) != 0 )
                return rc;
        if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_CMD ),
                                     SMSCUSB_OTP_CMD_READ ) ) != 0 )
                return rc;
        if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_GO ),
                                     SMSCUSB_OTP_GO_GO ) ) != 0 )
                return rc;

        /* Wait for command to complete */
        if ( ( rc = smscusb_otp_wait ( smscusb, otp_base ) ) != 0 )
                return rc;

        /* Read OTP data */
        if ( ( rc = smscusb_readl ( smscusb, ( otp_base + SMSCUSB_OTP_DATA ),
                                    &otp_data ) ) != 0 )
                return rc;

        return SMSCUSB_OTP_DATA_GET ( otp_data );
}
static int smscusb_otp_read ( struct smscusb_device smscusb,
unsigned int  otp_base,
unsigned int  address,
void *  data,
size_t  len 
) [static]

Read data from OTP.

Parameters:
smscusbSMSC USB device
otp_baseOTP register base
addressOTP address
dataData buffer
lenLength of data
Return values:
rcReturn status code

Definition at line 370 of file smscusb.c.

References byte, bytes, rc, smscusb_otp_power_up(), and smscusb_otp_read_byte().

Referenced by smscusb_otp_fetch_mac().

                                                       {
        uint8_t *bytes;
        int byte;
        int rc;

        /* Power up OTP */
        if ( ( rc = smscusb_otp_power_up ( smscusb, otp_base ) ) != 0 )
                return rc;

        /* Read bytes */
        for ( bytes = data ; len-- ; address++, bytes++ ) {
                byte = smscusb_otp_read_byte ( smscusb, otp_base, address );
                if ( byte < 0 )
                        return byte;
                *bytes = byte;
        }

        return 0;
}
int smscusb_otp_fetch_mac ( struct smscusb_device smscusb,
unsigned int  otp_base 
)

Fetch MAC address from OTP.

Parameters:
smscusbSMSC USB device
otp_baseOTP register base
Return values:
rcReturn status code

Definition at line 399 of file smscusb.c.

References address, DBGC, ENODEV, ENOTSUP, ETH_ALEN, eth_ntoa(), net_device::hw_addr, is_valid_ether_addr(), netdev, smscusb_device::netdev, rc, signature, SMSCUSB_OTP_1_MAC, SMSCUSB_OTP_1_SIG, SMSCUSB_OTP_2_MAC, SMSCUSB_OTP_2_SIG, and smscusb_otp_read().

Referenced by lan78xx_fetch_mac().

                                                    {
        struct net_device *netdev = smscusb->netdev;
        uint8_t signature;
        unsigned int address;
        int rc;

        /* Read OTP signature byte */
        if ( ( rc = smscusb_otp_read ( smscusb, otp_base, 0, &signature,
                                       sizeof ( signature ) ) ) != 0 )
                return rc;

        /* Determine location of MAC address */
        switch ( signature ) {
        case SMSCUSB_OTP_1_SIG:
                address = SMSCUSB_OTP_1_MAC;
                break;
        case SMSCUSB_OTP_2_SIG:
                address = SMSCUSB_OTP_2_MAC;
                break;
        default:
                DBGC ( smscusb, "SMSCUSB %p unknown OTP signature %#02x\n",
                       smscusb, signature );
                return -ENOTSUP;
        }

        /* Read MAC address from OTP */
        if ( ( rc = smscusb_otp_read ( smscusb, otp_base, address,
                                       netdev->hw_addr, ETH_ALEN ) ) != 0 )
                return rc;

        /* Check that OTP is valid */
        if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
                DBGC ( smscusb, "SMSCUSB %p has no layout %#02x OTP MAC (%s)\n",
                       smscusb, signature, eth_ntoa ( netdev->hw_addr ) );
                return -ENODEV;
        }

        DBGC ( smscusb, "SMSCUSB %p using layout %#02x OTP MAC %s\n",
               smscusb, signature, eth_ntoa ( netdev->hw_addr ) );
        return 0;
}
static int smscusb_mii_wait ( struct smscusb_device smscusb) [static]

Wait for MII to become idle.

Parameters:
smscusbSMSC USB device
Return values:
rcReturn status code

Definition at line 455 of file smscusb.c.

References base, DBGC, ETIMEDOUT, mdelay(), smscusb_device::mii_base, rc, SMSCUSB_MII_ACCESS, SMSCUSB_MII_ACCESS_MIIBZY, SMSCUSB_MII_MAX_WAIT_MS, and smscusb_readl().

Referenced by smscusb_mii_read(), and smscusb_mii_write().

                                                               {
        unsigned int base = smscusb->mii_base;
        uint32_t mii_access;
        unsigned int i;
        int rc;

        /* Wait for MIIBZY to become clear */
        for ( i = 0 ; i < SMSCUSB_MII_MAX_WAIT_MS ; i++ ) {

                /* Read MII_ACCESS and check MIIBZY */
                if ( ( rc = smscusb_readl ( smscusb,
                                            ( base + SMSCUSB_MII_ACCESS ),
                                            &mii_access ) ) != 0 )
                        return rc;
                if ( ! ( mii_access & SMSCUSB_MII_ACCESS_MIIBZY ) )
                        return 0;

                /* Delay */
                mdelay ( 1 );
        }

        DBGC ( smscusb, "SMSCUSB %p timed out waiting for MII\n",
               smscusb );
        return -ETIMEDOUT;
}
static int smscusb_mii_read ( struct mii_interface mdio,
unsigned int phy  __unused,
unsigned int  reg 
) [static]

Read from MII register.

Parameters:
mdioMII interface
phyPHY address
regRegister address
Return values:
valueData read, or negative error

Definition at line 489 of file smscusb.c.

References base, container_of, smscusb_device::mii_base, rc, SMSCUSB_MII_ACCESS, SMSCUSB_MII_ACCESS_MIIBZY, SMSCUSB_MII_ACCESS_MIIRINDA, SMSCUSB_MII_ACCESS_PHY_ADDRESS, SMSCUSB_MII_DATA, SMSCUSB_MII_DATA_GET, smscusb_mii_wait(), smscusb_readl(), and smscusb_writel().

                                                                            {
        struct smscusb_device *smscusb =
                container_of ( mdio, struct smscusb_device, mdio );
        unsigned int base = smscusb->mii_base;
        uint32_t mii_access;
        uint32_t mii_data;
        int rc;

        /* Wait for MII to become idle */
        if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
                return rc;

        /* Initiate read command */
        mii_access = ( SMSCUSB_MII_ACCESS_PHY_ADDRESS |
                       SMSCUSB_MII_ACCESS_MIIRINDA ( reg ) |
                       SMSCUSB_MII_ACCESS_MIIBZY );
        if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_ACCESS ),
                                     mii_access ) ) != 0 )
                return rc;

        /* Wait for command to complete */
        if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
                return rc;

        /* Read MII data */
        if ( ( rc = smscusb_readl ( smscusb, ( base + SMSCUSB_MII_DATA ),
                                    &mii_data ) ) != 0 )
                return rc;

        return SMSCUSB_MII_DATA_GET ( mii_data );
}
static int smscusb_mii_write ( struct mii_interface mdio,
unsigned int phy  __unused,
unsigned int  reg,
unsigned int  data 
) [static]

Write to MII register.

Parameters:
mdioMII interface
phyPHY address
regRegister address
dataData to write
Return values:
rcReturn status code

Definition at line 531 of file smscusb.c.

References base, container_of, smscusb_device::mii_base, rc, SMSCUSB_MII_ACCESS, SMSCUSB_MII_ACCESS_MIIBZY, SMSCUSB_MII_ACCESS_MIIRINDA, SMSCUSB_MII_ACCESS_MIIWNR, SMSCUSB_MII_ACCESS_PHY_ADDRESS, SMSCUSB_MII_DATA, SMSCUSB_MII_DATA_SET, smscusb_mii_wait(), and smscusb_writel().

                                                   {
        struct smscusb_device *smscusb =
                container_of ( mdio, struct smscusb_device, mdio );
        unsigned int base = smscusb->mii_base;
        uint32_t mii_access;
        uint32_t mii_data;
        int rc;

        /* Wait for MII to become idle */
        if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
                return rc;

        /* Write MII data */
        mii_data = SMSCUSB_MII_DATA_SET ( data );
        if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_DATA ),
                                     mii_data ) ) != 0 )
                return rc;

        /* Initiate write command */
        mii_access = ( SMSCUSB_MII_ACCESS_PHY_ADDRESS |
                       SMSCUSB_MII_ACCESS_MIIRINDA ( reg ) |
                       SMSCUSB_MII_ACCESS_MIIWNR |
                       SMSCUSB_MII_ACCESS_MIIBZY );
        if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_ACCESS ),
                                     mii_access ) ) != 0 )
                return rc;

        /* Wait for command to complete */
        if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
                return rc;

        return 0;
}
int smscusb_mii_check_link ( struct smscusb_device smscusb)

Check link status.

Parameters:
smscusbSMSC USB device
Return values:
rcReturn status code

Definition at line 579 of file smscusb.c.

References DBGC, intr, smscusb_device::mii, mii_check_link(), mii_read(), mii_write(), netdev, smscusb_device::netdev, netdev_link_ok(), smscusb_device::phy_source, rc, and strerror().

Referenced by smsc75xx_poll(), smsc95xx_poll(), and smscusb_mii_open().

                                                              {
        struct net_device *netdev = smscusb->netdev;
        int intr;
        int rc;

        /* Read PHY interrupt source */
        intr = mii_read ( &smscusb->mii, smscusb->phy_source );
        if ( intr < 0 ) {
                rc = intr;
                DBGC ( smscusb, "SMSCUSB %p could not get PHY interrupt "
                       "source: %s\n", smscusb, strerror ( rc ) );
                return rc;
        }

        /* Acknowledge PHY interrupt */
        if ( ( rc = mii_write ( &smscusb->mii, smscusb->phy_source,
                                intr ) ) != 0 ) {
                DBGC ( smscusb, "SMSCUSB %p could not acknowledge PHY "
                       "interrupt: %s\n", smscusb, strerror ( rc ) );
                return rc;
        }

        /* Check link status */
        if ( ( rc = mii_check_link ( &smscusb->mii, netdev ) ) != 0 ) {
                DBGC ( smscusb, "SMSCUSB %p could not check link: %s\n",
                       smscusb, strerror ( rc ) );
                return rc;
        }

        DBGC ( smscusb, "SMSCUSB %p link %s (intr %#04x)\n",
               smscusb, ( netdev_link_ok ( netdev ) ? "up" : "down" ), intr );
        return 0;
}
int smscusb_mii_open ( struct smscusb_device smscusb,
unsigned int  phy_mask,
unsigned int  intrs 
)

Enable PHY interrupts and update link status.

Parameters:
smscusbSMSC USB device
phy_maskPHY interrupt mask register
intrsPHY interrupts to enable
Return values:
rcReturn status code

Definition at line 621 of file smscusb.c.

References DBGC, smscusb_device::mii, mii_write(), rc, smscusb_mii_check_link(), and strerror().

Referenced by lan78xx_open(), smsc75xx_open(), and smsc95xx_open().

                                                                   {
        int rc;

        /* Enable PHY interrupts */
        if ( ( rc = mii_write ( &smscusb->mii, phy_mask, intrs ) ) != 0 ) {
                DBGC ( smscusb, "SMSCUSB %p could not set PHY interrupt "
                       "mask: %s\n", smscusb, strerror ( rc ) );
                return rc;
        }

        /* Update link status */
        smscusb_mii_check_link ( smscusb );

        return 0;
}
int smscusb_set_address ( struct smscusb_device smscusb,
unsigned int  addr_base 
)

Set receive address.

Parameters:
smscusbSMSC USB device
addr_baseReceive address register base
Return values:
rcReturn status code

Definition at line 652 of file smscusb.c.

References smscusb_mac::addr, ETH_ALEN, smscusb_mac::h, smscusb_mac::l, net_device::ll_addr, memcpy(), memset(), netdev, smscusb_device::netdev, smscusb_mac::raw, rc, smscusb_raw_writel(), SMSCUSB_RX_ADDRH, and SMSCUSB_RX_ADDRL.

Referenced by lan78xx_open(), smsc75xx_open(), and smsc95xx_open().

                                                   {
        struct net_device *netdev = smscusb->netdev;
        union smscusb_mac mac;
        int rc;

        /* Copy MAC address */
        memset ( &mac, 0, sizeof ( mac ) );
        memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );

        /* Write MAC address high register */
        if ( ( rc = smscusb_raw_writel ( smscusb,
                                         ( addr_base + SMSCUSB_RX_ADDRH ),
                                         mac.addr.h ) ) != 0 )
                return rc;

        /* Write MAC address low register */
        if ( ( rc = smscusb_raw_writel ( smscusb,
                                         ( addr_base + SMSCUSB_RX_ADDRL ),
                                         mac.addr.l ) ) != 0 )
                return rc;

        return 0;
}
int smscusb_set_filter ( struct smscusb_device smscusb,
unsigned int  filt_base 
)

Set receive filter.

Parameters:
smscusbSMSC USB device
filt_baseReceive filter register base
Return values:
rcReturn status code

Definition at line 684 of file smscusb.c.

References smscusb_mac::addr, cpu_to_le32, ETH_ALEN, smscusb_mac::h, smscusb_mac::l, net_device::ll_addr, memcpy(), memset(), netdev, smscusb_device::netdev, smscusb_mac::raw, rc, SMSCUSB_ADDR_FILTH, SMSCUSB_ADDR_FILTH_VALID, SMSCUSB_ADDR_FILTL, and smscusb_raw_writel().

Referenced by lan78xx_open(), and smsc75xx_open().

                                                  {
        struct net_device *netdev = smscusb->netdev;
        union smscusb_mac mac;
        int rc;

        /* Copy MAC address */
        memset ( &mac, 0, sizeof ( mac ) );
        memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
        mac.addr.h |= cpu_to_le32 ( SMSCUSB_ADDR_FILTH_VALID );

        /* Write MAC address perfect filter high register */
        if ( ( rc = smscusb_raw_writel ( smscusb,
                                         ( filt_base + SMSCUSB_ADDR_FILTH(0) ),
                                         mac.addr.h ) ) != 0 )
                return rc;

        /* Write MAC address perfect filter low register */
        if ( ( rc = smscusb_raw_writel ( smscusb,
                                         ( filt_base + SMSCUSB_ADDR_FILTL(0) ),
                                         mac.addr.l ) ) != 0 )
                return rc;

        return 0;
}
static void smscusb_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 724 of file smscusb.c.

References container_of, io_buffer::data, DBGC, DBGC_HDA, done, free_iob(), smscusb_interrupt::int_sts, smscusb_device::int_sts, usbnet_device::intr, intr, iob_len(), le32_to_cpu, netdev, smscusb_device::netdev, netdev_rx_err(), NULL, usb_endpoint::open, profile_start(), profile_stop(), strerror(), and smscusb_device::usbnet.

                                                                      {
        struct smscusb_device *smscusb =
                container_of ( ep, struct smscusb_device, usbnet.intr );
        struct net_device *netdev = smscusb->netdev;
        struct smscusb_interrupt *intr;

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

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

        /* Record USB errors against the network device */
        if ( rc != 0 ) {
                DBGC ( smscusb, "SMSCUSB %p interrupt failed: %s\n",
                       smscusb, strerror ( rc ) );
                DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
                netdev_rx_err ( netdev, NULL, rc );
                goto done;
        }

        /* Extract interrupt data */
        if ( iob_len ( iobuf ) != sizeof ( *intr ) ) {
                DBGC ( smscusb, "SMSCUSB %p malformed interrupt\n",
                       smscusb );
                DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
                netdev_rx_err ( netdev, NULL, rc );
                goto done;
        }
        intr = iobuf->data;

        /* Record interrupt status */
        smscusb->int_sts = le32_to_cpu ( intr->int_sts );
        profile_stop ( &smscusb_intr_profiler );

 done:
        /* Free I/O buffer */
        free_iob ( iobuf );
}
static void smscusb_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 778 of file smscusb.c.

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

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

        /* Report TX completion */
        netdev_tx_complete_err ( netdev, iobuf, rc );
}

Variable Documentation

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

Interrupt completion profiler.

Definition at line 42 of file smscusb.c.

Initial value:
 {
        .read = smscusb_mii_read,
        .write = smscusb_mii_write,
}

MII operations.

Definition at line 568 of file smscusb.c.

Initial value:
 {
        .complete = smscusb_intr_complete,
}

Interrupt endpoint operations.

Definition at line 767 of file smscusb.c.

Initial value:
 {
        .complete = smscusb_out_complete,
}

Bulk OUT endpoint operations.

Definition at line 789 of file smscusb.c.