drivers/net/ethernet/aeroflex/greth.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/aeroflex/greth.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/aeroflex/greth.c
Extension
.c
Size
39427 bytes
Lines
1576
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 struct net_device_ops greth_netdev_ops = {
	.ndo_open		= greth_open,
	.ndo_stop		= greth_close,
	.ndo_start_xmit		= greth_start_xmit,
	.ndo_set_mac_address	= greth_set_mac_add,
	.ndo_validate_addr	= eth_validate_addr,
};

static inline int wait_for_mdio(struct greth_private *greth)
{
	unsigned long timeout = jiffies + 4*HZ/100;
	while (GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_BUSY) {
		if (time_after(jiffies, timeout))
			return 0;
	}
	return 1;
}

static int greth_mdio_read(struct mii_bus *bus, int phy, int reg)
{
	struct greth_private *greth = bus->priv;
	int data;

	if (!wait_for_mdio(greth))
		return -EBUSY;

	GRETH_REGSAVE(greth->regs->mdio, ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 2);

	if (!wait_for_mdio(greth))
		return -EBUSY;

	if (!(GRETH_REGLOAD(greth->regs->mdio) & GRETH_MII_NVALID)) {
		data = (GRETH_REGLOAD(greth->regs->mdio) >> 16) & 0xFFFF;
		return data;

	} else {
		return -1;
	}
}

static int greth_mdio_write(struct mii_bus *bus, int phy, int reg, u16 val)
{
	struct greth_private *greth = bus->priv;

	if (!wait_for_mdio(greth))
		return -EBUSY;

	GRETH_REGSAVE(greth->regs->mdio,
		      ((val & 0xFFFF) << 16) | ((phy & 0x1F) << 11) | ((reg & 0x1F) << 6) | 1);

	if (!wait_for_mdio(greth))
		return -EBUSY;

	return 0;
}

static void greth_link_change(struct net_device *dev)
{
	struct greth_private *greth = netdev_priv(dev);
	struct phy_device *phydev = dev->phydev;
	unsigned long flags;
	int status_change = 0;
	u32 ctrl;

	spin_lock_irqsave(&greth->devlock, flags);

	if (phydev->link) {

		if ((greth->speed != phydev->speed) || (greth->duplex != phydev->duplex)) {
			ctrl = GRETH_REGLOAD(greth->regs->control) &
			       ~(GRETH_CTRL_FD | GRETH_CTRL_SP | GRETH_CTRL_GB);

			if (phydev->duplex)
				ctrl |= GRETH_CTRL_FD;

			if (phydev->speed == SPEED_100)
				ctrl |= GRETH_CTRL_SP;
			else if (phydev->speed == SPEED_1000)
				ctrl |= GRETH_CTRL_GB;

			GRETH_REGSAVE(greth->regs->control, ctrl);
			greth->speed = phydev->speed;
			greth->duplex = phydev->duplex;
			status_change = 1;
		}
	}

	if (phydev->link != greth->link) {
		if (!phydev->link) {
			greth->speed = 0;

Annotation

Implementation Notes