drivers/net/ethernet/8390/mcf8390.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/8390/mcf8390.c
Extension
.c
Size
11896 bytes
Lines
469
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 mcf8390_netdev_ops = {
	.ndo_open		= __ei_open,
	.ndo_stop		= __ei_close,
	.ndo_start_xmit		= __ei_start_xmit,
	.ndo_tx_timeout		= __ei_tx_timeout,
	.ndo_get_stats		= __ei_get_stats,
	.ndo_set_rx_mode	= __ei_set_multicast_list,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= __ei_poll,
#endif
};

static int mcf8390_init(struct net_device *dev)
{
	static u32 offsets[] = {
		0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
		0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
	};
	struct ei_device *ei_local = netdev_priv(dev);
	unsigned char SA_prom[32];
	u32 addr = dev->base_addr;
	int start_page, stop_page;
	int i, ret;

	mcf8390_reset_8390(dev);

	/*
	 * Read the 16 bytes of station address PROM.
	 * We must first initialize registers,
	 * similar to NS8390_init(eifdev, 0).
	 * We can't reliably read the SAPROM address without this.
	 * (I learned the hard way!).
	 */
	{
		static const struct {
			u32 value;
			u32 offset;
		} program_seq[] = {
			{E8390_NODMA + E8390_PAGE0 + E8390_STOP, NE_CMD},
						/* Select page 0 */
			{0x48,	NE_EN0_DCFG},	/* 0x48: Set byte-wide access */
			{0x00,	NE_EN0_RCNTLO},	/* Clear the count regs */
			{0x00,	NE_EN0_RCNTHI},
			{0x00,	NE_EN0_IMR},	/* Mask completion irq */
			{0xFF,	NE_EN0_ISR},
			{E8390_RXOFF, NE_EN0_RXCR}, /* 0x20 Set to monitor */
			{E8390_TXOFF, NE_EN0_TXCR}, /* 0x02 and loopback mode */
			{32,	NE_EN0_RCNTLO},
			{0x00,	NE_EN0_RCNTHI},
			{0x00,	NE_EN0_RSARLO},	/* DMA starting at 0x0000 */
			{0x00,	NE_EN0_RSARHI},
			{E8390_RREAD + E8390_START, NE_CMD},
		};
		for (i = 0; i < ARRAY_SIZE(program_seq); i++) {
			ei_outb(program_seq[i].value,
				 addr + program_seq[i].offset);
		}
	}

	for (i = 0; i < 16; i++) {
		SA_prom[i] = ei_inb(addr + NE_DATAPORT);
		ei_inb(addr + NE_DATAPORT);
	}

	/* We must set the 8390 for word mode. */
	ei_outb(0x49, addr + NE_EN0_DCFG);
	start_page = NESM_START_PG;
	stop_page = NESM_STOP_PG;

	/* Install the Interrupt handler */
	ret = request_irq(dev->irq, __ei_interrupt, 0, dev->name, dev);
	if (ret)
		return ret;

	eth_hw_addr_set(dev, SA_prom);

	netdev_dbg(dev, "Found ethernet address: %pM\n", dev->dev_addr);

	ei_local->name = "mcf8390";
	ei_local->tx_start_page = start_page;
	ei_local->stop_page = stop_page;
	ei_local->word16 = 1;
	ei_local->rx_start_page = start_page + TX_PAGES;
	ei_local->reset_8390 = mcf8390_reset_8390;
	ei_local->block_input = mcf8390_block_input;
	ei_local->block_output = mcf8390_block_output;
	ei_local->get_8390_hdr = mcf8390_get_8390_hdr;
	ei_local->reg_offset = offsets;

Annotation

Implementation Notes