iPXE
Functions | Variables
dm96xx.c File Reference

Davicom DM96xx USB Ethernet driver. More...

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

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static int dm96xx_reset (struct dm96xx_device *dm96xx)
 Reset device.
static int dm96xx_read_mac (struct dm96xx_device *dm96xx, uint8_t *mac)
 Read MAC address.
static int dm96xx_write_mac (struct dm96xx_device *dm96xx, uint8_t *mac)
 Write MAC address.
static void dm96xx_link_nsr (struct dm96xx_device *dm96xx, unsigned int nsr)
 Update link status based on network status register.
static int dm96xx_check_link (struct dm96xx_device *dm96xx)
 Get link status.
static int dm96xx_rx_mode (struct dm96xx_device *dm96xx)
 Set DM9601-compatible RX header mode.
static void dm96xx_intr_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete interrupt transfer.
static void dm96xx_in_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete bulk IN transfer.
static int dm96xx_out_transmit (struct dm96xx_device *dm96xx, struct io_buffer *iobuf)
 Transmit packet.
static void dm96xx_out_complete (struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
 Complete bulk OUT transfer.
static int dm96xx_open (struct net_device *netdev)
 Open network device.
static void dm96xx_close (struct net_device *netdev)
 Close network device.
static int dm96xx_transmit (struct net_device *netdev, struct io_buffer *iobuf)
 Transmit packet.
static void dm96xx_poll (struct net_device *netdev)
 Poll for completed and received packets.
static int dm96xx_probe (struct usb_function *func, struct usb_configuration_descriptor *config)
 Probe device.
static void dm96xx_remove (struct usb_function *func)
 Remove device.

Variables

static struct
usb_endpoint_driver_operations 
dm96xx_intr_operations
 Interrupt endpoint operations.
static struct
usb_endpoint_driver_operations 
dm96xx_in_operations
 Bulk IN endpoint operations.
static struct
usb_endpoint_driver_operations 
dm96xx_out_operations
 Bulk OUT endpoint operations.
static struct net_device_operations dm96xx_operations
 DM96xx network device operations.
static struct usb_device_id dm96xx_ids []
 DM96xx device IDs.
struct usb_driver dm96xx_driver __usb_driver
 Davicom DM96xx driver.

Detailed Description

Davicom DM96xx USB Ethernet driver.

Definition in file dm96xx.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static int dm96xx_reset ( struct dm96xx_device dm96xx) [static]

Reset device.

Parameters:
dm96xxDM96xx device
Return values:
rcReturn status code

Definition at line 53 of file dm96xx.c.

References DBGC, DM96XX_NCR, DM96XX_NCR_RST, dm96xx_read_register(), DM96XX_RESET_DELAY_US, dm96xx_write_register(), EIO, rc, strerror(), and udelay().

Referenced by dm96xx_close(), and dm96xx_probe().

                                                         {
        int ncr;
        int rc;

        /* Reset device */
        if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_NCR,
                                            DM96XX_NCR_RST ) ) != 0 ) {
                DBGC ( dm96xx, "DM96XX %p could not reset: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }

        /* Wait for reset to complete */
        udelay ( DM96XX_RESET_DELAY_US );

        /* Check that reset has completed */
        ncr = dm96xx_read_register ( dm96xx, DM96XX_NCR );
        if ( ncr < 0 ) {
                rc = ncr;
                DBGC ( dm96xx, "DM96XX %p failed to reset: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }
        if ( ncr & DM96XX_NCR_RST ) {
                DBGC ( dm96xx, "DM96XX %p failed to reset (NCR=%#02x)\n",
                       dm96xx, ncr );
                return -EIO;
        }

        return 0;
}
static int dm96xx_read_mac ( struct dm96xx_device dm96xx,
uint8_t mac 
) [static]

Read MAC address.

Parameters:
dm96xxDM96xx device
macMAC address to fill in
Return values:
rcReturn status code

Definition at line 92 of file dm96xx.c.

References DBGC, DM96XX_PAR, dm96xx_read_registers(), ETH_ALEN, rc, and strerror().

Referenced by dm96xx_probe().

                                                                          {
        int rc;

        /* Read MAC address */
        if ( ( rc = dm96xx_read_registers ( dm96xx, DM96XX_PAR, mac,
                                            ETH_ALEN ) ) != 0 ) {
                DBGC ( dm96xx, "DM96XX %p could not read MAC address: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static int dm96xx_write_mac ( struct dm96xx_device dm96xx,
uint8_t mac 
) [static]

Write MAC address.

Parameters:
dm96xxDM96xx device
macMAC address
Return values:
rcReturn status code

Definition at line 113 of file dm96xx.c.

References DBGC, DM96XX_PAR, dm96xx_write_registers(), ETH_ALEN, rc, and strerror().

Referenced by dm96xx_open().

                                                                           {
        int rc;

        /* Write MAC address */
        if ( ( rc = dm96xx_write_registers ( dm96xx, DM96XX_PAR, mac,
                                             ETH_ALEN ) ) != 0 ) {
                DBGC ( dm96xx, "DM96XX %p could not write MAC address: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void dm96xx_link_nsr ( struct dm96xx_device dm96xx,
unsigned int  nsr 
) [static]

Update link status based on network status register.

Parameters:
dm96xxDM96xx device
nsrNetwork status register

Definition at line 133 of file dm96xx.c.

References DM96XX_NSR_LINKST, netdev, dm96xx_device::netdev, netdev_link_down(), netdev_link_ok(), and netdev_link_up().

Referenced by dm96xx_check_link(), and dm96xx_intr_complete().

                                                                               {
        struct net_device *netdev = dm96xx->netdev;

        if ( nsr & DM96XX_NSR_LINKST ) {
                if ( ! netdev_link_ok ( netdev ) )
                        netdev_link_up ( netdev );
        } else {
                if ( netdev_link_ok ( netdev ) )
                        netdev_link_down ( netdev );
        }
}
static int dm96xx_check_link ( struct dm96xx_device dm96xx) [static]

Get link status.

Parameters:
dm96xxDM96xx device
Return values:
rcReturn status code

Definition at line 151 of file dm96xx.c.

References DBGC, dm96xx_link_nsr(), DM96XX_NSR, dm96xx_read_register(), rc, and strerror().

Referenced by dm96xx_open(), and dm96xx_probe().

                                                              {
        int nsr;
        int rc;

        /* Read network status register */
        nsr = dm96xx_read_register ( dm96xx, DM96XX_NSR );
        if ( nsr < 0 ) {
                rc = nsr;
                DBGC ( dm96xx, "DM96XX %p could not read network status: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }

        /* Update link status */
        dm96xx_link_nsr ( dm96xx, nsr );

        return 0;
}
static int dm96xx_rx_mode ( struct dm96xx_device dm96xx) [static]

Set DM9601-compatible RX header mode.

Parameters:
dm96xxDM96xx device
Return values:
rcReturn status code

Definition at line 176 of file dm96xx.c.

References DBGC, DM96XX_CHIPR, DM96XX_CHIPR_9601, DM96XX_MODE_CTL, DM96XX_MODE_CTL_MODE, dm96xx_read_register(), dm96xx_write_register(), rc, and strerror().

Referenced by dm96xx_open().

                                                           {
        int chipr;
        int mode_ctl;
        int rc;

        /* Get chip revision */
        chipr = dm96xx_read_register ( dm96xx, DM96XX_CHIPR );
        if ( chipr < 0 ) {
                rc = chipr;
                DBGC ( dm96xx, "DM96XX %p could not read chip revision: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }

        /* Do nothing if device is a DM9601 anyway */
        if ( chipr == DM96XX_CHIPR_9601 )
                return 0;

        /* Read current mode control */
        mode_ctl = dm96xx_read_register ( dm96xx, DM96XX_MODE_CTL );
        if ( mode_ctl < 0 ) {
                rc = mode_ctl;
                DBGC ( dm96xx, "DM96XX %p could not read mode control: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }

        /* Write mode control */
        mode_ctl &= ~DM96XX_MODE_CTL_MODE;
        if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_MODE_CTL,
                                            mode_ctl ) ) != 0 ) {
                DBGC ( dm96xx, "DM96XX %p could not write mode control: %s\n",
                       dm96xx, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void dm96xx_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 229 of file dm96xx.c.

References container_of, io_buffer::data, DBGC, DBGC_HDA, dm96xx_link_nsr(), done, EINVAL, free_iob(), usbnet_device::intr, intr, iob_len(), len, netdev, dm96xx_device::netdev, netdev_rx_err(), dm96xx_interrupt::nsr, NULL, usb_endpoint::open, strerror(), and dm96xx_device::usbnet.

                                                                     {
        struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
                                                      usbnet.intr );
        struct net_device *netdev = dm96xx->netdev;
        struct dm96xx_interrupt *intr;
        size_t len = iob_len ( iobuf );

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

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

        /* Extract message header */
        if ( len < sizeof ( *intr ) ) {
                DBGC ( dm96xx, "DM96XX %p underlength interrupt:\n", dm96xx );
                DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
                netdev_rx_err ( netdev, NULL, -EINVAL );
                goto done;
        }
        intr = iobuf->data;

        /* Update link status */
        dm96xx_link_nsr ( dm96xx, intr->nsr );

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

References container_of, io_buffer::data, DBGC, DBGC_HDA, DM96XX_RSR_MF, EINVAL, EIO, free_iob(), header, usbnet_device::in, iob_disown, iob_len(), iob_pull, iob_unput, netdev, dm96xx_device::netdev, netdev_rx(), netdev_rx_err(), usb_endpoint::open, dm96xx_rx_header::rsr, strerror(), and dm96xx_device::usbnet.

                                                                   {
        struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
                                                      usbnet.in );
        struct net_device *netdev = dm96xx->netdev;
        struct dm96xx_rx_header *header;

        /* Ignore packets cancelled when the endpoint closes */
        if ( ! ep->open ) {
                free_iob ( iobuf );
                return;
        }

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

        /* Sanity check */
        if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
                DBGC ( dm96xx, "DM96XX %p underlength bulk IN\n", dm96xx );
                DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EINVAL;
                goto err;
        }

        /* Strip header and CRC */
        header = iobuf->data;
        iob_pull ( iobuf, sizeof ( *header ) );
        iob_unput ( iobuf, 4 /* CRC */ );

        /* Check status */
        if ( header->rsr & ~DM96XX_RSR_MF ) {
                DBGC ( dm96xx, "DM96XX %p receive error %02x:\n",
                       dm96xx, header->rsr );
                DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
                rc = -EIO;
                goto err;
        }

        /* Hand off to network stack */
        netdev_rx ( netdev, iob_disown ( iobuf ) );
        return;

 err:
        /* Hand off to network stack */
        netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
static int dm96xx_out_transmit ( struct dm96xx_device dm96xx,
struct io_buffer iobuf 
) [static]

Transmit packet.

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

Definition at line 342 of file dm96xx.c.

References cpu_to_le16, header, iob_ensure_headroom(), iob_len(), iob_push, dm96xx_tx_header::len, len, usbnet_device::out, rc, usb_stream(), and dm96xx_device::usbnet.

Referenced by dm96xx_transmit().

                                                           {
        struct dm96xx_tx_header *header;
        size_t len = iob_len ( iobuf );
        int rc;

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

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

        return 0;
}
static void dm96xx_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 368 of file dm96xx.c.

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

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

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

Open network device.

Parameters:
netdevNetwork device
Return values:
rcReturn status code

Definition at line 396 of file dm96xx.c.

References DBGC, dm96xx_check_link(), DM96XX_RCR, DM96XX_RCR_ALL, DM96XX_RCR_PRMSC, DM96XX_RCR_RUNT, DM96XX_RCR_RXEN, dm96xx_rx_mode(), dm96xx_write_mac(), dm96xx_write_register(), net_device::ll_addr, net_device::priv, rc, strerror(), dm96xx_device::usbnet, usbnet_close(), and usbnet_open().

                                                     {
        struct dm96xx_device *dm96xx = netdev->priv;
        unsigned int rcr;
        int rc;

        /* Set DM9601-compatible RX header mode */
        if ( ( rc = dm96xx_rx_mode ( dm96xx ) ) != 0 )
                goto err_rx_mode;

        /* Write MAC address */
        if ( ( rc = dm96xx_write_mac ( dm96xx, netdev->ll_addr ) ) != 0 )
                goto err_write_mac;

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

        /* Set receive filters */
        rcr = ( DM96XX_RCR_ALL | DM96XX_RCR_RUNT | DM96XX_RCR_PRMSC |
                DM96XX_RCR_RXEN );
        if ( ( rc = dm96xx_write_register ( dm96xx, DM96XX_RCR, rcr ) ) != 0 ) {
                DBGC ( dm96xx, "DM96XX %p could not write receive filters: "
                       "%s\n", dm96xx, strerror ( rc ) );
                goto err_write_rcr;
        }

        /* Update link status */
        if ( ( rc = dm96xx_check_link ( dm96xx ) ) != 0 )
                goto err_check_link;

        return 0;

 err_check_link:
 err_write_rcr:
        usbnet_close ( &dm96xx->usbnet );
 err_open:
 err_write_mac:
 err_rx_mode:
        return rc;
}
static void dm96xx_close ( struct net_device netdev) [static]

Close network device.

Parameters:
netdevNetwork device

Definition at line 445 of file dm96xx.c.

References dm96xx_reset(), net_device::priv, dm96xx_device::usbnet, and usbnet_close().

                                                       {
        struct dm96xx_device *dm96xx = netdev->priv;

        /* Close USB network device */
        usbnet_close ( &dm96xx->usbnet );

        /* Reset device */
        dm96xx_reset ( dm96xx );
}
static int dm96xx_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 462 of file dm96xx.c.

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

                                                       {
        struct dm96xx_device *dm96xx = netdev->priv;
        int rc;

        /* Transmit packet */
        if ( ( rc = dm96xx_out_transmit ( dm96xx, iobuf ) ) != 0 )
                return rc;

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

Poll for completed and received packets.

Parameters:
netdevNetwork device

Definition at line 479 of file dm96xx.c.

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

                                                      {
        struct dm96xx_device *dm96xx = netdev->priv;
        int rc;

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

        /* Refill endpoints */
        if ( ( rc = usbnet_refill ( &dm96xx->usbnet ) ) != 0 )
                netdev_rx_err ( netdev, NULL, rc );
}
static int dm96xx_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 513 of file dm96xx.c.

References alloc_etherdev(), dm96xx_device::bus, usb_hub::bus, DBGC, net_device::dev, usb_function::dev, dm96xx_check_link(), DM96XX_IN_MAX_FILL, DM96XX_IN_MTU, DM96XX_INTR_MAX_FILL, dm96xx_read_mac(), dm96xx_reset(), ENOMEM, usb_port::hub, net_device::hw_addr, usbnet_device::in, usbnet_device::intr, memset(), usb_function::name, netdev, dm96xx_device::netdev, netdev_init(), netdev_nullify(), netdev_put(), usb_device::port, net_device::priv, rc, register_netdev(), strerror(), unregister_netdev(), dm96xx_device::usb, usb_function::usb, usb_func_set_drvdata(), usb_refill_init(), dm96xx_device::usbnet, usbnet_describe(), and usbnet_init().

                                                                     {
        struct usb_device *usb = func->usb;
        struct net_device *netdev;
        struct dm96xx_device *dm96xx;
        int rc;

        /* Allocate and initialise structure */
        netdev = alloc_etherdev ( sizeof ( *dm96xx ) );
        if ( ! netdev ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        netdev_init ( netdev, &dm96xx_operations );
        netdev->dev = &func->dev;
        dm96xx = netdev->priv;
        memset ( dm96xx, 0, sizeof ( *dm96xx ) );
        dm96xx->usb = usb;
        dm96xx->bus = usb->port->hub->bus;
        dm96xx->netdev = netdev;
        usbnet_init ( &dm96xx->usbnet, func, &dm96xx_intr_operations,
                      &dm96xx_in_operations, &dm96xx_out_operations );
        usb_refill_init ( &dm96xx->usbnet.intr, 0, 0, DM96XX_INTR_MAX_FILL );
        usb_refill_init ( &dm96xx->usbnet.in, 0, DM96XX_IN_MTU,
                          DM96XX_IN_MAX_FILL );
        DBGC ( dm96xx, "DM96XX %p on %s\n", dm96xx, func->name );

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

        /* Reset device */
        if ( ( rc = dm96xx_reset ( dm96xx ) ) != 0 )
                goto err_reset;

        /* Read MAC address */
        if ( ( rc = dm96xx_read_mac ( dm96xx, netdev->hw_addr ) ) != 0 )
                goto err_read_mac;

        /* Get initial link status */
        if ( ( rc = dm96xx_check_link ( dm96xx ) ) != 0 )
                goto err_check_link;

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

        usb_func_set_drvdata ( func, netdev );
        return 0;

        unregister_netdev ( netdev );
 err_register:
 err_check_link:
 err_read_mac:
 err_reset:
 err_describe:
        netdev_nullify ( netdev );
        netdev_put ( netdev );
 err_alloc:
        return rc;
}
static void dm96xx_remove ( struct usb_function func) [static]

Remove device.

Parameters:
funcUSB function

Definition at line 583 of file dm96xx.c.

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

                                                        {
        struct net_device *netdev = usb_func_get_drvdata ( func );

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

Variable Documentation

Initial value:
 {
        .complete = dm96xx_intr_complete,
}

Interrupt endpoint operations.

Definition at line 268 of file dm96xx.c.

Initial value:
 {
        .complete = dm96xx_in_complete,
}

Bulk IN endpoint operations.

Definition at line 331 of file dm96xx.c.

Initial value:
 {
        .complete = dm96xx_out_complete,
}

Bulk OUT endpoint operations.

Definition at line 379 of file dm96xx.c.

Initial value:
 {
        .open           = dm96xx_open,
        .close          = dm96xx_close,
        .transmit       = dm96xx_transmit,
        .poll           = dm96xx_poll,
}

DM96xx network device operations.

Definition at line 492 of file dm96xx.c.

struct usb_device_id dm96xx_ids[] [static]

DM96xx device IDs.

Definition at line 592 of file dm96xx.c.

struct usb_driver dm96xx_driver __usb_driver
Initial value:
 {
        .ids = dm96xx_ids,
        .id_count = ( sizeof ( dm96xx_ids ) / sizeof ( dm96xx_ids[0] ) ),
        .class = USB_CLASS_ID ( USB_ANY_ID, USB_ANY_ID, USB_ANY_ID ),
        .score = USB_SCORE_NORMAL,
        .probe = dm96xx_probe,
        .remove = dm96xx_remove,
}

Davicom DM96xx driver.

Definition at line 666 of file dm96xx.c.