drivers/net/ethernet/fealnx.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/fealnx.c
Extension
.c
Size
54676 bytes
Lines
1954
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 netdev_ops = {
	.ndo_open		= netdev_open,
	.ndo_stop		= netdev_close,
	.ndo_start_xmit		= start_tx,
	.ndo_get_stats 		= get_stats,
	.ndo_set_rx_mode	= set_rx_mode,
	.ndo_eth_ioctl		= mii_ioctl,
	.ndo_tx_timeout		= fealnx_tx_timeout,
	.ndo_set_mac_address 	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
};

static int fealnx_init_one(struct pci_dev *pdev,
			   const struct pci_device_id *ent)
{
	struct netdev_private *np;
	int i, option, err, irq;
	static int card_idx = -1;
	char boardname[12];
	void __iomem *ioaddr;
	unsigned long len;
	unsigned int chip_id = ent->driver_data;
	struct net_device *dev;
	void *ring_space;
	dma_addr_t ring_dma;
	u8 addr[ETH_ALEN];
#ifdef USE_IO_OPS
	int bar = 0;
#else
	int bar = 1;
#endif

	card_idx++;
	sprintf(boardname, "fealnx%d", card_idx);

	option = card_idx < MAX_UNITS ? options[card_idx] : 0;

	i = pci_enable_device(pdev);
	if (i) return i;
	pci_set_master(pdev);

	len = pci_resource_len(pdev, bar);
	if (len < MIN_REGION_SIZE) {
		dev_err(&pdev->dev,
			   "region size %ld too small, aborting\n", len);
		return -ENODEV;
	}

	i = pci_request_regions(pdev, boardname);
	if (i)
		return i;

	irq = pdev->irq;

	ioaddr = pci_iomap(pdev, bar, len);
	if (!ioaddr) {
		err = -ENOMEM;
		goto err_out_res;
	}

	dev = alloc_etherdev(sizeof(struct netdev_private));
	if (!dev) {
		err = -ENOMEM;
		goto err_out_unmap;
	}
	SET_NETDEV_DEV(dev, &pdev->dev);

	/* read ethernet id */
	for (i = 0; i < 6; ++i)
		addr[i] = ioread8(ioaddr + PAR0 + i);
	eth_hw_addr_set(dev, addr);

	/* Reset the chip to erase previous misconfiguration. */
	iowrite32(0x00000001, ioaddr + BCR);

	/* Make certain the descriptor lists are aligned. */
	np = netdev_priv(dev);
	np->mem = ioaddr;
	spin_lock_init(&np->lock);
	np->pci_dev = pdev;
	np->flags = skel_netdrv_tbl[chip_id].flags;
	pci_set_drvdata(pdev, dev);
	np->mii.dev = dev;
	np->mii.mdio_read = mdio_read;
	np->mii.mdio_write = mdio_write;
	np->mii.phy_id_mask = 0x1f;
	np->mii.reg_num_mask = 0x1f;

	ring_space = dma_alloc_coherent(&pdev->dev, RX_TOTAL_SIZE, &ring_dma,
					GFP_KERNEL);

Annotation

Implementation Notes