drivers/net/wan/c101.c

Source file repositories/reference/linux-study-clean/drivers/net/wan/c101.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wan/c101.c
Extension
.c
Size
10876 bytes
Lines
441
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 c101_ops = {
	.ndo_open       = c101_open,
	.ndo_stop       = c101_close,
	.ndo_start_xmit = hdlc_start_xmit,
	.ndo_siocwandev = c101_ioctl,
	.ndo_siocdevprivate = c101_siocdevprivate,
};

static int __init c101_run(unsigned long irq, unsigned long winbase)
{
	struct net_device *dev;
	hdlc_device *hdlc;
	card_t *card;
	int result;

	if (irq < 3 || irq > 15 || irq == 6) /* FIXME */ {
		pr_err("invalid IRQ value\n");
		return -ENODEV;
	}

	if (winbase < 0xC0000 || winbase > 0xDFFFF || (winbase & 0x3FFF) != 0) {
		pr_err("invalid RAM value\n");
		return -ENODEV;
	}

	card = kzalloc_obj(card_t);
	if (!card)
		return -ENOBUFS;

	card->dev = alloc_hdlcdev(card);
	if (!card->dev) {
		pr_err("unable to allocate memory\n");
		kfree(card);
		return -ENOBUFS;
	}

	if (request_irq(irq, sca_intr, 0, devname, card)) {
		pr_err("could not allocate IRQ\n");
		c101_destroy_card(card);
		return -EBUSY;
	}
	card->irq = irq;

	if (!request_mem_region(winbase, C101_MAPPED_RAM_SIZE, devname)) {
		pr_err("could not request RAM window\n");
		c101_destroy_card(card);
		return -EBUSY;
	}
	card->phy_winbase = winbase;
	card->win0base = ioremap(winbase, C101_MAPPED_RAM_SIZE);
	if (!card->win0base) {
		pr_err("could not map I/O address\n");
		c101_destroy_card(card);
		return -EFAULT;
	}

	card->tx_ring_buffers = TX_RING_BUFFERS;
	card->rx_ring_buffers = RX_RING_BUFFERS;
	card->buff_offset = C101_WINDOW_SIZE; /* Bytes 1D00-1FFF reserved */

	readb(card->win0base + C101_PAGE); /* Resets SCA? */
	udelay(100);
	writeb(0, card->win0base + C101_PAGE);
	writeb(0, card->win0base + C101_DTR); /* Power-up for RAM? */

	sca_init(card, 0);

	dev = port_to_dev(card);
	hdlc = dev_to_hdlc(dev);

	spin_lock_init(&card->lock);
	dev->irq = irq;
	dev->mem_start = winbase;
	dev->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1;
	dev->tx_queue_len = 50;
	dev->netdev_ops = &c101_ops;
	hdlc->attach = sca_attach;
	hdlc->xmit = sca_xmit;
	card->settings.clock_type = CLOCK_EXT;

	result = register_hdlc_device(dev);
	if (result) {
		pr_warn("unable to register hdlc device\n");
		c101_destroy_card(card);
		return result;
	}

	sca_init_port(card); /* Set up C101 memory */
	set_carrier(card);

Annotation

Implementation Notes