微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM-Linux驱动--DM9000网卡驱动分析(四)

ARM-Linux驱动--DM9000网卡驱动分析(四)

时间:11-20 来源:互联网 点击:

u32 ret;

if (dm->flags & DM9000_PLATF_EXT_PHY)

ret = mii_link_ok(&dm->mii);

else

ret = dm9000_read_locked(dm, DM9000_NSR) & NSR_LINKST ? 1 : 0;

return ret;

}

#define DM_EEPROM_MAGIC (0x444D394B)

static int dm9000_get_eeprom_len(struct net_device *dev)

{

return 128;

}

static int dm9000_get_eeprom(struct net_device *dev,

struct ethtool_eeprom *ee, u8 *data)

{

board_info_t *dm = to_dm9000_board(dev);

int offset = ee->offset;

int len = ee->len;

int i;

if ((len & 1) != 0 || (offset & 1) != 0)

return -EINVAL;

if (dm->flags & DM9000_PLATF_NO_EEPROM)

return -ENOENT;

ee->magic = DM_EEPROM_MAGIC;

for (i = 0; i < len; i += 2)

dm9000_read_eeprom(dm, (offset + i) / 2, data + i);

return 0;

}

static int dm9000_set_eeprom(struct net_device *dev,

struct ethtool_eeprom *ee, u8 *data)

{

board_info_t *dm = to_dm9000_board(dev);

int offset = ee->offset;

int len = ee->len;

int i;

if ((len & 1) != 0 || (offset & 1) != 0)

return -EINVAL;

if (dm->flags & DM9000_PLATF_NO_EEPROM)

return -ENOENT;

if (ee->magic != DM_EEPROM_MAGIC)

return -EINVAL;

for (i = 0; i < len; i += 2)

dm9000_write_eeprom(dm, (offset + i) / 2, data + i);

return 0;

}

static void dm9000_get_wol(struct net_device *dev, struct ethtool_wolinfo *w)

{

board_info_t *dm = to_dm9000_board(dev);

memset(w, 0, sizeof(struct ethtool_wolinfo));

w->supported = dm->wake_supported ? WAKE_MAGIC : 0;

w->wolopts = dm->wake_state;

}

static int dm9000_set_wol(struct net_device *dev, struct ethtool_wolinfo *w)

{

board_info_t *dm = to_dm9000_board(dev);

unsigned long flags;

u32 opts = w->wolopts;

u32 wcr = 0;

if (!dm->wake_supported)

return -EOPNOTSUPP;

if (opts & ~WAKE_MAGIC)

return -EINVAL;

if (opts & WAKE_MAGIC)

wcr |= WCR_MAGICEN;

mutex_lock(&dm->addr_lock);

spin_lock_irqsave(&dm->lock, flags);

iow(dm, DM9000_WCR, wcr);

spin_unlock_irqrestore(&dm->lock, flags);

mutex_unlock(&dm->addr_lock);

if (dm->wake_state != opts) {

if (!dm->wake_state)

set_irq_wake(dm->irq_wake, 1);

else if (dm->wake_state & !opts)

set_irq_wake(dm->irq_wake, 0);

}

dm->wake_state = opts;

return 0;

}

static const struct ethtool_ops dm9000_ethtool_ops = {

.get_drvinfo = dm9000_get_drvinfo,

.get_settings = dm9000_get_settings,

.set_settings = dm9000_set_settings,

.get_msglevel = dm9000_get_msglevel,

.set_msglevel = dm9000_set_msglevel,

.nway_reset = dm9000_nway_reset,

.get_link = dm9000_get_link,

.get_wol = dm9000_get_wol,

.set_wol = dm9000_set_wol,

.get_eeprom_len = dm9000_get_eeprom_len,

.get_eeprom = dm9000_get_eeprom,

.set_eeprom = dm9000_set_eeprom,

.get_rx_csum = dm9000_get_rx_csum,

.set_rx_csum = dm9000_set_rx_csum,

.get_tx_csum = ethtool_op_get_tx_csum,

.set_tx_csum = dm9000_set_tx_csum,

};

static void dm9000_show_carrier(board_info_t *db,

unsigned carrier, unsigned nsr)

{

struct net_device *ndev = db->ndev;

unsigned ncr = dm9000_read_locked(db, DM9000_NCR);

if (carrier)

dev_info(db->dev, "%s: link up, %dMbps, %s-duplex, no LPA\n",

ndev->name, (nsr & NSR_SPEED) ? 10 : 100,

(ncr & NCR_FDX) ? "full" : "half");

else

dev_info(db->dev, "%s: link down\n", ndev->name);

}

static void

dm9000_poll_work(struct work_struct *w)

{

struct delayed_work *dw = to_delayed_work(w);

board_info_t *db = container_of(dw, board_info_t, phy_poll);

struct net_device *ndev = db->ndev;

if (db->flags & DM9000_PLATF_SIMPLE_PHY &&

!(db->flags & DM9000_PLATF_EXT_PHY)) {

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top