drivers/net/ethernet/wiznet/w5100.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/wiznet/w5100.c
Extension
.c
Size
21046 bytes
Lines
867
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 w5100_netdev_ops = {
	.ndo_open		= w5100_open,
	.ndo_stop		= w5100_stop,
	.ndo_start_xmit		= w5100_start_tx,
	.ndo_tx_timeout		= w5100_tx_timeout,
	.ndo_set_rx_mode	= w5100_set_rx_mode,
	.ndo_set_mac_address	= w5100_set_macaddr,
	.ndo_validate_addr	= eth_validate_addr,
};

void *w5100_ops_priv(const struct net_device *ndev)
{
	return netdev_priv(ndev) +
	       ALIGN(sizeof(struct w5100_priv), NETDEV_ALIGN);
}
EXPORT_SYMBOL_GPL(w5100_ops_priv);

int w5100_probe(struct device *dev, const struct w5100_ops *ops,
		int sizeof_ops_priv, const void *mac_addr, int irq)
{
	struct w5100_priv *priv;
	struct net_device *ndev;
	int err;
	size_t alloc_size;

	alloc_size = sizeof(*priv);
	if (sizeof_ops_priv) {
		alloc_size = ALIGN(alloc_size, NETDEV_ALIGN);
		alloc_size += sizeof_ops_priv;
	}
	alloc_size += NETDEV_ALIGN - 1;

	ndev = alloc_etherdev(alloc_size);
	if (!ndev)
		return -ENOMEM;
	SET_NETDEV_DEV(ndev, dev);
	dev_set_drvdata(dev, ndev);
	priv = netdev_priv(ndev);

	switch (ops->chip_id) {
	case W5100:
		priv->s0_regs = W5100_S0_REGS;
		priv->s0_tx_buf = W5100_TX_MEM_START;
		priv->s0_tx_buf_size = W5100_TX_MEM_SIZE;
		priv->s0_rx_buf = W5100_RX_MEM_START;
		priv->s0_rx_buf_size = W5100_RX_MEM_SIZE;
		break;
	case W5200:
		priv->s0_regs = W5200_S0_REGS;
		priv->s0_tx_buf = W5200_TX_MEM_START;
		priv->s0_tx_buf_size = W5200_TX_MEM_SIZE;
		priv->s0_rx_buf = W5200_RX_MEM_START;
		priv->s0_rx_buf_size = W5200_RX_MEM_SIZE;
		break;
	case W5500:
		priv->s0_regs = W5500_S0_REGS;
		priv->s0_tx_buf = W5500_TX_MEM_START;
		priv->s0_tx_buf_size = W5500_TX_MEM_SIZE;
		priv->s0_rx_buf = W5500_RX_MEM_START;
		priv->s0_rx_buf_size = W5500_RX_MEM_SIZE;
		break;
	default:
		err = -EINVAL;
		goto err_register;
	}

	priv->ndev = ndev;
	priv->ops = ops;
	priv->irq = irq;

	ndev->netdev_ops = &w5100_netdev_ops;
	ndev->ethtool_ops = &w5100_ethtool_ops;
	netif_napi_add_weight(ndev, &priv->napi, w5100_napi_poll, 16);

	/* This chip doesn't support VLAN packets with normal MTU,
	 * so disable VLAN for this device.
	 */
	ndev->features |= NETIF_F_VLAN_CHALLENGED;

	err = register_netdev(ndev);
	if (err < 0)
		goto err_register;

	priv->xfer_wq = alloc_workqueue("%s", WQ_MEM_RECLAIM | WQ_PERCPU, 0,
					netdev_name(ndev));
	if (!priv->xfer_wq) {
		err = -ENOMEM;
		goto err_wq;
	}

Annotation

Implementation Notes