static int smsc95xx_bind(struct usbnet *dev) { struct smsc95xx_priv *pdata = NULL; int ret; printf(SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n"); ret = usbnet_get_endpoints(dev); if (ret < 0) { netdev_warn(dev->net, "usbnet_get_endpoints failed: %d\n", ret); return ret; } dev->data[0] = (unsigned long)malloc(sizeof(struct smsc95xx_priv)); pdata = (struct smsc95xx_priv *)(dev->data[0]); if (!pdata) { netdev_warn(dev->net, "Unable to allocate struct smsc95xx_priv\n"); return -ENOMEM; } pdata->use_tx_csum = DEFAULT_TX_CSUM_ENABLE; pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE; /* Init all registers */ ret = smsc95xx_reset(dev); dev->edev.get_ethaddr = smsc95xx_get_ethaddr; dev->edev.set_ethaddr = smsc95xx_set_ethaddr; mdiobus_register(&dev->miibus); return 0; }
/** * Close network device * * @v netdev Network device */ static void smsc95xx_close ( struct net_device *netdev ) { struct smsc95xx_device *smsc95xx = netdev->priv; /* Close USB network device */ usbnet_close ( &smsc95xx->usbnet ); /* Dump statistics (for debugging) */ smsc95xx_dump_statistics ( smsc95xx ); /* Reset device */ smsc95xx_reset ( smsc95xx ); }
/** * Open network device * * @v netdev Network device * @ret rc Return status code */ static int smsc95xx_open ( struct net_device *netdev ) { struct smsc95xx_device *smsc95xx = netdev->priv; union smsc95xx_mac mac; int rc; /* Clear stored interrupt status */ smsc95xx->int_sts = 0; /* Copy MAC address */ memset ( &mac, 0, sizeof ( mac ) ); memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN ); /* Configure bulk IN empty response */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_HW_CFG, SMSC95XX_HW_CFG_BIR ) ) != 0 ) goto err_hw_cfg; /* Open USB network device */ if ( ( rc = usbnet_open ( &smsc95xx->usbnet ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not open: %s\n", smsc95xx, strerror ( rc ) ); goto err_open; } /* Configure interrupt endpoint */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_INT_EP_CTL, ( SMSC95XX_INT_EP_CTL_RXDF_EN | SMSC95XX_INT_EP_CTL_PHY_EN ) ) ) != 0 ) goto err_int_ep_ctl; /* Configure bulk IN delay */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_BULK_IN_DLY, SMSC95XX_BULK_IN_DLY_SET ( 0 ) ) ) != 0 ) goto err_bulk_in_dly; /* Configure MAC */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_MAC_CR, ( SMSC95XX_MAC_CR_RXALL | SMSC95XX_MAC_CR_FDPX | SMSC95XX_MAC_CR_MCPAS | SMSC95XX_MAC_CR_PRMS | SMSC95XX_MAC_CR_PASSBAD | SMSC95XX_MAC_CR_TXEN | SMSC95XX_MAC_CR_RXEN ) ) ) != 0 ) goto err_mac_cr; /* Configure transmit datapath */ if ( ( rc = smsc95xx_writel ( smsc95xx, SMSC95XX_TX_CFG, SMSC95XX_TX_CFG_ON ) ) != 0 ) goto err_tx_cfg; /* Write MAC address high register */ if ( ( rc = smsc95xx_raw_writel ( smsc95xx, SMSC95XX_ADDRH, mac.addr.h ) ) != 0 ) goto err_addrh; /* Write MAC address low register */ if ( ( rc = smsc95xx_raw_writel ( smsc95xx, SMSC95XX_ADDRL, mac.addr.l ) ) != 0 ) goto err_addrl; /* Enable PHY interrupts */ if ( ( rc = mii_write ( &smsc95xx->mii, SMSC95XX_MII_PHY_INTR_MASK, ( SMSC95XX_PHY_INTR_ANEG_DONE | SMSC95XX_PHY_INTR_LINK_DOWN ) ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not set PHY interrupt " "mask: %s\n", smsc95xx, strerror ( rc ) ); goto err_phy_intr_mask; } /* Update link status */ smsc95xx_check_link ( smsc95xx ); return 0; err_phy_intr_mask: err_addrl: err_addrh: err_tx_cfg: err_mac_cr: err_bulk_in_dly: err_int_ep_ctl: usbnet_close ( &smsc95xx->usbnet ); err_open: err_hw_cfg: smsc95xx_reset ( smsc95xx ); return rc; }
/** * Probe device * * @v func USB function * @v config Configuration descriptor * @ret rc Return status code */ static int smsc95xx_probe ( struct usb_function *func, struct usb_configuration_descriptor *config ) { struct usb_device *usb = func->usb; struct net_device *netdev; struct smsc95xx_device *smsc95xx; int rc; /* Allocate and initialise structure */ netdev = alloc_etherdev ( sizeof ( *smsc95xx ) ); if ( ! netdev ) { rc = -ENOMEM; goto err_alloc; } netdev_init ( netdev, &smsc95xx_operations ); netdev->dev = &func->dev; smsc95xx = netdev->priv; memset ( smsc95xx, 0, sizeof ( *smsc95xx ) ); smsc95xx->usb = usb; smsc95xx->bus = usb->port->hub->bus; smsc95xx->netdev = netdev; usbnet_init ( &smsc95xx->usbnet, func, &smsc95xx_intr_operations, &smsc95xx_in_operations, &smsc95xx_out_operations ); usb_refill_init ( &smsc95xx->usbnet.intr, 0, 0, SMSC95XX_INTR_MAX_FILL ); usb_refill_init ( &smsc95xx->usbnet.in, ( sizeof ( struct smsc95xx_tx_header ) - sizeof ( struct smsc95xx_rx_header ) ), SMSC95XX_IN_MTU, SMSC95XX_IN_MAX_FILL ); mii_init ( &smsc95xx->mii, &smsc95xx_mii_operations ); DBGC ( smsc95xx, "SMSC95XX %p on %s\n", smsc95xx, func->name ); /* Describe USB network device */ if ( ( rc = usbnet_describe ( &smsc95xx->usbnet, config ) ) != 0 ) { DBGC ( smsc95xx, "SMSC95XX %p could not describe: %s\n", smsc95xx, strerror ( rc ) ); goto err_describe; } /* Reset device */ if ( ( rc = smsc95xx_reset ( smsc95xx ) ) != 0 ) goto err_reset; /* Read MAC address */ if ( ( rc = smsc95xx_fetch_mac ( smsc95xx, netdev->hw_addr ) ) != 0 ) goto err_fetch_mac; /* 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_fetch_mac: err_reset: err_describe: netdev_nullify ( netdev ); netdev_put ( netdev ); err_alloc: return rc; }