drivers/net/can/mscan/mscan.c

Source file repositories/reference/linux-study-clean/drivers/net/can/mscan/mscan.c

File Facts

System
Linux kernel
Corpus path
drivers/net/can/mscan/mscan.c
Extension
.c
Size
17503 bytes
Lines
699
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 mscan_netdev_ops = {
	.ndo_open	= mscan_open,
	.ndo_stop	= mscan_close,
	.ndo_start_xmit	= mscan_start_xmit,
};

static const struct ethtool_ops mscan_ethtool_ops = {
	.get_ts_info = ethtool_op_get_ts_info,
};

int register_mscandev(struct net_device *dev, int mscan_clksrc)
{
	struct mscan_priv *priv = netdev_priv(dev);
	struct mscan_regs __iomem *regs = priv->reg_base;
	u8 ctl1;

	ctl1 = in_8(&regs->canctl1);
	if (mscan_clksrc)
		ctl1 |= MSCAN_CLKSRC;
	else
		ctl1 &= ~MSCAN_CLKSRC;

	if (priv->type == MSCAN_TYPE_MPC5121) {
		priv->can.do_get_berr_counter = mscan_get_berr_counter;
		ctl1 |= MSCAN_BORM; /* bus-off recovery upon request */
	}

	ctl1 |= MSCAN_CANE;
	out_8(&regs->canctl1, ctl1);
	udelay(100);

	/* acceptance mask/acceptance code (accept everything) */
	out_be16(&regs->canidar1_0, 0);
	out_be16(&regs->canidar3_2, 0);
	out_be16(&regs->canidar5_4, 0);
	out_be16(&regs->canidar7_6, 0);

	out_be16(&regs->canidmr1_0, 0xffff);
	out_be16(&regs->canidmr3_2, 0xffff);
	out_be16(&regs->canidmr5_4, 0xffff);
	out_be16(&regs->canidmr7_6, 0xffff);
	/* Two 32 bit Acceptance Filters */
	out_8(&regs->canidac, MSCAN_AF_32BIT);

	mscan_set_mode(dev, MSCAN_INIT_MODE);

	return register_candev(dev);
}

void unregister_mscandev(struct net_device *dev)
{
	struct mscan_priv *priv = netdev_priv(dev);
	struct mscan_regs __iomem *regs = priv->reg_base;
	mscan_set_mode(dev, MSCAN_INIT_MODE);
	clrbits8(&regs->canctl1, MSCAN_CANE);
	unregister_candev(dev);
}

struct net_device *alloc_mscandev(void)
{
	struct net_device *dev;
	struct mscan_priv *priv;
	int i;

	dev = alloc_candev(sizeof(struct mscan_priv), MSCAN_ECHO_SKB_MAX);
	if (!dev)
		return NULL;
	priv = netdev_priv(dev);

	dev->netdev_ops = &mscan_netdev_ops;
	dev->ethtool_ops = &mscan_ethtool_ops;

	dev->flags |= IFF_ECHO;	/* we support local echo */

	netif_napi_add_weight(dev, &priv->napi, mscan_rx_poll, 8);

	priv->can.bittiming_const = &mscan_bittiming_const;
	priv->can.do_set_bittiming = mscan_do_set_bittiming;
	priv->can.do_set_mode = mscan_do_set_mode;
	priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
		CAN_CTRLMODE_LISTENONLY;

	for (i = 0; i < TX_QUEUE_SIZE; i++) {
		priv->tx_queue[i].id = i;
		priv->tx_queue[i].mask = 1 << i;
	}

	return dev;
}

Annotation

Implementation Notes