drivers/net/ethernet/i825xx/lib82596.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/i825xx/lib82596.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/i825xx/lib82596.c
Extension
.c
Size
39167 bytes
Lines
1424
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops i596_netdev_ops = {
	.ndo_open		= i596_open,
	.ndo_stop		= i596_close,
	.ndo_start_xmit		= i596_start_xmit,
	.ndo_set_rx_mode	= set_multicast_list,
	.ndo_tx_timeout		= i596_tx_timeout,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= i596_poll_controller,
#endif
};

static int i82596_probe(struct net_device *dev)
{
	struct i596_private *lp = netdev_priv(dev);
	int ret;

	/* This lot is ensure things have been cache line aligned. */
	BUILD_BUG_ON(sizeof(struct i596_rfd) != 32);
	BUILD_BUG_ON(sizeof(struct i596_rbd) &  31);
	BUILD_BUG_ON(sizeof(struct tx_cmd)   &  31);
	BUILD_BUG_ON(sizeof(struct i596_tbd) != 32);
#ifndef __LP64__
	BUILD_BUG_ON(sizeof(struct i596_dma) > 4096);
#endif

	if (!dev->base_addr || !dev->irq)
		return -ENODEV;

	dev->netdev_ops = &i596_netdev_ops;
	dev->watchdog_timeo = TX_TIMEOUT;

	memset(lp->dma, 0, sizeof(struct i596_dma));
	lp->dma->scb.command = 0;
	lp->dma->scb.cmd = I596_NULL;
	lp->dma->scb.rfd = I596_NULL;
	spin_lock_init(&lp->lock);

	dma_sync_dev(dev, lp->dma, sizeof(struct i596_dma));

	ret = register_netdev(dev);
	if (ret)
		return ret;

	DEB(DEB_PROBE, printk(KERN_INFO "%s: 82596 at %#3lx, %pM IRQ %d.\n",
			      dev->name, dev->base_addr, dev->dev_addr,
			      dev->irq));
	DEB(DEB_INIT, printk(KERN_INFO
			     "%s: dma at 0x%p (%d bytes), lp->scb at 0x%p\n",
			     dev->name, lp->dma, (int)sizeof(struct i596_dma),
			     &lp->dma->scb));

	return 0;
}

#ifdef CONFIG_NET_POLL_CONTROLLER
static void i596_poll_controller(struct net_device *dev)
{
	disable_irq(dev->irq);
	i596_interrupt(dev->irq, dev);
	enable_irq(dev->irq);
}
#endif

static irqreturn_t i596_interrupt(int irq, void *dev_id)
{
	struct net_device *dev = dev_id;
	struct i596_private *lp;
	struct i596_dma *dma;
	unsigned short status, ack_cmd = 0;

	lp = netdev_priv(dev);
	dma = lp->dma;

	spin_lock (&lp->lock);

	wait_cmd(dev, dma, 100, "i596 interrupt, timeout");
	status = SWAP16(dma->scb.status);

	DEB(DEB_INTS, printk(KERN_DEBUG
			     "%s: i596 interrupt, IRQ %d, status %4.4x.\n",
			dev->name, dev->irq, status));

	ack_cmd = status & 0xf000;

	if (!ack_cmd) {
		DEB(DEB_ERRORS, printk(KERN_DEBUG
				       "%s: interrupt with no events\n",
				       dev->name));

Annotation

Implementation Notes