分类: LINUX
2015-03-18 16:11:52
Analy the skelet of netdriver (Isa-skeleton.c)
init
//private data
struct net_local {
struct net_device_stats stats;
long open_time; /* Useless example local info. */
spinlock_t lock;
};
int init_module(void)
//create function
->alloc_etherdev(sizeof(struct net_local));
->alloc_netdev(sizeof_priv, "eth%d", ether_setup);
->p = kzalloc(alloc_size, GFP_KERNEL);
->setup(dev);
//void ether_setup(struct net_device *dev)
{
dev->change_mtu = eth_change_mtu;
dev->hard_header = eth_header;
dev->rebuild_header = eth_rebuild_header;
dev->set_mac_address = eth_mac_addr;
dev->hard_header_cache = eth_header_cache;
dev->header_cache_update= eth_header_cache_update;
dev->hard_header_parse = eth_header_parse;
dev->type = ARPHRD_ETHER;
dev->hard_header_len = ETH_HLEN;
dev->mtu = ETH_DATA_LEN;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 1000; /* Ethernet wants good queues */
dev->flags = IFF_BROADCAST|IFF_MULTICAST;
memset(dev->broadcast, 0xFF, ETH_ALEN);
}
//get resource from platform_device
->dev->base_addr = io;
->dev->irq = irq;
->dev->dma = dma;
->dev->mem_start = mem;
//real work
->do_netcard_probe(dev)
->netcard_probe1(dev, base_addr)
//fill the net_device object
->request_region(ioaddr, NETCARD_IO_EXTENT, cardname)
->request_irq(dev->irq, &net_interrupt, 0, cardname, dev);
->request_dma(dev->dma, cardname)
->dev->open = net_open;
->dev->stop = net_close;
->dev->hard_start_xmit = net_send_packet;
->dev->get_stats = net_get_stats;
->dev->set_multicast_list = &set_multicast_list;
-> dev->tx_timeout = &net_tx_timeout;
->dev->watchdog_timeo = MY_TX_TIMEOUT;
//Take a completed network device structure and add it to the kernel interfaces.
->register_netdev(dev);
->dev_alloc_name(dev, dev->name)
->register_netdevice(dev);
->netdev_register_sysfs(dev);
->dev_init_scheduler(dev);
Net_open
net_open(struct net_device *dev)
->request_irq(dev->irq, &net_interrupt, 0, cardname, dev)
->request_dma(dev->dma, cardname)
->chipset_init(dev, 1);
-> np->open_time = jiffies;
->netif_start_queue(dev);
->clear_bit(__LINK_STATE_XOFF, &dev->state);
Send data
net_send_packet(struct sk_buff *skb, struct net_device *dev)(isa-skeleton.c)
->spin_lock_irq(&np->lock);
//force the hard to send
//touch the interrupt?????
->add_to_tx_ring(np, skb, length);
->dev->trans_start = jiffies;
->if (tx_full(dev)) netif_stop_queue(dev);
interrupt
static irqreturn_t net_interrupt(int irq, void *dev_id)
//receicve
->if (status & RX_INTR)
/* Got a packet(s). */
net_rx(dev);
->struct sk_buff *skb;
lp->stats.rx_bytes+=pkt_len;
skb = dev_alloc_skb(pkt_len);
skb->dev = dev;
insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
netif_rx(skb);
dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
}
//transmit
->if (status & TX_INTR) {
/* Transmit complete. */
net_tx(dev);
//cpu put data to mac fifo
->while (tx_entry_is_sent(np, entry)) {
struct sk_buff *skb = np->skbs[entry];
np->stats.tx_bytes += skb->len;
dev_kfree_skb_irq (skb);
entry = next_tx_entry(np, entry);
}