Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2209081
  • 博文数量: 668
  • 博客积分: 10016
  • 博客等级: 上将
  • 技术积分: 8588
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-29 19:22
文章分类

全部博文(668)

文章存档

2011年(1)

2010年(2)

2009年(273)

2008年(392)

分类:

2009-01-01 08:43:01

前面讨论了probe函数和open函数,下面继续。

内核发送数据在底层是通过dmfe_start_xmit函数来实现的
static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
        board_info_t *db = (board_info_t *)dev->priv;
        char * data_ptr;
        int i, tmplen;
        if(db->Speed == 10)
                {if (db->tx_pkt_cnt >= 1) return 1;}
        else
                {if (db->tx_pkt_cnt >= 2) return 1;}
        
        /* packet counting */
        db->tx_pkt_cnt++;
        db->stats.tx_packets++;
        db->stats.tx_bytes+=skb->len;
        if (db->Speed == 10)
                {if (db->tx_pkt_cnt >= 1) netif_stop_queue(dev);}
        else
                {if (db->tx_pkt_cnt >= 2) netif_stop_queue(dev);}
        /* Disable all interrupt */
        iow(db, DM9KS_IMR, DM9KS_DISINTR);
        /* Set TX length to reg. 0xfc & 0xfd */
        iow(db, DM9KS_TXPLL, (skb->len & 0xff));
        iow(db, DM9KS_TXPLH, (skb->len >> 8) & 0xff);
        /* Move data to TX SRAM */
        data_ptr = (char *)skb->data;
        
        PUTB(DM9KS_MWCMD, db->io_addr); // Write data into SRAM trigger
        switch(db->io_mode)
        {
                case DM9KS_BYTE_MODE:
                        for (i = 0; i  skb->len; i++)
                                PUTB((data_ptr & 0xff), db->io_data);
                        break;
                case DM9KS_WORD_MODE:
                        tmplen = (skb->len + 1) / 2;
                        for (i = 0; i  tmplen; i++)
                                 PUTW(((u16 *)data_ptr), db->io_data);
                         break;
                 case DM9KS_DWORD_MODE:
                         tmplen = (skb->len + 3) / 4; 
                        for (i = 0; i tmplen; i++)
                                PUTL(((u32 *)data_ptr), db->io_data);
                        break;
        }
        
#if !defined(ETRANS)
        /* Issue TX polling command */
        iow(db, DM9KS_TCR, 0x1); /* Cleared after TX complete*/
#endif
        /* Saved the time stamp */
        dev->trans_start = jiffies;
        db->cont_rx_pkt_cnt =0;
        /* Free this SKB */
        dev_kfree_skb(skb);
        /* Re-enable interrupt */
        iow(db, DM9KS_IMR, DM9KS_REGFF);
        return 0;
}
该函数首先判断设备使用的模式,若speed为10,则发送的数据包个数最大为1,若speed为100,则最大个数为2.超过这两个值,函数立即返回。若不超过,则说明可以进行数据发送。然后是更新系统的统计信息。如果待发送包达到上限,则调用netif_stop_queue,告诉内核暂时停止内核与驱动程序间的数据传递。
这些完成后,就可以开始真正的数据传输了。先禁止dm9000a的所有中断,通过写它的Interrupt Mask Register来实现。然后将要传递的数据的长度信息写入TX Packet Length Register中。
需要注意的是char * data_ptr在这里不能理解为一个指向char变量的指针,而应该理解为一个char数组。根据芯片的硬件连接方式,选择字节、半字或者字的方式对数据进行发送。发送完成后,记录下时间戳,并释放skb的空间,然后允许dm9000a的中断,以便继续进行发送或者接收。
stop方法和open函数的方法作用相反,即停止网络设备
static int dmfe_stop(struct net_device *dev)
{
        board_info_t *db = (board_info_t *)dev->priv;
        
        /* deleted timer */
        del_timer(&db->timer);
        netif_stop_queue(dev); 
        /* free interrupt */
        free_irq(dev->irq, dev);
        /* RESET devie */
        phy_write(db, 0x00, 0x8000); /* PHY RESET */
        iow(db, DM9KS_GPR, 0x01); /* Power-Down PHY */
        iow(db, DM9KS_IMR, DM9KS_DISINTR); /* Disable all interrupt */
        iow(db, DM9KS_RXCR, 0x00); /* Disable RX */
        /* Dump Statistic counter */
        return 0;
}
完成的工作主要有删除定时器、释放中断、调用netif_stop_queue()告诉内核停止内核与驱动程序之间的数据交换,最后使dm9000a网卡处于power-down模式。
阅读(665) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~