drivers/net/ethernet/silan/sc92031.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/silan/sc92031.c
Extension
.c
Size
39672 bytes
Lines
1577
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 sc92031_netdev_ops = {
	.ndo_get_stats		= sc92031_get_stats,
	.ndo_start_xmit		= sc92031_start_xmit,
	.ndo_open		= sc92031_open,
	.ndo_stop		= sc92031_stop,
	.ndo_set_rx_mode	= sc92031_set_multicast_list,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address 	= eth_mac_addr,
	.ndo_tx_timeout		= sc92031_tx_timeout,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= sc92031_poll_controller,
#endif
};

static int sc92031_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	int err;
	void __iomem* port_base;
	struct net_device *dev;
	struct sc92031_priv *priv;
	u8 addr[ETH_ALEN];
	u32 mac0, mac1;

	err = pci_enable_device(pdev);
	if (unlikely(err < 0))
		goto out_enable_device;

	pci_set_master(pdev);

	err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (unlikely(err < 0))
		goto out_set_dma_mask;

	err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (unlikely(err < 0))
		goto out_set_dma_mask;

	err = pci_request_regions(pdev, SC92031_NAME);
	if (unlikely(err < 0))
		goto out_request_regions;

	port_base = pci_iomap(pdev, SC92031_USE_PIO, 0);
	if (unlikely(!port_base)) {
		err = -EIO;
		goto out_iomap;
	}

	dev = alloc_etherdev(sizeof(struct sc92031_priv));
	if (unlikely(!dev)) {
		err = -ENOMEM;
		goto out_alloc_etherdev;
	}

	pci_set_drvdata(pdev, dev);
	SET_NETDEV_DEV(dev, &pdev->dev);

	/* faked with skb_copy_and_csum_dev */
	dev->features = NETIF_F_SG | NETIF_F_HIGHDMA |
		NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;

	dev->netdev_ops		= &sc92031_netdev_ops;
	dev->watchdog_timeo	= TX_TIMEOUT;
	dev->ethtool_ops	= &sc92031_ethtool_ops;

	priv = netdev_priv(dev);
	priv->ndev = dev;
	spin_lock_init(&priv->lock);
	priv->port_base = port_base;
	priv->pdev = pdev;
	tasklet_setup(&priv->tasklet, sc92031_tasklet);
	/* Fudge tasklet count so the call to sc92031_enable_interrupts at
	 * sc92031_open will work correctly */
	tasklet_disable_nosync(&priv->tasklet);

	/* PCI PM Wakeup */
	iowrite32((~PM_LongWF & ~PM_LWPTN) | PM_Enable, port_base + PMConfig);

	mac0 = ioread32(port_base + MAC0);
	mac1 = ioread32(port_base + MAC0 + 4);
	addr[0] = mac0 >> 24;
	addr[1] = mac0 >> 16;
	addr[2] = mac0 >> 8;
	addr[3] = mac0;
	addr[4] = mac1 >> 8;
	addr[5] = mac1;
	eth_hw_addr_set(dev, addr);

	err = register_netdev(dev);
	if (err < 0)
		goto out_register_netdev;

Annotation

Implementation Notes