drivers/net/arcnet/com20020.c

Source file repositories/reference/linux-study-clean/drivers/net/arcnet/com20020.c

File Facts

System
Linux kernel
Corpus path
drivers/net/arcnet/com20020.c
Extension
.c
Size
12094 bytes
Lines
395
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

const struct net_device_ops com20020_netdev_ops = {
	.ndo_open	= com20020_netdev_open,
	.ndo_stop	= com20020_netdev_close,
	.ndo_start_xmit = arcnet_send_packet,
	.ndo_tx_timeout = arcnet_timeout,
	.ndo_set_mac_address = com20020_set_hwaddr,
	.ndo_set_rx_mode = com20020_set_rx_mode,
};

/* Set up the struct net_device associated with this card.  Called after
 * probing succeeds.
 */
int com20020_found(struct net_device *dev, int shared)
{
	struct arcnet_local *lp;
	int ioaddr = dev->base_addr;

	/* Initialize the rest of the device structure. */

	lp = netdev_priv(dev);

	lp->hw.owner = THIS_MODULE;
	lp->hw.command = com20020_command;
	lp->hw.status = com20020_status;
	lp->hw.intmask = com20020_setmask;
	lp->hw.reset = com20020_reset;
	lp->hw.copy_to_card = com20020_copy_to_card;
	lp->hw.copy_from_card = com20020_copy_from_card;
	lp->hw.close = com20020_close;

	/* FIXME: do this some other way! */
	if (!dev->dev_addr[0])
		arcnet_set_addr(dev, inb(ioaddr + 8));

	com20020_set_subaddress(lp, ioaddr, SUB_SETUP1);
	outb(lp->setup, ioaddr + COM20020_REG_W_XREG);

	if (lp->card_flags & ARC_CAN_10MBIT) {
		com20020_set_subaddress(lp, ioaddr, SUB_SETUP2);
		outb(lp->setup2, ioaddr + COM20020_REG_W_XREG);

		/* must now write the magic "restart operation" command */
		mdelay(1);
		outb(STARTIOcmd, ioaddr + COM20020_REG_W_COMMAND);
	}

	lp->config = (lp->timeout << 3) | (lp->backplane << 2) | SUB_NODE;
	/* Default 0x38 + register: Node ID */
	outb(lp->config, ioaddr + COM20020_REG_W_CONFIG);
	outb(dev->dev_addr[0], ioaddr + COM20020_REG_W_XREG);

	/* reserve the irq */
	if (request_irq(dev->irq, arcnet_interrupt, shared,
			"arcnet (COM20020)", dev)) {
		arc_printk(D_NORMAL, dev, "Can't get IRQ %d!\n", dev->irq);
		return -ENODEV;
	}

	arc_printk(D_NORMAL, dev, "%s: station %02Xh found at %03lXh, IRQ %d.\n",
		   lp->card_name, dev->dev_addr[0], dev->base_addr, dev->irq);

	if (lp->backplane)
		arc_printk(D_NORMAL, dev, "Using backplane mode.\n");

	if (lp->timeout != 3)
		arc_printk(D_NORMAL, dev, "Using extended timeout value of %d\n",
			   lp->timeout);

	arc_printk(D_NORMAL, dev, "Using CKP %d - data rate %s\n",
		   lp->setup >> 1,
		   clockrates[3 -
			      ((lp->setup2 & 0xF0) >> 4) +
			      ((lp->setup & 0x0F) >> 1)]);
			/* The clockrates array index looks very fragile.
			 * It seems like it could have negative indexing.
			 */

	if (register_netdev(dev)) {
		free_irq(dev->irq, dev);
		return -EIO;
	}
	return 0;
}

/* Do a hardware reset on the card, and set up necessary registers.
 *
 * This should be called as little as possible, because it disrupts the
 * token on the network (causes a RECON) and requires a significant delay.
 *
 * However, it does make sure the card is in a defined state.

Annotation

Implementation Notes