arch/m68k/emu/nfeth.c

Source file repositories/reference/linux-study-clean/arch/m68k/emu/nfeth.c

File Facts

System
Linux kernel
Corpus path
arch/m68k/emu/nfeth.c
Extension
.c
Size
6309 bytes
Lines
266
Domain
Architecture Layer
Bucket
arch/m68k
Inferred role
Architecture Layer: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct net_device_ops nfeth_netdev_ops = {
	.ndo_open		= nfeth_open,
	.ndo_stop		= nfeth_stop,
	.ndo_start_xmit		= nfeth_xmit,
	.ndo_tx_timeout		= nfeth_tx_timeout,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
};

static struct net_device * __init nfeth_probe(int unit)
{
	struct net_device *dev;
	struct nfeth_private *priv;
	char mac[ETH_ALEN], host_ip[32], local_ip[32];
	int err;

	if (!nf_call(nfEtherID + XIF_GET_MAC, unit, virt_to_phys(mac),
		     ETH_ALEN))
		return NULL;

	dev = alloc_etherdev(sizeof(struct nfeth_private));
	if (!dev)
		return NULL;

	dev->irq = nfEtherIRQ;
	dev->netdev_ops = &nfeth_netdev_ops;

	eth_hw_addr_set(dev, mac);

	priv = netdev_priv(dev);
	priv->ethX = unit;

	err = register_netdev(dev);
	if (err) {
		free_netdev(dev);
		return NULL;
	}

	nf_call(nfEtherID + XIF_GET_IPHOST, unit,
		virt_to_phys(host_ip), sizeof(host_ip));
	nf_call(nfEtherID + XIF_GET_IPATARI, unit,
		virt_to_phys(local_ip), sizeof(local_ip));

	netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip,
		    local_ip, mac);

	return dev;
}

static int __init nfeth_init(void)
{
	long ver;
	int error, i;

	nfEtherID = nf_get_id("ETHERNET");
	if (!nfEtherID)
		return -ENODEV;

	ver = nf_call(nfEtherID + GET_VERSION);
	pr_info("API %lu\n", ver);

	nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
	error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
			    "eth emu", nfeth_interrupt);
	if (error) {
		pr_err("request for irq %d failed %d", nfEtherIRQ, error);
		return error;
	}

	for (i = 0; i < MAX_UNIT; i++)
		nfeth_dev[i] = nfeth_probe(i);

	return 0;
}

static void __exit nfeth_cleanup(void)
{
	int i;

	for (i = 0; i < MAX_UNIT; i++) {
		if (nfeth_dev[i]) {
			unregister_netdev(nfeth_dev[i]);
			free_netdev(nfeth_dev[i]);
		}
	}
	free_irq(nfEtherIRQ, nfeth_interrupt);
}

module_init(nfeth_init);
module_exit(nfeth_cleanup);

Annotation

Implementation Notes