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

📄 arcnet.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif  /* Shut down the card */  /* Disable TX if we need to */  if (lp->en_dis_able_TX)    (*lp->en_dis_able_TX)(dev, 0);  (*lp->arcnet_reset)(dev, 3);	/* reset IRQ won't run if START=0 */#if 0  lp->intmask=0;  SETMASK;		/* no IRQ's (except RESET, of course) */  ACOMMAND(NOTXcmd);	/* stop transmit */  ACOMMAND(NORXcmd);	/* disable receive */#endif  /* reset more flags */  dev->interrupt=0;#ifdef CONFIG_ARCNET_ETH  lp->edev->interrupt=0;#endif#ifdef CONFIG_ARCNET_1051  lp->sdev->interrupt=0;#endif  /* do NOT free lp->adev!!  It's static! */  lp->adev=NULL;#ifdef CONFIG_ARCNET_ETH  /* free the ethernet-encap protocol device */  lp->edev->priv=NULL;  unregister_netdevice(lp->edev);  kfree(lp->edev->name);  kfree(lp->edev);  lp->edev=NULL;#endif#ifdef CONFIG_ARCNET_1051  /* free the RFC1051-encap protocol device */  lp->sdev->priv=NULL;  unregister_netdevice(lp->sdev);  kfree(lp->sdev->name);  kfree(lp->sdev);  lp->sdev=NULL;#endif  /* Update the statistics here. (not necessary in ARCnet) */  /* Decrease the use count */  (*lp->openclose_device)(0);  return 0;}/**************************************************************************** *                                                                          * * Transmitter routines                                                     * *                                                                          * ****************************************************************************//* Generic error checking routine for arcnet??_send_packet */static intarcnet_send_packet_bad(struct sk_buff *skb, struct device *dev){  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;  BUGMSG(D_DURING,"transmit requested (status=%Xh, inTX=%d)\n",	 ARCSTATUS,lp->intx);  if (lp->in_txhandler)    {      BUGMSG(D_NORMAL,"send_packet called while in txhandler!\n");      lp->stats.tx_dropped++;      return 1;    }  if (lp->intx>1)    {      BUGMSG(D_NORMAL,"send_packet called while intx!\n");      lp->stats.tx_dropped++;      return 1;    }  if (test_bit(0, (int *)&dev->tbusy))    {      /* If we get here, some higher level has decided we are broken.	 There should really be a "kick me" function call instead. */      int tickssofar = jiffies - dev->trans_start;      int status=ARCSTATUS;      if (tickssofar < TX_TIMEOUT)	{	  BUGMSG(D_DURING,"premature kickme! (status=%Xh ticks=%d o.skb=%ph numsegs=%d segnum=%d\n",		 status,tickssofar,lp->outgoing.skb,		 lp->outgoing.numsegs,		 lp->outgoing.segnum);	  return 1;	}      lp->intmask &= ~TXFREEflag;      SETMASK;      if (status&TXFREEflag)	/* transmit _DID_ finish */	{	  BUGMSG(D_NORMAL,"tx timeout - missed IRQ? (status=%Xh, ticks=%d, mask=%Xh, dest=%02Xh)\n",		 status,tickssofar,lp->intmask,lp->lasttrans_dest);	  lp->stats.tx_errors++;	}      else	{	  BUGMSG(D_EXTRA,"tx timed out (status=%Xh, tickssofar=%d, intmask=%Xh, dest=%02Xh)\n",		 status,tickssofar,lp->intmask,lp->lasttrans_dest);	  lp->stats.tx_errors++;	  lp->stats.tx_aborted_errors++;	  ACOMMAND(NOTXcmd);	}      if (lp->outgoing.skb)	{	  dev_kfree_skb(lp->outgoing.skb);	  lp->stats.tx_dropped++;	}      lp->outgoing.skb=NULL;#ifdef CONFIG_ARCNET_ETH      lp->edev->tbusy=0;#endif#ifdef CONFIG_ARCNET_1051      lp->sdev->tbusy=0;#endif      if (!test_and_clear_bit(0,(int *)&dev->tbusy))	BUGMSG(D_EXTRA, "after timing out, tbusy was clear!\n");      lp->txready=0;      lp->sending=0;      return 1;    }  if (lp->txready)	/* transmit already in progress! */    {      BUGMSG(D_NORMAL,"trying to start new packet while busy! (status=%Xh)\n",	     ARCSTATUS);      lp->intmask &= ~TXFREEflag;      SETMASK;      ACOMMAND(NOTXcmd); /* abort current send */      (*lp->inthandler)(dev); /* fake an interrupt */      lp->stats.tx_errors++;      lp->stats.tx_fifo_errors++;      lp->txready=0;	/* we definitely need this line! */      return 1;    }  /* Block a timer-based transmit from overlapping.  This could better be     done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */  if (test_and_set_bit(0, (int *)&lp->adev->tbusy))    {      BUGMSG(D_NORMAL,"transmitter called with busy bit set! (status=%Xh, inTX=%d, tickssofar=%ld)\n",	     ARCSTATUS,lp->intx,jiffies-dev->trans_start);      lp->stats.tx_errors++;      lp->stats.tx_fifo_errors++;      return -EBUSY;    }#ifdef CONFIG_ARCNET_1051  lp->sdev->tbusy=1;#endif#ifdef CONFIG_ARCNET_ETH  lp->edev->tbusy=1;#endif  return 0;}/* Called by the kernel in order to transmit a packet. */static intarcnetA_send_packet(struct sk_buff *skb, struct device *dev){  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;  int bad,oldmask=0;  struct Outgoing *out=&(lp->outgoing);  lp->intx++;  oldmask |= lp->intmask;  lp->intmask=0;  SETMASK;  bad=arcnet_send_packet_bad(skb,dev);  if (bad)    {      lp->intx--;      lp->intmask=oldmask;      SETMASK;      return bad;    }  /* arcnet_send_packet_pad has already set tbusy - don't bother here. */  lp->intmask = oldmask & ~TXFREEflag;  SETMASK;  out->length = 1 < skb->len ? skb->len : 1;  out->hdr=(struct ClientData*)skb->data;  out->skb=skb;  BUGLVL(D_SKB) arcnet_dump_skb(dev,skb,"tx");  out->hdr->sequence=(lp->sequence++);  /* fits in one packet? */  if (out->length-EXTRA_CLIENTDATA<=XMTU)    {      BUGMSG(D_DURING,"not splitting %d-byte packet. (split_flag=%d)\n",	     out->length,out->hdr->split_flag);      if (out->hdr->split_flag)	BUGMSG(D_NORMAL,"short packet has split_flag set?! (split_flag=%d)\n",	       out->hdr->split_flag);      out->numsegs=1;      out->segnum=1;      (*lp->prepare_tx)(dev,			((char *)out->hdr)+EXTRA_CLIENTDATA,			sizeof(struct ClientData)-EXTRA_CLIENTDATA,			((char *)skb->data)+sizeof(struct ClientData),			out->length-sizeof(struct ClientData),			out->hdr->daddr,1,0);      /* done right away */      lp->stats.tx_bytes += out->skb->len;      dev_kfree_skb(out->skb);      out->skb=NULL;      if (arcnet_go_tx(dev,1))	{	  /* inform upper layers */	  arcnet_tx_done(dev, lp);	}    }  else			/* too big for one - split it */    {      int maxsegsize=XMTU-4;      out->data=(u_char *)skb->data	+ sizeof(struct ClientData);      out->dataleft=out->length-sizeof(struct ClientData);      out->numsegs=(out->dataleft+maxsegsize-1)/maxsegsize;      out->segnum=0;      BUGMSG(D_TX,"packet (%d bytes) split into %d fragments:\n",	     out->length,out->numsegs);      /* if a packet waiting, launch it */      arcnet_go_tx(dev,1);      if (!lp->txready)	{	  /* prepare a packet, launch it and prepare	   * another.	   */	  arcnetA_continue_tx(dev);	  if (arcnet_go_tx(dev,1))	    {	      arcnetA_continue_tx(dev);	      arcnet_go_tx(dev,1);	    }	}      /* if segnum==numsegs, the transmission is finished;       * free the skb right away.       */      if (out->segnum==out->numsegs)	{	  /* transmit completed */	  out->segnum++;	  if (out->skb)	    {	      lp->stats.tx_bytes += skb->len;	      dev_kfree_skb(out->skb);	    }	  out->skb=NULL;	}    }  dev->trans_start=jiffies;  lp->intx--;  /* make sure we didn't ignore a TX IRQ while we were in here */  lp->intmask |= TXFREEflag;  SETMASK;  return 0;}/* After an RFC1201 split packet has been set up, this function calls * arcnetAS_prepare_tx to load the next segment into the card.  This function * does NOT automatically call arcnet_go_tx. */void arcnetA_continue_tx(struct device *dev){  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;  int maxsegsize=XMTU-4;  struct Outgoing *out=&(lp->outgoing);  BUGMSG(D_DURING,"continue_tx called (status=%Xh, intx=%d, intxh=%d, intmask=%Xh\n",	 ARCSTATUS,lp->intx,lp->in_txhandler,lp->intmask);  if (lp->txready)    {      BUGMSG(D_NORMAL,"continue_tx: called with packet in buffer!\n");      return;    }  if (out->segnum>=out->numsegs)    {      BUGMSG(D_NORMAL,"continue_tx: building segment %d of %d!\n",	     out->segnum+1,out->numsegs);    }  if (!out->segnum)	/* first packet */    out->hdr->split_flag=((out->numsegs-2)<<1)+1;  else    out->hdr->split_flag=out->segnum<<1;  out->seglen=maxsegsize;  if (out->seglen>out->dataleft) out->seglen=out->dataleft;  BUGMSG(D_TX,"building packet #%d (%d bytes) of %d (%d total), splitflag=%d\n",	 out->segnum+1,out->seglen,out->numsegs,	 out->length,out->hdr->split_flag);  (*lp->prepare_tx)(dev,((char *)out->hdr)+EXTRA_CLIENTDATA,		    sizeof(struct ClientData)-EXTRA_CLIENTDATA,		    out->data,out->seglen,out->hdr->daddr,1,0);  out->dataleft-=out->seglen;  out->data+=out->seglen;  out->segnum++;}/* Actually start transmitting a packet that was placed in the card's * buffer by arcnetAS_prepare_tx.  Returns 1 if a Tx is really started. * * This should probably always be called with the INTMASK register set to 0, * so go_tx is not called recursively. * * The enable_irq flag determines whether to actually write INTMASK value * to the card; TXFREEflag is always OR'ed into the memory variable either * way. */int arcnet_go_tx(struct device *dev,int enable_irq){	struct arcnet_local *lp=(struct arcnet_local *)dev->priv;	BUGMSG(D_DURING,"go_tx: status=%Xh, intmask=%Xh, txready=%d, sending=%d\n",		ARCSTATUS,lp->intmask,lp->txready,lp->sending);	if (lp->sending || !lp->txready)	{		if (enable_irq && lp->sending)		{			lp->intmask |= TXFREEflag;			SETMASK;		}		return 0;	}	/* start sending */	ACOMMAND(TXcmd|(lp->txready<<3));	lp->stats.tx_packets++;	lp->txready=0;	lp->sending++;	lp->lasttrans_dest=lp->lastload_dest;	lp->lastload_dest=0;	lp->intmask |= TXFREEflag;	if (enable_irq)	SETMASK;	return 1;}/**************************************************************************** *                                                                          * * Interrupt handler                                                        * *                                                                          * ****************************************************************************//* The typical workload of the driver:  Handle the network interface * interrupts. Establish which device needs attention, and call the correct * chipset interrupt handler. */voidarcnet_interrupt(int irq,void *dev_id,struct pt_regs *regs){	struct device *dev = dev_id;	struct arcnet_local *lp;	if (dev==NULL)	  {	    BUGMSG(D_DURING, "arcnet: irq %d for unknown device.\n", irq);	    return;	  }	BUGMSG(D_DURING,"in arcnet_interrupt\n");	lp=(struct arcnet_local *)dev->priv;	if (!lp)	  {	    BUGMSG(D_DURING, "arcnet: irq ignored.\n");	    return;	  }	/* RESET flag was enabled - if !dev->start, we must clear it right	 * away (but nothing else) since inthandler() is never called.	 */	if (!dev->start)	  {	    if (ARCSTATUS & RESETflag)	      ACOMMAND(CFLAGScmd|RESETclear);	    return;	  }	if (test_and_set_bit(0, (int *)&dev->interrupt))	  {	    BUGMSG(D_NORMAL,"DRIVER PROBLEM!  Nested arcnet interrupts!\n");	    return;	/* don't even try. */	  }#ifdef CONFIG_ARCNET_1051	if (lp->sdev)	  lp->sdev->interrupt=1;#endif#ifdef CONFIG_ARCNET_ETH	if (lp->edev)	  lp->edev->interrupt=1;#endif	/* Call the "real" interrupt handler. */	(*lp->inthandler)(dev);#ifdef CONFIG_ARCNET_ETH	if (lp->edev)	  lp->edev->interrupt=0;#endif#ifdef CONFIG_ARCNET_1051	if (lp->sdev)	  lp->sdev->interrupt=0;#endif	if (!test_and_clear_bit(0, (int *)&dev->interrupt))	  BUGMSG(D_NORMAL, "Someone cleared our dev->interrupt flag!\n");}void arcnet_tx_done(struct device *dev, struct arcnet_local *lp){  if (dev->tbusy)    {#ifdef CONFIG_ARCNET_ETH      lp->edev->tbusy=0;#endif#ifdef CONFIG_ARCNET_1051      lp->sdev->tbusy=0;#endif      if (!test_and_clear_bit(0, (int *)&dev->tbusy))	BUGMSG(D_NORMAL, "In arcnet_tx_done: Someone cleared our dev->tbusy"	       " flag!\n");      mark_bh(NET_BH);    }}/**************************************************************************** *                                                                          * * Receiver routines                                                        * *                                                                          * ****************************************************************************//* * This is a generic packet receiver that calls arcnet??_rx depending on the * protocol ID found. */void arcnet_rx(struct arcnet_local *lp, u_char *arcsoft, short length, int saddr, int daddr){  struct device *dev=lp->adev;  BUGMSG(D_DURING,"received packet from %02Xh to %02Xh (%d bytes)\n",	 saddr,daddr,length);  /* call the right receiver for the protocol */  switch (arcsoft[0])    {    case ARC_P_IP:    case ARC_P_ARP:    case ARC_P_RARP:    case ARC_P_IPX:    case ARC_P_NOVELL_EC:      arcnetA_rx(lp->adev,arcsoft,length,saddr,daddr);      break;#ifdef CONFIG_ARCNET_ETH    case ARC_P_ETHER:      arcnetE_rx(lp->edev,arcsoft,length,saddr,daddr);      break;#endif#ifdef CONFIG_ARCNET_1051    case ARC_P_IP_RFC1051:    case ARC_P_ARP_RFC1051:      arcnetS_rx(lp->sdev,arcsoft,length,saddr,daddr);

⌨️ 快捷键说明

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