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

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

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

{

board_info_t *dm = to_dm9000_board(dev);

if (dm->ip_summed != ip_summed) {

if (ip_summed == CHECKSUM_NONE)

iow(dm, DM9000_TCCR, 0);

else

iow(dm, DM9000_TCCR, TCCR_IP | TCCR_UDP | TCCR_TCP);

dm->ip_summed = ip_summed;

}

iow(dm, DM9000_TXPLL, pkt_len);

iow(dm, DM9000_TXPLH, pkt_len >> 8);

iow(dm, DM9000_TCR, TCR_TXREQ);

}

static int

dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev)

{

unsigned long flags;

board_info_t *db = netdev_priv(dev);

dm9000_dbg(db, 3, "%s:\n", __func__);

if (db->tx_pkt_cnt > 1)

return NETDEV_TX_BUSY;

spin_lock_irqsave(&db->lock, flags);

writeb(DM9000_MWCMD, db->io_addr);

(db->outblk)(db->io_data, skb->data, skb->len);

dev->stats.tx_bytes += skb->len;

db->tx_pkt_cnt++;

if (db->tx_pkt_cnt == 1) {

dm9000_send_packet(dev, skb->ip_summed, skb->len);

} else {

db->queue_pkt_len = skb->len;

db->queue_ip_summed = skb->ip_summed;

netif_stop_queue(dev);

}

spin_unlock_irqrestore(&db->lock, flags);

dev_kfree_skb(skb);

return NETDEV_TX_OK;

}

static void dm9000_tx_done(struct net_device *dev, board_info_t *db)

{

int tx_status = ior(db, DM9000_NSR);

if (tx_status & (NSR_TX2END | NSR_TX1END)) {

db->tx_pkt_cnt--;

dev->stats.tx_packets++;

if (netif_msg_tx_done(db))

dev_dbg(db->dev, "tx done, NSR x\n", tx_status);

if (db->tx_pkt_cnt > 0)

dm9000_send_packet(dev, db->queue_ip_summed,

db->queue_pkt_len);

netif_wake_queue(dev);

}

}

struct dm9000_rxhdr {

u8 RxPktReady;

u8 RxStatus;

__le16 RxLen;

} __attribute__((__packed__));

static void

dm9000_rx(struct net_device *dev)

{

board_info_t *db = netdev_priv(dev);

struct dm9000_rxhdr rxhdr;

struct sk_buff *skb;

u8 rxbyte, *rdptr;

bool GoodPacket;

int RxLen;

do {

ior(db, DM9000_MRCMDX);

rxbyte = readb(db->io_data);

if (rxbyte & DM9000_PKT_ERR) {

dev_warn(db->dev, "status check fail: %d\n", rxbyte);

iow(db, DM9000_RCR, 0x00);

iow(db, DM9000_ISR, IMR_PAR);

return;

}

if (!(rxbyte & DM9000_PKT_RDY))

return;

GoodPacket = true;

writeb(DM9000_MRCMD, db->io_addr);

(db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr));

RxLen = le16_to_cpu(rxhdr.RxLen);

if (netif_msg_rx_status(db))

dev_dbg(db->dev, "RX: status x, length x\n",

rxhdr.RxStatus, RxLen);

if (RxLen < 0x40) {

GoodPacket = false;

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "RX: Bad Packet (runt)\n");

}

if (RxLen > DM9000_PKT_MAX) {

dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);

}

if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |

RSR_PLE | RSR_RWTO |

RSR_LCS | RSR_RF)) {

GoodPacket = false;

if (rxhdr.RxStatus & RSR_FOE) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "fifo error\n");

dev->stats.rx_fifo_errors++;

}

if (rxhdr.RxStatus & RSR_CE) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "crc error\n");

dev->stats.rx_crc_errors++;

}

if (rxhdr.RxStatus & RSR_RF) {

if (netif_msg_rx_err(db))

dev_dbg(db->dev, "length error\n");

dev->stats.rx_length_errors++;

}

}

if (GoodPacket &&

((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {

skb_reserve(skb, 2);

rdptr = (u8 *) skb_put(skb, RxLen - 4);

(db->inblk)(db->io_data, rdptr, RxLen);

dev->stats.rx_bytes += RxLen;

skb->protocol = eth_type_trans(skb, dev);

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

网站地图

Top