drivers/net/ethernet/tundra/tsi108_eth.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/tundra/tsi108_eth.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/tundra/tsi108_eth.c
Extension
.c
Size
46610 bytes
Lines
1690
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 tsi108_netdev_ops = {
	.ndo_open		= tsi108_open,
	.ndo_stop		= tsi108_close,
	.ndo_start_xmit		= tsi108_send_packet,
	.ndo_set_rx_mode	= tsi108_set_rx_mode,
	.ndo_get_stats		= tsi108_get_stats,
	.ndo_eth_ioctl		= tsi108_do_ioctl,
	.ndo_set_mac_address	= tsi108_set_mac,
	.ndo_validate_addr	= eth_validate_addr,
};

static int
tsi108_init_one(struct platform_device *pdev)
{
	struct net_device *dev = NULL;
	struct tsi108_prv_data *data = NULL;
	hw_info *einfo;
	int err = 0;

	einfo = dev_get_platdata(&pdev->dev);

	if (NULL == einfo) {
		printk(KERN_ERR "tsi-eth %d: Missing additional data!\n",
		       pdev->id);
		return -ENODEV;
	}

	/* Create an ethernet device instance */

	dev = alloc_etherdev(sizeof(struct tsi108_prv_data));
	if (!dev)
		return -ENOMEM;

	printk("tsi108_eth%d: probe...\n", pdev->id);
	data = netdev_priv(dev);
	data->dev = dev;
	data->pdev = pdev;

	pr_debug("tsi108_eth%d:regs:phyresgs:phy:irq_num=0x%x:0x%x:0x%x:0x%x\n",
			pdev->id, einfo->regs, einfo->phyregs,
			einfo->phy, einfo->irq_num);

	data->regs = ioremap(einfo->regs, 0x400);
	if (NULL == data->regs) {
		err = -ENOMEM;
		goto regs_fail;
	}

	data->phyregs = ioremap(einfo->phyregs, 0x400);
	if (NULL == data->phyregs) {
		err = -ENOMEM;
		goto phyregs_fail;
	}
/* MII setup */
	data->mii_if.dev = dev;
	data->mii_if.mdio_read = tsi108_mdio_read;
	data->mii_if.mdio_write = tsi108_mdio_write;
	data->mii_if.phy_id = einfo->phy;
	data->mii_if.phy_id_mask = 0x1f;
	data->mii_if.reg_num_mask = 0x1f;

	data->phy = einfo->phy;
	data->phy_type = einfo->phy_type;
	data->irq_num = einfo->irq_num;
	data->id = pdev->id;
	netif_napi_add(dev, &data->napi, tsi108_poll);
	dev->netdev_ops = &tsi108_netdev_ops;
	dev->ethtool_ops = &tsi108_ethtool_ops;

	/* Apparently, the Linux networking code won't use scatter-gather
	 * if the hardware doesn't do checksums.  However, it's faster
	 * to checksum in place and use SG, as (among other reasons)
	 * the cache won't be dirtied (which then has to be flushed
	 * before DMA).  The checksumming is done by the driver (via
	 * a new function skb_csum_dev() in net/core/skbuff.c).
	 */

	dev->features = NETIF_F_HIGHDMA;

	spin_lock_init(&data->txlock);
	spin_lock_init(&data->misclock);

	tsi108_reset_ether(data);
	tsi108_kill_phy(dev);

	if ((err = tsi108_get_mac(dev)) != 0) {
		printk(KERN_ERR "%s: Invalid MAC address.  Please correct.\n",
		       dev->name);
		goto register_fail;
	}

Annotation

Implementation Notes