⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 plip.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
		if (net_debug > 1)			printk(KERN_DEBUG "%s: spurious interrupt\n", dev->name);		return;	}	dev->interrupt = 1;	if (net_debug > 3)		printk(KERN_DEBUG "%s: interrupt.\n", dev->name);	spin_lock_irq(&nl->lock);	switch (nl->connection) {	case PLIP_CN_CLOSING:		dev->tbusy = 0;	case PLIP_CN_NONE:	case PLIP_CN_SEND:		dev->last_rx = jiffies;		rcv->state = PLIP_PK_TRIGGER;		nl->connection = PLIP_CN_RECEIVE;		nl->timeout_count = 0;		queue_task(&nl->immediate, &tq_immediate);		mark_bh(IMMEDIATE_BH);		spin_unlock_irq(&nl->lock);		break;	case PLIP_CN_RECEIVE:		/* May occur because there is race condition		   around test and set of dev->interrupt.		   Ignore this interrupt. */		spin_unlock_irq(&nl->lock);		break;	case PLIP_CN_ERROR:		spin_unlock_irq(&nl->lock);		printk(KERN_ERR "%s: receive interrupt in error state\n", dev->name);		break;	}}/* We don't need to send arp, for plip is point-to-point. */static intplip_rebuild_header(struct sk_buff *skb){	struct device *dev = skb->dev;	struct net_local *nl = (struct net_local *)dev->priv;	struct ethhdr *eth = (struct ethhdr *)skb->data;	if ((dev->flags & IFF_NOARP)==0)		return nl->orig_rebuild_header(skb);	memcpy(eth->h_source, dev->dev_addr, dev->addr_len);	memcpy(eth->h_dest, dev->broadcast, dev->addr_len);	return 0;}static intplip_tx_packet(struct sk_buff *skb, struct device *dev){	struct net_local *nl = (struct net_local *)dev->priv;	struct plip_local *snd = &nl->snd_data;	if (dev->tbusy)		return 1;	/* We may need to grab the bus */	if (!nl->port_owner) {		if (parport_claim(nl->pardev))			return 1;		nl->port_owner = 1;	}	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);		return 1;	}	if (skb->len > dev->mtu + dev->hard_header_len) {		printk(KERN_WARNING "%s: packet too big, %d.\n", dev->name, (int)skb->len);		dev->tbusy = 0;		return 0;	}	if (net_debug > 2)		printk(KERN_DEBUG "%s: send request\n", dev->name);	spin_lock_irq(&nl->lock);	dev->trans_start = jiffies;	snd->skb = skb;	snd->length.h = skb->len;	snd->state = PLIP_PK_TRIGGER;	if (nl->connection == PLIP_CN_NONE) {		nl->connection = PLIP_CN_SEND;		nl->timeout_count = 0;	}	queue_task(&nl->immediate, &tq_immediate);	mark_bh(IMMEDIATE_BH);	spin_unlock_irq(&nl->lock);	return 0;}/* Open/initialize the board.  This is called (in the current kernel)   sometime after booting when the 'ifconfig' program is run.   This routine gets exclusive access to the parallel port by allocating   its IRQ line. */static intplip_open(struct device *dev){	struct net_local *nl = (struct net_local *)dev->priv;	struct in_device *in_dev;	/* Grab the port */	if (!nl->port_owner) {		if (parport_claim(nl->pardev)) return -EAGAIN;		nl->port_owner = 1;	}	nl->should_relinquish = 0;	/* Clear the data port. */	outb (0x00, PAR_DATA(dev));	/* Enable rx interrupt. */	outb(PAR_INTR_ON, PAR_CONTROL(dev));	/* Initialize the state machine. */	nl->rcv_data.state = nl->snd_data.state = PLIP_PK_DONE;	nl->rcv_data.skb = nl->snd_data.skb = NULL;	nl->connection = PLIP_CN_NONE;	nl->is_deferred = 0;	/* Fill in the MAC-level header.	   (ab)Use "dev->broadcast" to store point-to-point MAC address.	   PLIP doesn't have a real mac address, but we need to create one	   to be DOS compatible.  */	memset(dev->dev_addr,  0xfc, ETH_ALEN);	memset(dev->broadcast, 0xfc, ETH_ALEN);	if ((in_dev=dev->ip_ptr) != NULL) {		/*		 *	Any address will do - we take the first		 */		struct in_ifaddr *ifa=in_dev->ifa_list;		if (ifa != NULL) {			memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);			memcpy(dev->broadcast+2, &ifa->ifa_address, 4);		}	}	dev->interrupt = 0;	dev->start = 1;	dev->tbusy = 0;	MOD_INC_USE_COUNT;	return 0;}/* The inverse routine to plip_open (). */static intplip_close(struct device *dev){	struct net_local *nl = (struct net_local *)dev->priv;	struct plip_local *snd = &nl->snd_data;	struct plip_local *rcv = &nl->rcv_data;	dev->tbusy = 1;	dev->start = 0;	DISABLE(dev->irq);	synchronize_irq();#ifdef NOTDEF	outb(0x00, PAR_DATA(dev));#endif	nl->is_deferred = 0;	nl->connection = PLIP_CN_NONE;	if (nl->port_owner) {		parport_release(nl->pardev);		nl->port_owner = 0;	}	snd->state = PLIP_PK_DONE;	if (snd->skb) {		dev_kfree_skb(snd->skb);		snd->skb = NULL;	}	rcv->state = PLIP_PK_DONE;	if (rcv->skb) {		kfree_skb(rcv->skb);		rcv->skb = NULL;	}#ifdef NOTDEF	/* Reset. */	outb(0x00, PAR_CONTROL(dev));#endif	MOD_DEC_USE_COUNT;	return 0;}static intplip_preempt(void *handle){	struct device *dev = (struct device *)handle;	struct net_local *nl = (struct net_local *)dev->priv;	/* Stand our ground if a datagram is on the wire */	if (nl->connection != PLIP_CN_NONE) {		nl->should_relinquish = 1;		return 1;	}	nl->port_owner = 0;	/* Remember that we released the bus */	return 0;}static voidplip_wakeup(void *handle){	struct device *dev = (struct device *)handle;	struct net_local *nl = (struct net_local *)dev->priv;	if (nl->port_owner) {		/* Why are we being woken up? */		printk(KERN_DEBUG "%s: why am I being woken up?\n", dev->name);		if (!parport_claim(nl->pardev))			/* bus_owner is already set (but why?) */			printk(KERN_DEBUG "%s: I'm broken.\n", dev->name);		else			return;	}		if (!(dev->flags & IFF_UP))		/* Don't need the port when the interface is down */		return;	if (!parport_claim(nl->pardev)) {		nl->port_owner = 1;		/* Clear the data port. */		outb (0x00, PAR_DATA(dev));	}	return;}static struct net_device_stats *plip_get_stats(struct device *dev){	struct net_local *nl = (struct net_local *)dev->priv;	struct net_device_stats *r = &nl->enet_stats;	return r;}static intplip_config(struct device *dev, struct ifmap *map){	struct net_local *nl = (struct net_local *) dev->priv;	struct pardevice *pardev = nl->pardev;	if (dev->flags & IFF_UP)		return -EBUSY;	printk(KERN_WARNING "plip: Warning, changing irq with ifconfig will be obsoleted.\n");	printk(KERN_WARNING "plip: Next time, please set with /proc/parport/*/irq instead.\n");	if (map->irq != (unsigned char)-1) {		pardev->port->irq = dev->irq = map->irq;		/* Dummy request */		request_irq(dev->irq, plip_interrupt, SA_INTERRUPT,			    pardev->name, NULL);	}	return 0;}static intplip_ioctl(struct device *dev, struct ifreq *rq, int cmd){	struct net_local *nl = (struct net_local *) dev->priv;	struct plipconf *pc = (struct plipconf *) &rq->ifr_data;	switch(pc->pcmd) {	case PLIP_GET_TIMEOUT:		pc->trigger = nl->trigger;		pc->nibble  = nl->nibble;		break;	case PLIP_SET_TIMEOUT:		nl->trigger = pc->trigger;		nl->nibble  = pc->nibble;		break;	default:		return -EOPNOTSUPP;	}	return 0;}static int parport[PLIP_MAX] = { [0 ... PLIP_MAX-1] = -1 };static int timid = 0;MODULE_PARM(parport, "1-" __MODULE_STRING(PLIP_MAX) "i");MODULE_PARM(timid, "1i");static struct device *dev_plip[PLIP_MAX] = { NULL, };#ifdef MODULEvoidcleanup_module(void){	int i;	for (i=0; i < PLIP_MAX; i++) {		if (dev_plip[i]) {			struct net_local *nl =				(struct net_local *)dev_plip[i]->priv;			unregister_netdev(dev_plip[i]);			if (nl->port_owner)				parport_release(nl->pardev);			parport_unregister_device(nl->pardev);			kfree(dev_plip[i]->priv);			kfree(dev_plip[i]->name);			kfree(dev_plip[i]);			dev_plip[i] = NULL;		}	}}#define plip_init  init_module#else /* !MODULE */static int parport_ptr = 0;void plip_setup(char *str, int *ints){	/* Ugh. */	if (!strncmp(str, "parport", 7)) {		int n = simple_strtoul(str+7, NULL, 10);		if (parport_ptr < PLIP_MAX)			parport[parport_ptr++] = n;		else			printk(KERN_INFO "plip: too many ports, %s ignored.\n",			       str);	} else if (!strcmp(str, "timid")) {		timid = 1;	} else {		if (ints[0] == 0 || ints[1] == 0) {			/* disable driver on "plip=" or "plip=0" */			parport[0] = -2;		} else {			printk(KERN_WARNING "warning: 'plip=0x%x' ignored\n", 			       ints[1]);		}	}}#endif /* MODULE */static int inline plip_searchfor(int list[], int a){	int i;	for (i = 0; i < PLIP_MAX && list[i] != -1; i++) {		if (list[i] == a) return 1;	}	return 0;}__initfunc(intplip_init(void)){	struct parport *pb = parport_enumerate();	int i=0;	if (parport[0] == -2)		return 0;	if (parport[0] != -1 && timid) {		printk(KERN_WARNING "plip: warning, ignoring `timid' since specific ports given.\n");		timid = 0;	}	/* If the user feeds parameters, use them */	while (pb) {		if ((parport[0] == -1 && (!timid || !pb->devices)) || 		    plip_searchfor(parport, pb->number)) {			if (i == PLIP_MAX) {				printk(KERN_ERR "plip: too many devices\n");				break;			}			dev_plip[i] = kmalloc(sizeof(struct device),					      GFP_KERNEL);			if (!dev_plip[i]) {				printk(KERN_ERR "plip: memory squeeze\n");				break;			}			memset(dev_plip[i], 0, sizeof(struct device));			dev_plip[i]->name = 				kmalloc(strlen("plipXXX"), GFP_KERNEL);			if (!dev_plip[i]->name) {				printk(KERN_ERR "plip: memory squeeze.\n");				kfree(dev_plip[i]);				break;			}			sprintf(dev_plip[i]->name, "plip%d", i);			dev_plip[i]->priv = pb;			if (plip_init_dev(dev_plip[i],pb) || register_netdev(dev_plip[i])) {				kfree(dev_plip[i]->name);				kfree(dev_plip[i]);			} else {				i++;			}		}		pb = pb->next;  	}	if (i == 0) {		printk(KERN_INFO "plip: no devices registered\n");		return -EIO;	}	return 0;}/* * Local variables: * compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -g -fomit-frame-pointer -pipe -c plip.c" * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -