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

📄 com90io.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
static voidarc90io_inthandler(struct device *dev){  struct arcnet_local *lp=(struct arcnet_local *)dev->priv;  int ioaddr=dev->base_addr, status, boguscount = 3, didsomething;  AINTMASK(0);  BUGMSG(D_DURING,"in arc90io_inthandler (status=%Xh, intmask=%Xh)\n",	 ARCSTATUS,lp->intmask);  do    {      status = ARCSTATUS;      didsomething=0;      /* RESET flag was enabled - card is resetting and if RX       * is disabled, it's NOT because we just got a packet.       */      if (status & RESETflag)	{	  BUGMSG(D_NORMAL,"spurious reset (status=%Xh)\n",		 status);	  arc90io_reset(dev,0);	  /* all other flag values are just garbage */	  break;	}      /* RX is inhibited - we must have received something. */      if (status & lp->intmask & NORXflag)	{	  int recbuf=lp->recbuf=!lp->recbuf;	  int oldaddr=0;	  BUGMSG(D_DURING,"receive irq (status=%Xh)\n",		 status);	  /* enable receive of our next packet */	  EnableReceiver();	  if (lp->intx)	    oldaddr=(inb(_ADDR_HI)<<8) | inb(_ADDR_LO);	  /* Got a packet. */	  arc90io_rx(dev,!recbuf);	  if (lp->intx)	    {	      outb( (oldaddr >> 8),  _ADDR_HI);	      outb( oldaddr & 0xff, _ADDR_LO);	    }	  didsomething++;	}      /* it can only be an xmit-done irq if we're xmitting :) */      /*if (status&TXFREEflag && !lp->in_txhandler && lp->sending)*/      if (status & lp->intmask & TXFREEflag)	{	  struct Outgoing *out=&(lp->outgoing);	  int was_sending=lp->sending;	  lp->intmask &= ~TXFREEflag;	  lp->in_txhandler++;	  if (was_sending) lp->sending--;	  BUGMSG(D_DURING,"TX IRQ (stat=%Xh, numsegs=%d, segnum=%d, skb=%ph)\n",		 status,out->numsegs,out->segnum,out->skb);	  if (was_sending && !(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);		}	    }	  /* send packet if there is one */	  arcnet_go_tx(dev,0);	  didsomething++;	  if (lp->intx)	    {	      BUGMSG(D_DURING,"TXDONE while intx! (status=%Xh, intx=%d)\n",		     ARCSTATUS,lp->intx);	      lp->in_txhandler--;	      continue;	    }	  if (!lp->outgoing.skb)	    {	      BUGMSG(D_DURING,"TX IRQ done: no split to continue.\n");	      /* inform upper layers */	      if (!lp->txready) arcnet_tx_done(dev, lp);	      lp->in_txhandler--;	      continue;	    }	  /* if more than one segment, and not all segments	   * are done, then continue xmit.	   */	  if (out->segnum<out->numsegs)	    arcnetA_continue_tx(dev);	  arcnet_go_tx(dev,0);	  /* if segnum==numsegs, the transmission is finished;	   * free the skb.	   */	  if (out->segnum>=out->numsegs)	    {	      /* transmit completed */	      out->segnum++;	      if (out->skb)		{		  lp->stats.tx_bytes += out->skb->len;		  dev_kfree_skb(out->skb);		}	      out->skb=NULL;	      /* inform upper layers */	      if (!lp->txready) arcnet_tx_done(dev, lp);	    }	  didsomething++;	  lp->in_txhandler--;	}      else if (lp->txready && !lp->sending && !lp->intx)	{	  BUGMSG(D_NORMAL,"recovery from silent TX (status=%Xh)\n",		 status);	  arcnet_go_tx(dev,0);	  didsomething++;	}#ifdef DETECT_RECONFIGS      if (status & (lp->intmask) & RECONflag)	{	  ACOMMAND(CFLAGScmd|CONFIGclear);	  lp->stats.tx_carrier_errors++;#ifdef SHOW_RECONFIGS	  BUGMSG(D_NORMAL,"Network reconfiguration detected"		 " (status=%Xh, config=%X)\n",		 status,lp->config);#endif /* SHOW_RECONFIGS */#ifdef RECON_THRESHOLD	  /* 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+ sec	       *   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");#endif	}#endif /* DETECT_RECONFIGS */    } while (--boguscount && didsomething);  BUGMSG(D_DURING,"net_interrupt complete (status=%Xh, count=%d)\n",	 ARCSTATUS,boguscount);  BUGMSG(D_DURING,"\n");  SETMASK;	/* put back interrupt mask */}/* A packet has arrived; grab it from the buffers and pass it to the generic * arcnet_rx routing to deal with it. */static voidarc90io_rx(struct device *dev,int recbuf){  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;  int ioaddr=dev->base_addr;  union ArcPacket packetbuf;  union ArcPacket *arcpacket=&packetbuf;  u_char *arcsoft;  short length,offset;  u_char daddr,saddr;  lp->stats.rx_packets++;  get_whole_buffer(dev,recbuf*512,4,(char *)arcpacket);  saddr=arcpacket->hardheader.source;  /* if source is 0, it's a "used" packet! */  if (saddr==0)    {      BUGMSG(D_NORMAL,"discarding old packet. (status=%Xh)\n",	     ARCSTATUS);      lp->stats.rx_errors++;      return;    }  /* Set source address to zero to mark it as old */  put_buffer_byte(dev,recbuf*512,0);  arcpacket->hardheader.source=0;  daddr=arcpacket->hardheader.destination;  if (arcpacket->hardheader.offset1) /* Normal Packet */    {      offset=arcpacket->hardheader.offset1;      arcsoft=&arcpacket->raw[offset];      length=256-offset;    }  else		/* ExtendedPacket or ExceptionPacket */    {      offset=arcpacket->hardheader.offset2;      arcsoft=&arcpacket->raw[offset];      length=512-offset;    }  get_whole_buffer(dev,recbuf*512+offset,length,(char *)arcpacket+offset);  arcnet_rx(lp, arcsoft, length, saddr, daddr);  BUGLVL(D_RX) arcnet_dump_packet(lp->adev,arcpacket->raw,length>240,"rx");}/* Given an skb, copy a packet into the ARCnet buffers for later transmission * by arcnet_go_tx. */static voidarc90io_prepare_tx(struct device *dev,u_char *hdr,int hdrlen,		    char *data,int length,int daddr,int exceptA, int offset){  struct arcnet_local *lp = (struct arcnet_local *)dev->priv;  lp->txbuf=lp->txbuf^1;	/* XOR with 1 to alternate between 2 and 3 */  length+=hdrlen;  BUGMSG(D_TX,"arcnetAS_prep_tx: hdr:%ph, length:%d, data:%ph\n",	 hdr,length,data);  put_buffer_byte(dev, lp->txbuf*512+1, daddr);  /* load packet into shared memory */  if (length<=MTU)	/* Normal (256-byte) Packet */    put_buffer_byte(dev, lp->txbuf*512+2, offset=offset?offset:256-length);  else if (length>=MinTU || offset)	/* Extended (512-byte) Packet */    {      put_buffer_byte(dev, lp->txbuf*512+2, 0);      put_buffer_byte(dev, lp->txbuf*512+3, offset=offset?offset:512-length);    }  else if (exceptA)		/* RFC1201 Exception Packet */    {      put_buffer_byte(dev, lp->txbuf*512+2, 0);      put_buffer_byte(dev, lp->txbuf*512+3, offset=512-length-4);      /* exception-specific stuff - these four bytes       * make the packet long enough to fit in a 512-byte       * frame.       */      put_buffer_byte(dev, lp->txbuf*512+offset,hdr[0]);      put_whole_buffer(dev, lp->txbuf*512+offset+1,3,"\377\377\377");      offset+=4;    }  else				/* "other" Exception packet */    {      /* RFC1051 - set 4 trailing bytes to 0 */      put_whole_buffer(dev,lp->txbuf*512+508,4,"\0\0\0\0");      /* now round up to MinTU */      put_buffer_byte(dev, lp->txbuf*512+2, 0);      put_buffer_byte(dev, lp->txbuf*512+3, offset=512-MinTU);    }  /* copy the packet into ARCnet shmem   *  - the first bytes of ClientData header are skipped   */  put_whole_buffer(dev, 512*lp->txbuf+offset, hdrlen,(u_char *)hdr);  put_whole_buffer(dev, 512*lp->txbuf+offset+hdrlen,length-hdrlen,data);  BUGMSG(D_DURING,"transmitting packet to station %02Xh (%d bytes)\n",	 daddr,length);  lp->lastload_dest=daddr;  lp->txready=lp->txbuf;	/* packet is ready for sending */}/**************************************************************************** *                                                                          * * Kernel Loadable Module Support                                           * *                                                                          * ****************************************************************************/#ifdef MODULEstatic struct device *cards[16]={NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,			  NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};int init_module(void){  struct device *dev=cards[0];  cards[0]=dev=(struct device *)kmalloc(sizeof(struct device), GFP_KERNEL);  if (!dev)    return -ENOMEM;  memset(dev, 0, sizeof(struct device));  dev->name=(char *)kmalloc(9, GFP_KERNEL);  if (!dev->name)    {      kfree(dev);      return -ENOMEM;    }  dev->init=arc90io_probe;  if (device)    strcpy(dev->name,device);  else arcnet_makename(dev->name);  dev->base_addr=io;  dev->irq=irq;  if (dev->irq==2) dev->irq=9;  if (register_netdev(dev) != 0)    return -EIO;  /* Increase use count of arcnet.o */  arcnet_use_count(1);  return 0;}void cleanup_module(void){  struct device *dev=cards[0];  int ioaddr=dev->base_addr;  if (dev->start) (*dev->stop)(dev);  /* Flush TX and disable RX */  if (ioaddr)    {      AINTMASK(0);		/* disable IRQ's */      ACOMMAND(NOTXcmd);	/* stop transmit */      ACOMMAND(NORXcmd);	/* disable receive */      /* Set the thing back to MMAP mode, in case the old	         driver is loaded later */      outb( (inb(_CONFIG)&~IOMAPflag),_CONFIG);    }  if (dev->irq)    {      free_irq(dev->irq,dev);    }  if (dev->base_addr) release_region(dev->base_addr,ARCNET_TOTAL_SIZE);  unregister_netdev(dev);  kfree(dev->priv);  dev->priv = NULL;  /* Decrease use count of arcnet.o */  arcnet_use_count(0);}#else__initfunc(void com90io_setup (char *str, int *ints)){  struct device *dev;  if (arcnet_num_devs == MAX_ARCNET_DEVS)    {      printk("com90xx IO-MAP: Too many ARCnet devices registered (max %d).\n",	     MAX_ARCNET_DEVS);      return;    }  dev=&arcnet_devs[arcnet_num_devs];  if (ints[0] < 1)    {      printk("com90xx IO-MAP: You must give an IO address.\n");      return;    }  dev->init=arc90io_probe;  switch(ints[0])    {    case 3: /* ERROR */      printk("com90xx IO-MAP: Too many arguments.\n");    case 2: /* IRQ */      dev->irq=ints[2];    case 1: /* IO address */      dev->base_addr=ints[1];    }  dev->name = (char *)&arcnet_dev_names[arcnet_num_devs];  if (str)    strncpy(dev->name, str, 9);  arcnet_num_devs++;}#endif /* MODULE */

⌨️ 快捷键说明

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