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

📄 arcnet.c

📁 h内核
💻 C
📖 第 1 页 / 共 2 页
字号:
	struct ArcProto *proto;	if (skb->nh.raw - skb->mac.raw != 2) {		BUGMSG(D_NORMAL,		     "rebuild_header: shouldn't be here! (hdrsize=%d)\n",		     (int)(skb->nh.raw - skb->mac.raw));		return 0;	}	type = *(uint16_t *) skb_pull(skb, 2);	BUGMSG(D_DURING, "rebuild header for protocol %Xh\n", type);	if (type == ETH_P_IP) {#ifdef CONFIG_INET		BUGMSG(D_DURING, "rebuild header for ethernet protocol %Xh\n", type);		status = arp_find(&daddr, skb) ? 1 : 0;		BUGMSG(D_DURING, " rebuilt: dest is %d; protocol %Xh\n",		       daddr, type);#endif	} else {		BUGMSG(D_NORMAL,		       "I don't understand ethernet protocol %Xh addresses!\n", type);		lp->stats.tx_errors++;		lp->stats.tx_aborted_errors++;	}	/* if we couldn't resolve the address... give up. */	if (!status)		return 0;	/* add the _real_ header this time! */	proto = arc_proto_map[lp->default_proto[daddr]];	proto->build_header(skb, dev, type, daddr);	return 1;		/* success */}/* Called by the kernel in order to transmit a packet. */static int arcnet_send_packet(struct sk_buff *skb, struct net_device *dev){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	struct archdr *pkt;	struct arc_rfc1201 *soft;	struct ArcProto *proto;	int txbuf;	unsigned long flags;	int freeskb = 0;	BUGMSG(D_DURING,	       "transmit requested (status=%Xh, txbufs=%d/%d, len=%d, protocol %x)\n",	       ASTATUS(), lp->cur_tx, lp->next_tx, skb->len,skb->protocol);	pkt = (struct archdr *) skb->data;	soft = &pkt->soft.rfc1201;	proto = arc_proto_map[soft->proto];	BUGMSG(D_SKB_SIZE, "skb: transmitting %d bytes to %02X\n",		skb->len, pkt->hard.dest);	BUGLVL(D_SKB) arcnet_dump_skb(dev, skb, "tx");	/* fits in one packet? */	if (skb->len - ARC_HDR_SIZE > XMTU && !proto->continue_tx) {		BUGMSG(D_NORMAL, "fixme: packet too large: compensating badly!\n");		dev_kfree_skb(skb);		return 0;	/* don't try again */	}	/* We're busy transmitting a packet... */	netif_stop_queue(dev);	spin_lock_irqsave(&lp->lock, flags);	AINTMASK(0);	txbuf = get_arcbuf(dev);	if (txbuf != -1) {		if (proto->prepare_tx(dev, pkt, skb->len, txbuf) &&		    !proto->ack_tx) {			/* done right away and we don't want to acknowledge			   the package later - forget about it now */			lp->stats.tx_bytes += skb->len;			freeskb = 1;		} else {			/* do it the 'split' way */			lp->outgoing.proto = proto;			lp->outgoing.skb = skb;			lp->outgoing.pkt = pkt;			if (proto->continue_tx &&			    proto->continue_tx(dev, txbuf)) {			  BUGMSG(D_NORMAL,				 "bug! continue_tx finished the first time! "				 "(proto='%c')\n", proto->suffix);			}		}		lp->next_tx = txbuf;	} else {		freeskb = 1;	}	BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());	/* make sure we didn't ignore a TX IRQ while we were in here */	AINTMASK(0);	BUGMSG(D_DEBUG, "%s: %d: %s\n",__FILE__,__LINE__,__FUNCTION__);	lp->intmask |= TXFREEflag|EXCNAKflag;	AINTMASK(lp->intmask);	BUGMSG(D_DEBUG, "%s: %d: %s, status: %x\n",__FILE__,__LINE__,__FUNCTION__,ASTATUS());	spin_unlock_irqrestore(&lp->lock, flags);	if (freeskb) {		dev_kfree_skb(skb);	}	return 0;		/* no need to try again */}/* * Actually start transmitting a packet that was loaded into a buffer * by prepare_tx.  This should _only_ be called by the interrupt handler. */static int go_tx(struct net_device *dev){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	BUGMSG(D_DURING, "go_tx: status=%Xh, intmask=%Xh, next_tx=%d, cur_tx=%d\n",	       ASTATUS(), lp->intmask, lp->next_tx, lp->cur_tx);	if (lp->cur_tx != -1 || lp->next_tx == -1)		return 0;	BUGLVL(D_TX) arcnet_dump_packet(dev, lp->next_tx, "go_tx", 0);	lp->cur_tx = lp->next_tx;	lp->next_tx = -1;	/* start sending */	ACOMMAND(TXcmd | (lp->cur_tx << 3));	dev->trans_start = jiffies;	lp->stats.tx_packets++;	lp->lasttrans_dest = lp->lastload_dest;	lp->lastload_dest = 0;	lp->excnak_pending = 0;	lp->intmask |= TXFREEflag|EXCNAKflag;	return 1;}/* Called by the kernel when transmit times out */static void arcnet_timeout(struct net_device *dev){	unsigned long flags;	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	int status = ASTATUS();	char *msg;	spin_lock_irqsave(&lp->lock, flags);	if (status & TXFREEflag) {	/* transmit _DID_ finish */		msg = " - missed IRQ?";	} else {		msg = "";		lp->stats.tx_aborted_errors++;		lp->timed_out = 1;		ACOMMAND(NOTXcmd | (lp->cur_tx << 3));	}	lp->stats.tx_errors++;	/* make sure we didn't miss a TX or a EXC NAK IRQ */	AINTMASK(0);	lp->intmask |= TXFREEflag|EXCNAKflag;	AINTMASK(lp->intmask);		spin_unlock_irqrestore(&lp->lock, flags);	if (jiffies - lp->last_timeout > 10*HZ) {		BUGMSG(D_EXTRA, "tx timed out%s (status=%Xh, intmask=%Xh, dest=%02Xh)\n",		       msg, status, lp->intmask, lp->lasttrans_dest);		lp->last_timeout = jiffies;	}	if (lp->cur_tx == -1)		netif_wake_queue(dev);}/* * The typical workload of the driver: Handle the network interface * interrupts. Establish which device needs attention, and call the correct * chipset interrupt handler. */irqreturn_t arcnet_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = dev_id;	struct arcnet_local *lp;	int recbuf, status, diagstatus, didsomething, boguscount;	int retval = IRQ_NONE;	BUGMSG(D_DURING, "\n");	BUGMSG(D_DURING, "in arcnet_interrupt\n");		lp = (struct arcnet_local *) dev->priv;	if (!lp)		BUG();			spin_lock(&lp->lock);	/*	 * RESET flag was enabled - if device is not running, we must clear it right	 * away (but nothing else).	 */	if (!netif_running(dev)) {		if (ASTATUS() & RESETflag)			ACOMMAND(CFLAGScmd | RESETclear);		AINTMASK(0);		spin_unlock(&lp->lock);		return IRQ_HANDLED;	}	BUGMSG(D_DURING, "in arcnet_inthandler (status=%Xh, intmask=%Xh)\n",	       ASTATUS(), lp->intmask);	boguscount = 5;	do {		status = ASTATUS();                diagstatus = (status >> 8) & 0xFF;		BUGMSG(D_DEBUG, "%s: %d: %s: status=%x\n",			__FILE__,__LINE__,__FUNCTION__,status);		didsomething = 0;		/*		 * RESET flag was enabled - card is resetting and if RX is		 * disabled, it's NOT because we just got a packet.		 * 		 * The card is in an undefined state.  Clear it out and start over.		 */		if (status & RESETflag) {			BUGMSG(D_NORMAL, "spurious reset (status=%Xh)\n", status);			arcnet_close(dev);			arcnet_open(dev);			/* get out of the interrupt handler! */			break;		}		/* 		 * RX is inhibited - we must have received something. Prepare to		 * receive into the next buffer.		 * 		 * We don't actually copy the received packet from the card until		 * after the transmit handler runs (and possibly launches the next		 * tx); this should improve latency slightly if we get both types		 * of interrupts at once. 		 */		recbuf = -1;		if (status & lp->intmask & NORXflag) {			recbuf = lp->cur_rx;			BUGMSG(D_DURING, "Buffer #%d: receive irq (status=%Xh)\n",			       recbuf, status);			lp->cur_rx = get_arcbuf(dev);			if (lp->cur_rx != -1) {				BUGMSG(D_DURING, "enabling receive to buffer #%d\n",				       lp->cur_rx);				ACOMMAND(RXcmd | (lp->cur_rx << 3) | RXbcasts);			}			didsomething++;		}		if((diagstatus & EXCNAKflag)) {			BUGMSG(D_DURING, "EXCNAK IRQ (diagstat=%Xh)\n",			       diagstatus);                        ACOMMAND(NOTXcmd);      /* disable transmit */                        lp->excnak_pending = 1;                        ACOMMAND(EXCNAKclear);			lp->intmask &= ~(EXCNAKflag);                        didsomething++;                }		/* a transmit finished, and we're interested in it. */		if ((status & lp->intmask & TXFREEflag) || lp->timed_out) {			lp->intmask &= ~(TXFREEflag|EXCNAKflag);			BUGMSG(D_DURING, "TX IRQ (stat=%Xh)\n", status);			if (lp->cur_tx != -1 && !lp->timed_out) {				if(!(status & TXACKflag)) {					if (lp->lasttrans_dest != 0) {						BUGMSG(D_EXTRA,						       "transmit was not acknowledged! "						       "(status=%Xh, dest=%02Xh)\n",						       status, lp->lasttrans_dest);						lp->stats.tx_errors++;						lp->stats.tx_carrier_errors++;					} else {						BUGMSG(D_DURING,						       "broadcast was not acknowledged; that's normal "						       "(status=%Xh, dest=%02Xh)\n",						       status, lp->lasttrans_dest);					}				}				if (lp->outgoing.proto &&				    lp->outgoing.proto->ack_tx) {				  int ackstatus;				  if(status & TXACKflag)                                    ackstatus=2;                                  else if(lp->excnak_pending)                                    ackstatus=1;                                  else                                    ackstatus=0;                                  lp->outgoing.proto                                    ->ack_tx(dev, ackstatus);				}			}			if (lp->cur_tx != -1)				release_arcbuf(dev, lp->cur_tx);			lp->cur_tx = -1;			lp->timed_out = 0;			didsomething++;			/* send another packet if there is one */			go_tx(dev);			/* continue a split packet, if any */			if (lp->outgoing.proto && lp->outgoing.proto->continue_tx) {				int txbuf = get_arcbuf(dev);				if (txbuf != -1) {					if (lp->outgoing.proto->continue_tx(dev, txbuf)) {						/* that was the last segment */						lp->stats.tx_bytes += lp->outgoing.skb->len;						if(!lp->outgoing.proto->ack_tx)						  {						    dev_kfree_skb_irq(lp->outgoing.skb);						    lp->outgoing.proto = NULL;						  }					}					lp->next_tx = txbuf;				}			}			/* inform upper layers of idleness, if necessary */			if (lp->cur_tx == -1)				netif_wake_queue(dev);		}		/* now process the received packet, if any */		if (recbuf != -1) {			BUGLVL(D_RX) arcnet_dump_packet(dev, recbuf, "rx irq", 0);			arcnet_rx(dev, recbuf);			release_arcbuf(dev, recbuf);			didsomething++;		}		if (status & lp->intmask & RECONflag) {			ACOMMAND(CFLAGScmd | CONFIGclear);			lp->stats.tx_carrier_errors++;			BUGMSG(D_RECON, "Network reconfiguration detected (status=%Xh)\n",			       status);			/* is the RECON info empty or old? */			if (!lp->first_recon || !lp->last_recon ||			    jiffies - lp->last_recon > HZ * 10) {				if (lp->network_down)					BUGMSG(D_NORMAL, "reconfiguration detected: cabling restored?\n");				lp->first_recon = lp->last_recon = jiffies;				lp->num_recons = lp->network_down = 0;				BUGMSG(D_DURING, "recon: clearing counters.\n");			} else {	/* add to current RECON counter */				lp->last_recon = jiffies;				lp->num_recons++;				BUGMSG(D_DURING, "recon: counter=%d, time=%lds, net=%d\n",				       lp->num_recons,				 (lp->last_recon - lp->first_recon) / HZ,				       lp->network_down);				/* if network is marked up;				 * and first_recon and last_recon are 60+ apart;				 * and the average no. of recons counted is				 *    > RECON_THRESHOLD/min;				 * then print a warning message.				 */				if (!lp->network_down				    && (lp->last_recon - lp->first_recon) <= HZ * 60				  && lp->num_recons >= RECON_THRESHOLD) {					lp->network_down = 1;					BUGMSG(D_NORMAL, "many reconfigurations detected: cabling problem?\n");				} else if (!lp->network_down					   && lp->last_recon - lp->first_recon > HZ * 60) {					/* reset counters if we've gone for over a minute. */					lp->first_recon = lp->last_recon;					lp->num_recons = 1;				}			}		} else if (lp->network_down && jiffies - lp->last_recon > HZ * 10) {			if (lp->network_down)				BUGMSG(D_NORMAL, "cabling restored?\n");			lp->first_recon = lp->last_recon = 0;			lp->num_recons = lp->network_down = 0;			BUGMSG(D_DURING, "not recon: clearing counters anyway.\n");		}		if(didsomething) {			retval |= IRQ_HANDLED;		}	}	while (--boguscount && didsomething);	BUGMSG(D_DURING, "arcnet_interrupt complete (status=%Xh, count=%d)\n",	       ASTATUS(), boguscount);	BUGMSG(D_DURING, "\n");	AINTMASK(0);	udelay(1);	AINTMASK(lp->intmask);		spin_unlock(&lp->lock);	return retval;}/* * This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. */void arcnet_rx(struct net_device *dev, int bufnum){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	struct archdr pkt;	struct arc_rfc1201 *soft;	int length, ofs;	soft = &pkt.soft.rfc1201;	lp->hw.copy_from_card(dev, bufnum, 0, &pkt, sizeof(ARC_HDR_SIZE));	if (pkt.hard.offset[0]) {		ofs = pkt.hard.offset[0];		length = 256 - ofs;	} else {		ofs = pkt.hard.offset[1];		length = 512 - ofs;	}	/* get the full header, if possible */	if (sizeof(pkt.soft) <= length)		lp->hw.copy_from_card(dev, bufnum, ofs, soft, sizeof(pkt.soft));	else {		memset(&pkt.soft, 0, sizeof(pkt.soft));		lp->hw.copy_from_card(dev, bufnum, ofs, soft, length);	}	BUGMSG(D_DURING, "Buffer #%d: received packet from %02Xh to %02Xh "	       "(%d+4 bytes)\n",	       bufnum, pkt.hard.source, pkt.hard.dest, length);	lp->stats.rx_packets++;	lp->stats.rx_bytes += length + ARC_HDR_SIZE;	/* call the right receiver for the protocol */	if (arc_proto_map[soft->proto]->is_ip) {		BUGLVL(D_PROTO) {			struct ArcProto			*oldp = arc_proto_map[lp->default_proto[pkt.hard.source]],			*newp = arc_proto_map[soft->proto];			if (oldp != newp) {				BUGMSG(D_PROTO,				       "got protocol %02Xh; encap for host %02Xh is now '%c'"				       " (was '%c')\n", soft->proto, pkt.hard.source,				       newp->suffix, oldp->suffix);			}		}		/* broadcasts will always be done with the last-used encap. */		lp->default_proto[0] = soft->proto;		/* in striking contrast, the following isn't a hack. */		lp->default_proto[pkt.hard.source] = soft->proto;	}	/* call the protocol-specific receiver. */	arc_proto_map[soft->proto]->rx(dev, bufnum, &pkt, length);}/*  * Get the current statistics.  This may be called with the card open or * closed. */static struct net_device_stats *arcnet_get_stats(struct net_device *dev){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	return &lp->stats;}static void null_rx(struct net_device *dev, int bufnum,		    struct archdr *pkthdr, int length){	BUGMSG(D_PROTO,	"rx: don't know how to deal with proto %02Xh from host %02Xh.\n",	       pkthdr->soft.rfc1201.proto, pkthdr->hard.source);}static int null_build_header(struct sk_buff *skb, struct net_device *dev,			     unsigned short type, uint8_t daddr){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	BUGMSG(D_PROTO,	       "tx: can't build header for encap %02Xh; load a protocol driver.\n",	       lp->default_proto[daddr]);	/* always fails */	return 0;}/* the "do nothing" prepare_tx function warns that there's nothing to do. */static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,			   int length, int bufnum){	struct arcnet_local *lp = (struct arcnet_local *) dev->priv;	struct arc_hardware newpkt;	BUGMSG(D_PROTO, "tx: no encap for this host; load a protocol driver.\n");	/* send a packet to myself -- will never get received, of course */	newpkt.source = newpkt.dest = dev->dev_addr[0];	/* only one byte of actual data (and it's random) */	newpkt.offset[0] = 0xFF;	lp->hw.copy_to_card(dev, bufnum, 0, &newpkt, ARC_HDR_SIZE);	return 1;		/* done */}

⌨️ 快捷键说明

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