drivers/net/plip/plip.c

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

File Facts

System
Linux kernel
Corpus path
drivers/net/plip/plip.c
Extension
.c
Size
35908 bytes
Lines
1441
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 plip_netdev_ops = {
	.ndo_open		 = plip_open,
	.ndo_stop		 = plip_close,
	.ndo_start_xmit		 = plip_tx_packet,
	.ndo_siocdevprivate	 = plip_siocdevprivate,
	.ndo_set_mac_address	 = eth_mac_addr,
	.ndo_validate_addr	 = eth_validate_addr,
};

/* Entry point of PLIP driver.
   Probe the hardware, and register/initialize the driver.

   PLIP is rather weird, because of the way it interacts with the parport
   system.  It is _not_ initialised from Space.c.  Instead, plip_init()
   is called, and that function makes up a "struct net_device" for each port, and
   then calls us here.

   */
static void
plip_init_netdev(struct net_device *dev)
{
	static const u8 addr_init[ETH_ALEN] = {
		0xfc, 0xfc, 0xfc,
		0xfc, 0xfc, 0xfc,
	};
	struct net_local *nl = netdev_priv(dev);

	/* Then, override parts of it */
	dev->tx_queue_len 	 = 10;
	dev->flags	         = IFF_POINTOPOINT|IFF_NOARP;
	eth_hw_addr_set(dev, addr_init);

	dev->netdev_ops		 = &plip_netdev_ops;
	dev->header_ops          = &plip_header_ops;


	nl->port_owner = 0;

	/* Initialize constants */
	nl->trigger	= PLIP_TRIGGER_WAIT;
	nl->nibble	= PLIP_NIBBLE_WAIT;

	/* Initialize task queue structures */
	INIT_WORK(&nl->immediate, plip_bh);
	INIT_DELAYED_WORK(&nl->deferred, plip_kick_bh);

	if (dev->irq == -1)
		INIT_DELAYED_WORK(&nl->timer, plip_timer_bh);

	spin_lock_init(&nl->lock);
}

/* Bottom half handler for the delayed request.
   This routine is kicked by do_timer().
   Request `plip_bh' to be invoked. */
static void
plip_kick_bh(struct work_struct *work)
{
	struct net_local *nl =
		container_of(work, struct net_local, deferred.work);

	if (nl->is_deferred)
		schedule_work(&nl->immediate);
}

/* Forward declarations of internal routines */
static int plip_none(struct net_device *, struct net_local *,
		     struct plip_local *, struct plip_local *);
static int plip_receive_packet(struct net_device *, struct net_local *,
			       struct plip_local *, struct plip_local *);
static int plip_send_packet(struct net_device *, struct net_local *,
			    struct plip_local *, struct plip_local *);
static int plip_connection_close(struct net_device *, struct net_local *,
				 struct plip_local *, struct plip_local *);
static int plip_error(struct net_device *, struct net_local *,
		      struct plip_local *, struct plip_local *);
static int plip_bh_timeout_error(struct net_device *dev, struct net_local *nl,
				 struct plip_local *snd,
				 struct plip_local *rcv,
				 int error);

#define OK        0
#define TIMEOUT   1
#define ERROR     2
#define HS_TIMEOUT	3

typedef int (*plip_func)(struct net_device *dev, struct net_local *nl,
			 struct plip_local *snd, struct plip_local *rcv);

static const plip_func connection_state_table[] =

Annotation

Implementation Notes