drivers/net/ethernet/natsemi/natsemi.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/natsemi/natsemi.c
Extension
.c
Size
95526 bytes
Lines
3384
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 natsemi_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_change_mtu		= natsemi_change_mtu,
	.ndo_eth_ioctl		= netdev_ioctl,
	.ndo_tx_timeout 	= ns_tx_timeout,
	.ndo_set_mac_address 	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= natsemi_poll_controller,
#endif
};

static int natsemi_probe1(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct net_device *dev;
	struct netdev_private *np;
	int i, option, irq, chip_idx = ent->driver_data;
	static int find_cnt = -1;
	resource_size_t iostart;
	unsigned long iosize;
	void __iomem *ioaddr;
	const int pcibar = 1; /* PCI base address register */
	u8 addr[ETH_ALEN];
	int prev_eedata;
	u32 tmp;

/* when built into the kernel, we only print version if device is found */
#ifndef MODULE
	static int printed_version;
	if (!printed_version++)
		printk(version);
#endif

	i = pcim_enable_device(pdev);
	if (i) return i;

	/* natsemi has a non-standard PM control register
	 * in PCI config space.  Some boards apparently need
	 * to be brought to D0 in this manner.
	 */
	pci_read_config_dword(pdev, PCIPM, &tmp);
	if (tmp & PCI_PM_CTRL_STATE_MASK) {
		/* D0 state, disable PME assertion */
		u32 newtmp = tmp & ~PCI_PM_CTRL_STATE_MASK;
		pci_write_config_dword(pdev, PCIPM, newtmp);
	}

	find_cnt++;
	iostart = pci_resource_start(pdev, pcibar);
	iosize = pci_resource_len(pdev, pcibar);
	irq = pdev->irq;

	pci_set_master(pdev);

	dev = alloc_etherdev(sizeof (struct netdev_private));
	if (!dev)
		return -ENOMEM;
	SET_NETDEV_DEV(dev, &pdev->dev);

	i = pcim_request_all_regions(pdev, DRV_NAME);
	if (i)
		goto err_pci_request_regions;

	ioaddr = ioremap(iostart, iosize);
	if (!ioaddr) {
		i = -ENOMEM;
		goto err_pci_request_regions;
	}

	/* Work around the dropped serial bit. */
	prev_eedata = eeprom_read(ioaddr, 6);
	for (i = 0; i < 3; i++) {
		int eedata = eeprom_read(ioaddr, i + 7);
		addr[i*2] = (eedata << 1) + (prev_eedata >> 15);
		addr[i*2+1] = eedata >> 7;
		prev_eedata = eedata;
	}
	eth_hw_addr_set(dev, addr);

	np = netdev_priv(dev);
	np->ioaddr = ioaddr;

	netif_napi_add(dev, &np->napi, natsemi_poll);
	np->dev = dev;

	np->pci_dev = pdev;

Annotation

Implementation Notes