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

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

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

unsigned nsr = dm9000_read_locked(db, DM9000_NSR);

unsigned old_carrier = netif_carrier_ok(ndev) ? 1 : 0;

unsigned new_carrier;

new_carrier = (nsr & NSR_LINKST) ? 1 : 0;

if (old_carrier != new_carrier) {

if (netif_msg_link(db))

dm9000_show_carrier(db, new_carrier, nsr);

if (!new_carrier)

netif_carrier_off(ndev);

else

netif_carrier_on(ndev);

}

} else

mii_check_media(&db->mii, netif_msg_link(db), 0);

if (netif_running(ndev))

dm9000_schedule_poll(db);

}

static void

dm9000_release_board(struct platform_device *pdev, struct board_info *db)

{

iounmap(db->io_addr);

iounmap(db->io_data);

release_resource(db->data_req);

kfree(db->data_req);

release_resource(db->addr_req);

kfree(db->addr_req);

}

static unsigned char dm9000_type_to_char(enum dm9000_type type)

{

switch (type) {

case TYPE_DM9000E: return e;

case TYPE_DM9000A: return a;

case TYPE_DM9000B: return b;

}

return ?;

}

static void

dm9000_hash_table_unlocked(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

struct netdev_hw_addr *ha;

int i, oft;

u32 hash_val;

u16 hash_table[4];

u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN;

dm9000_dbg(db, 1, "entering %s\n", __func__);

for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++)

iow(db, oft, dev->dev_addr[i]);

for (i = 0; i < 4; i++)

hash_table[i] = 0x0;

hash_table[3] = 0x8000;

if (dev->flags & IFF_PROMISC)

rcr |= RCR_PRMSC;

if (dev->flags & IFF_ALLMULTI)

rcr |= RCR_ALL;

netdev_for_each_mc_addr(ha, dev) {

hash_val = ether_crc_le(6, ha->addr) & 0x3f;

hash_table[hash_val / 16] |= (u16) 1 < (hash_val % 16);

}

for (i = 0, oft = DM9000_MAR; i < 4; i++) {

iow(db, oft++, hash_table[i]);

iow(db, oft++, hash_table[i] >> 8);

}

iow(db, DM9000_RCR, rcr);

}

static void

dm9000_hash_table(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

unsigned long flags;

spin_lock_irqsave(&db->lock, flags);

dm9000_hash_table_unlocked(dev);

spin_unlock_irqrestore(&db->lock, flags);

}

static void

dm9000_init_dm9000(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

unsigned int imr;

unsigned int ncr;

dm9000_dbg(db, 1, "entering %s\n", __func__);

db->io_mode = ior(db, DM9000_ISR) >> 6;

dm9000_set_rx_csum_unlocked(dev, db->rx_csum);

iow(db, DM9000_GPR, 0);

iow(db, DM9000_GPCR, GPCR_GEP_CNTL);

iow(db, DM9000_GPR, 0);

ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;

if (db->wake_supported)

ncr |= NCR_WAKEEN;

iow(db, DM9000_NCR, ncr);

iow(db, DM9000_TCR, 0);

iow(db, DM9000_BPTR, 0x3f);

iow(db, DM9000_FCR, 0xff);

iow(db, DM9000_SMCR, 0);

iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);

iow(db, DM9000_ISR, ISR_CLR_STATUS);

dm9000_hash_table_unlocked(dev);

imr = IMR_PAR | IMR_PTM | IMR_PRM;

if (db->type != TYPE_DM9000E)

imr |= IMR_LNKCHNG;

db->imr_all = imr;

iow(db, DM9000_IMR, imr);

db->tx_pkt_cnt = 0;

db->queue_pkt_len = 0;

dev->trans_start = jiffies;

}

static void dm9000_timeout(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

u8 reg_save;

unsigned long flags;

reg_save = readb(db->io_addr);

spin_lock_irqsave(&db->lock, flags);

netif_stop_queue(dev);

dm9000_reset(db);

dm9000_init_dm9000(dev);

dev->trans_start = jiffies;

netif_wake_queue(dev);

writeb(reg_save, db->io_addr);

spin_unlock_irqrestore(&db->lock, flags);

}

static void dm9000_send_packet(struct net_device *dev,

int ip_summed,

u16 pkt_len)

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

网站地图

Top