drivers/net/ethernet/smsc/smsc911x.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/smsc/smsc911x.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/smsc/smsc911x.c
Extension
.c
Size
71206 bytes
Lines
2703
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 smsc911x_netdev_ops = {
	.ndo_open		= smsc911x_open,
	.ndo_stop		= smsc911x_stop,
	.ndo_start_xmit		= smsc911x_hard_start_xmit,
	.ndo_get_stats		= smsc911x_get_stats,
	.ndo_set_rx_mode	= smsc911x_set_multicast_list,
	.ndo_eth_ioctl		= phy_do_ioctl_running,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address 	= smsc911x_set_mac_address,
#ifdef CONFIG_NET_POLL_CONTROLLER
	.ndo_poll_controller	= smsc911x_poll_controller,
#endif
};

/* copies the current mac address from hardware to dev->dev_addr */
static void smsc911x_read_mac_address(struct net_device *dev)
{
	struct smsc911x_data *pdata = netdev_priv(dev);
	u32 mac_high16, mac_low32;
	u8 addr[ETH_ALEN];

	mac_high16 = smsc911x_mac_read(pdata, ADDRH);
	mac_low32 = smsc911x_mac_read(pdata, ADDRL);

	/* The first mac_read in some setups can incorrectly read 0. Re-read it
	 * to get the full MAC if this is observed.
	 */
	if (mac_high16 == 0) {
		SMSC_TRACE(pdata, probe, "Re-read MAC ADDRH\n");
		mac_high16 = smsc911x_mac_read(pdata, ADDRH);
	}

	addr[0] = (u8)(mac_low32);
	addr[1] = (u8)(mac_low32 >> 8);
	addr[2] = (u8)(mac_low32 >> 16);
	addr[3] = (u8)(mac_low32 >> 24);
	addr[4] = (u8)(mac_high16);
	addr[5] = (u8)(mac_high16 >> 8);
	eth_hw_addr_set(dev, addr);
}

/* Initializing private device structures, only called from probe */
static int smsc911x_init(struct net_device *dev)
{
	struct smsc911x_data *pdata = netdev_priv(dev);
	unsigned int byte_test, mask;
	unsigned int to = 100;

	SMSC_TRACE(pdata, probe, "Driver Parameters:");
	SMSC_TRACE(pdata, probe, "LAN base: 0x%08lX",
		   (unsigned long)pdata->ioaddr);
	SMSC_TRACE(pdata, probe, "IRQ: %d", dev->irq);
	SMSC_TRACE(pdata, probe, "PHY will be autodetected.");

	spin_lock_init(&pdata->dev_lock);
	spin_lock_init(&pdata->mac_lock);

	if (pdata->ioaddr == NULL) {
		SMSC_WARN(pdata, probe, "pdata->ioaddr: 0x00000000");
		return -ENODEV;
	}

	/*
	 * poll the READY bit in PMT_CTRL. Any other access to the device is
	 * forbidden while this bit isn't set. Try for 100ms
	 *
	 * Note that this test is done before the WORD_SWAP register is
	 * programmed. So in some configurations the READY bit is at 16 before
	 * WORD_SWAP is written to. This issue is worked around by waiting
	 * until either bit 0 or bit 16 gets set in PMT_CTRL.
	 *
	 * SMSC has confirmed that checking bit 16 (marked as reserved in
	 * the datasheet) is fine since these bits "will either never be set
	 * or can only go high after READY does (so also indicate the device
	 * is ready)".
	 */

	mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_);
	while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to)
		udelay(1000);

	if (to == 0) {
		netdev_err(dev, "Device not READY in 100ms aborting\n");
		return -ENODEV;
	}

	/* Check byte ordering */
	byte_test = smsc911x_reg_read(pdata, BYTE_TEST);
	SMSC_TRACE(pdata, probe, "BYTE_TEST: 0x%08X", byte_test);
	if (byte_test == 0x43218765) {

Annotation

Implementation Notes