drivers/net/ethernet/3com/typhoon.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/3com/typhoon.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/3com/typhoon.c
Extension
.c
Size
73445 bytes
Lines
2610
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 typhoon_netdev_ops = {
	.ndo_open		= typhoon_open,
	.ndo_stop		= typhoon_close,
#if MAX_SKB_FRAGS > 32
	.ndo_features_check	= typhoon_features_check,
#endif
	.ndo_start_xmit		= typhoon_start_tx,
	.ndo_set_rx_mode	= typhoon_set_rx_mode,
	.ndo_tx_timeout		= typhoon_tx_timeout,
	.ndo_get_stats		= typhoon_get_stats,
	.ndo_validate_addr	= eth_validate_addr,
	.ndo_set_mac_address	= eth_mac_addr,
};

static int
typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct net_device *dev;
	struct typhoon *tp;
	int card_id = (int) ent->driver_data;
	u8 addr[ETH_ALEN] __aligned(4);
	void __iomem *ioaddr;
	void *shared;
	dma_addr_t shared_dma;
	struct cmd_desc xp_cmd;
	struct resp_desc xp_resp[3];
	int err = 0;
	const char *err_msg;

	dev = alloc_etherdev(sizeof(*tp));
	if (dev == NULL) {
		err_msg = "unable to alloc new net device";
		err = -ENOMEM;
		goto error_out;
	}
	SET_NETDEV_DEV(dev, &pdev->dev);

	err = pci_enable_device(pdev);
	if (err < 0) {
		err_msg = "unable to enable device";
		goto error_out_dev;
	}

	err = pci_set_mwi(pdev);
	if (err < 0) {
		err_msg = "unable to set MWI";
		goto error_out_disable;
	}

	err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
	if (err < 0) {
		err_msg = "No usable DMA configuration";
		goto error_out_mwi;
	}

	/* sanity checks on IO and MMIO BARs
	 */
	if (!(pci_resource_flags(pdev, 0) & IORESOURCE_IO)) {
		err_msg = "region #1 not a PCI IO resource, aborting";
		err = -ENODEV;
		goto error_out_mwi;
	}
	if (pci_resource_len(pdev, 0) < 128) {
		err_msg = "Invalid PCI IO region size, aborting";
		err = -ENODEV;
		goto error_out_mwi;
	}
	if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
		err_msg = "region #1 not a PCI MMIO resource, aborting";
		err = -ENODEV;
		goto error_out_mwi;
	}
	if (pci_resource_len(pdev, 1) < 128) {
		err_msg = "Invalid PCI MMIO region size, aborting";
		err = -ENODEV;
		goto error_out_mwi;
	}

	err = pci_request_regions(pdev, KBUILD_MODNAME);
	if (err < 0) {
		err_msg = "could not request regions";
		goto error_out_mwi;
	}

	/* map our registers
	 */
	if (use_mmio != 0 && use_mmio != 1)
		use_mmio = typhoon_test_mmio(pdev);

	ioaddr = pci_iomap(pdev, use_mmio, 128);

Annotation

Implementation Notes