drivers/net/ethernet/sun/sunhme.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/sun/sunhme.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/sun/sunhme.c
Extension
.c
Size
80878 bytes
Lines
2902
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 hme_netdev_ops = {
	.ndo_open		= happy_meal_open,
	.ndo_stop		= happy_meal_close,
	.ndo_start_xmit		= happy_meal_start_xmit,
	.ndo_tx_timeout		= happy_meal_tx_timeout,
	.ndo_get_stats		= happy_meal_get_stats,
	.ndo_set_rx_mode	= happy_meal_set_multicast,
	.ndo_set_mac_address 	= eth_mac_addr,
	.ndo_validate_addr	= eth_validate_addr,
};

#ifdef CONFIG_PCI
static int is_quattro_p(struct pci_dev *pdev)
{
	struct pci_dev *busdev = pdev->bus->self;
	struct pci_dev *this_pdev;
	int n_hmes;

	if (!busdev || busdev->vendor != PCI_VENDOR_ID_DEC ||
	    busdev->device != PCI_DEVICE_ID_DEC_21153)
		return 0;

	n_hmes = 0;
	list_for_each_entry(this_pdev, &pdev->bus->devices, bus_list) {
		if (this_pdev->vendor == PCI_VENDOR_ID_SUN &&
		    this_pdev->device == PCI_DEVICE_ID_SUN_HAPPYMEAL)
			n_hmes++;
	}

	if (n_hmes != 4)
		return 0;

	return 1;
}

/* Fetch MAC address from vital product data of PCI ROM. */
static int find_eth_addr_in_vpd(void __iomem *rom_base, int len, int index, unsigned char *dev_addr)
{
	int this_offset;

	for (this_offset = 0x20; this_offset < len; this_offset++) {
		void __iomem *p = rom_base + this_offset;

		if (readb(p + 0) != 0x90 ||
		    readb(p + 1) != 0x00 ||
		    readb(p + 2) != 0x09 ||
		    readb(p + 3) != 0x4e ||
		    readb(p + 4) != 0x41 ||
		    readb(p + 5) != 0x06)
			continue;

		this_offset += 6;
		p += 6;

		if (index == 0) {
			for (int i = 0; i < 6; i++)
				dev_addr[i] = readb(p + i);
			return 1;
		}
		index--;
	}
	return 0;
}

static void __maybe_unused get_hme_mac_nonsparc(struct pci_dev *pdev,
						unsigned char *dev_addr)
{
	void __iomem *p;
	size_t size;

	p = pci_map_rom(pdev, &size);
	if (p) {
		int index = 0;
		int found;

		if (is_quattro_p(pdev))
			index = PCI_SLOT(pdev->devfn);

		found = readb(p) == 0x55 &&
			readb(p + 1) == 0xaa &&
			find_eth_addr_in_vpd(p, (64 * 1024), index, dev_addr);
		pci_unmap_rom(pdev, p);
		if (found)
			return;
	}

	/* Sun MAC prefix then 3 random bytes. */
	dev_addr[0] = 0x08;
	dev_addr[1] = 0x00;
	dev_addr[2] = 0x20;

Annotation

Implementation Notes