drivers/net/ethernet/8390/ax88796.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/8390/ax88796.c
Extension
.c
Size
25198 bytes
Lines
1023
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 ax_netdev_ops = {
	.ndo_open		= ax_open,
	.ndo_stop		= ax_close,
	.ndo_eth_ioctl		= ax_ioctl,

	.ndo_start_xmit		= ax_ei_start_xmit,
	.ndo_tx_timeout		= ax_ei_tx_timeout,
	.ndo_get_stats		= ax_ei_get_stats,
	.ndo_set_rx_mode	= ax_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	= ax_ei_poll,
#endif
};

/* setup code */

static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
{
	void __iomem *ioaddr = ei_local->mem;
	struct ax_device *ax = to_ax_dev(dev);

	/* Select page 0 */
	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_STOP, ioaddr + E8390_CMD);

	/* set to byte access */
	ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
	ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
}

/*
 * ax_init_dev
 *
 * initialise the specified device, taking care to note the MAC
 * address it may already have (if configured), ensure
 * the device is ready to be used by lib8390.c and registerd with
 * the network layer.
 */
static int ax_init_dev(struct net_device *dev)
{
	struct ei_device *ei_local = netdev_priv(dev);
	struct ax_device *ax = to_ax_dev(dev);
	void __iomem *ioaddr = ei_local->mem;
	unsigned int start_page;
	unsigned int stop_page;
	int ret;
	int i;

	ret = ax_initial_check(dev);
	if (ret)
		goto err_out;

	/* setup goes here */

	ax_initial_setup(dev, ei_local);

	/* read the mac from the card prom if we need it */

	if (ax->plat->flags & AXFLG_HAS_EEPROM) {
		unsigned char SA_prom[32];

		ei_outb(6, ioaddr + EN0_RCNTLO);
		ei_outb(0, ioaddr + EN0_RCNTHI);
		ei_outb(0, ioaddr + EN0_RSARLO);
		ei_outb(0, ioaddr + EN0_RSARHI);
		ei_outb(E8390_RREAD + E8390_START, ioaddr + NE_CMD);
		for (i = 0; i < sizeof(SA_prom); i += 2) {
			SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
			SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
		}
		ei_outb(ENISR_RDC, ioaddr + EN0_ISR);	/* Ack intr. */

		if (ax->plat->wordlength == 2)
			for (i = 0; i < 16; i++)
				SA_prom[i] = SA_prom[i+i];

		eth_hw_addr_set(dev, SA_prom);
	}

#ifdef CONFIG_AX88796_93CX6
	if (ax->plat->flags & AXFLG_HAS_93CX6) {
		unsigned char mac_addr[ETH_ALEN];
		struct eeprom_93cx6 eeprom;

		eeprom.data = ei_local;
		eeprom.register_read = ax_eeprom_register_read;
		eeprom.register_write = ax_eeprom_register_write;
		eeprom.width = PCI_EEPROM_WIDTH_93C56;

Annotation

Implementation Notes