drivers/net/ethernet/apple/bmac.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/apple/bmac.c
Extension
.c
Size
40343 bytes
Lines
1613
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 bmac_netdev_ops = {
	.ndo_open		= bmac_open,
	.ndo_stop		= bmac_close,
	.ndo_start_xmit		= bmac_output,
	.ndo_set_rx_mode	= bmac_set_multicast,
	.ndo_set_mac_address	= bmac_set_address,
	.ndo_validate_addr	= eth_validate_addr,
};

static int bmac_probe(struct macio_dev *mdev, const struct of_device_id *match)
{
	int j, rev, ret;
	struct bmac_data *bp;
	const unsigned char *prop_addr;
	unsigned char addr[6];
	u8 macaddr[6];
	struct net_device *dev;
	int is_bmac_plus = ((int)match->data) != 0;

	if (macio_resource_count(mdev) != 3 || macio_irq_count(mdev) != 3) {
		printk(KERN_ERR "BMAC: can't use, need 3 addrs and 3 intrs\n");
		return -ENODEV;
	}
	prop_addr = of_get_property(macio_get_of_node(mdev),
			"mac-address", NULL);
	if (prop_addr == NULL) {
		prop_addr = of_get_property(macio_get_of_node(mdev),
				"local-mac-address", NULL);
		if (prop_addr == NULL) {
			printk(KERN_ERR "BMAC: Can't get mac-address\n");
			return -ENODEV;
		}
	}
	memcpy(addr, prop_addr, sizeof(addr));

	dev = alloc_etherdev(PRIV_BYTES);
	if (!dev)
		return -ENOMEM;

	bp = netdev_priv(dev);
	SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
	macio_set_drvdata(mdev, dev);

	bp->mdev = mdev;
	spin_lock_init(&bp->lock);

	if (macio_request_resources(mdev, "bmac")) {
		printk(KERN_ERR "BMAC: can't request IO resource !\n");
		goto out_free;
	}

	dev->base_addr = (unsigned long)
		ioremap(macio_resource_start(mdev, 0), macio_resource_len(mdev, 0));
	if (dev->base_addr == 0)
		goto out_release;

	dev->irq = macio_irq(mdev, 0);

	bmac_enable_and_reset_chip(dev);
	bmwrite(dev, INTDISABLE, DisableAll);

	rev = addr[0] == 0 && addr[1] == 0xA0;
	for (j = 0; j < 6; ++j)
		macaddr[j] = rev ? bitrev8(addr[j]): addr[j];

	eth_hw_addr_set(dev, macaddr);

	/* Enable chip without interrupts for now */
	bmac_enable_and_reset_chip(dev);
	bmwrite(dev, INTDISABLE, DisableAll);

	dev->netdev_ops = &bmac_netdev_ops;
	dev->ethtool_ops = &bmac_ethtool_ops;

	bmac_get_station_address(dev, addr);
	if (bmac_verify_checksum(dev) != 0)
		goto err_out_iounmap;

	bp->is_bmac_plus = is_bmac_plus;
	bp->tx_dma = ioremap(macio_resource_start(mdev, 1), macio_resource_len(mdev, 1));
	if (!bp->tx_dma)
		goto err_out_iounmap;
	bp->tx_dma_intr = macio_irq(mdev, 1);
	bp->rx_dma = ioremap(macio_resource_start(mdev, 2), macio_resource_len(mdev, 2));
	if (!bp->rx_dma)
		goto err_out_iounmap_tx;
	bp->rx_dma_intr = macio_irq(mdev, 2);

	bp->tx_cmds = (volatile struct dbdma_cmd *) DBDMA_ALIGN(bp + 1);
	bp->rx_cmds = bp->tx_cmds + N_TX_RING + 1;

Annotation

Implementation Notes