drivers/net/usb/mcs7830.c

Source file repositories/reference/linux-study-clean/drivers/net/usb/mcs7830.c

File Facts

System
Linux kernel
Corpus path
drivers/net/usb/mcs7830.c
Extension
.c
Size
16442 bytes
Lines
631
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 mcs7830_netdev_ops = {
	.ndo_open		= usbnet_open,
	.ndo_stop		= usbnet_stop,
	.ndo_start_xmit		= usbnet_start_xmit,
	.ndo_tx_timeout		= usbnet_tx_timeout,
	.ndo_change_mtu		= usbnet_change_mtu,
	.ndo_get_stats64	= dev_get_tstats64,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_eth_ioctl		= usbnet_mii_ioctl,
	.ndo_set_rx_mode	= mcs7830_set_multicast,
	.ndo_set_mac_address	= mcs7830_set_mac_address,
};

static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev)
{
	struct net_device *net = dev->net;
	u8 addr[ETH_ALEN];
	int ret;
	int retry;

	/* Initial startup: Gather MAC address setting from EEPROM */
	ret = -EINVAL;
	for (retry = 0; retry < 5 && ret; retry++)
		ret = mcs7830_hif_get_mac_address(dev, addr);
	if (ret) {
		dev_warn(&dev->udev->dev, "Cannot read MAC address\n");
		goto out;
	}
	eth_hw_addr_set(net, addr);

	mcs7830_data_set_multicast(net);

	ret = mcs7830_apply_base_config(dev);
	if (ret)
		goto out;

	net->ethtool_ops = &mcs7830_ethtool_ops;
	net->netdev_ops = &mcs7830_netdev_ops;

	/* reserve space for the status byte on rx */
	dev->rx_urb_size = ETH_FRAME_LEN + 1;

	dev->mii.mdio_read = mcs7830_mdio_read;
	dev->mii.mdio_write = mcs7830_mdio_write;
	dev->mii.dev = net;
	dev->mii.phy_id_mask = 0x3f;
	dev->mii.reg_num_mask = 0x1f;
	dev->mii.phy_id = *((u8 *) net->dev_addr + 1);

	ret = usbnet_get_endpoints(dev, udev);
out:
	return ret;
}

/* The chip always appends a status byte that we need to strip */
static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
{
	u8 status;

	/* This check is no longer done by usbnet */
	if (skb->len < dev->net->hard_header_len) {
		dev_err(&dev->udev->dev, "unexpected tiny rx frame\n");
		return 0;
	}

	skb_trim(skb, skb->len - 1);
	status = skb->data[skb->len];

	if (status != MCS7830_RX_FRAME_CORRECT) {
		dev_dbg(&dev->udev->dev, "rx fixup status %x\n", status);

		/* hmm, perhaps usbnet.c already sees a globally visible
		   frame error and increments rx_errors on its own already? */
		dev->net->stats.rx_errors++;

		if (status &	(MCS7830_RX_SHORT_FRAME
				|MCS7830_RX_LENGTH_ERROR
				|MCS7830_RX_LARGE_FRAME))
			dev->net->stats.rx_length_errors++;
		if (status & MCS7830_RX_ALIGNMENT_ERROR)
			dev->net->stats.rx_frame_errors++;
		if (status & MCS7830_RX_CRC_ERROR)
			dev->net->stats.rx_crc_errors++;
	}

	return skb->len > 0;
}

static void mcs7830_status(struct usbnet *dev, struct urb *urb)
{

Annotation

Implementation Notes