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

📄 cs89x0.c

📁 基于linux嵌入式系统,芯片为cs8900的以太网驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));  /* Receive only error free packets addressed to this card */  lp->rx_mode = 0;//RX_OK_ACCEPT | RX_IA_ACCEPT;  lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;	  writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);  writereg(dev, PP_RxCFG, lp->curr_rx_cfg);  writereg(dev, PP_TxCFG,	   TX_LOST_CRS_ENBL |	   TX_SQE_ERROR_ENBL |	   TX_OK_ENBL |	   TX_LATE_COL_ENBL |	   TX_JBR_ENBL |	   TX_ANY_COL_ENBL |	   TX_16_COL_ENBL);  writereg(dev, PP_BufCFG,	   READY_FOR_TX_ENBL |	   RX_MISS_COUNT_OVRFLOW_ENBL |	   TX_COL_COUNT_OVRFLOW_ENBL |	   TX_UNDERRUN_ENBL);  /* Turn on both receive and transmit operations */  writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) |	   SERIAL_RX_ON |	   SERIAL_TX_ON);  /* now that we've got our act together, enable everything */  writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | IO_CHANNEL_READY_ON);  writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);  /* enable IRQ  */  enable_irq(dev->irq);	  MOD_INC_USE_COUNT;  netif_start_queue(dev);  return 0;}static void net_timeout(struct net_device *dev){  /* If we get here, some higher level has decided we are broken.     There should really be a "kick me" function call instead. */  if (net_debug > 0)    printk("%s: transmit timed out, %s?\n", dev->name,	   tx_done(dev) ? "IRQ conflict ?" : "network cable problem");  /* Try to restart the adaptor. */  netif_wake_queue(dev);}static int net_send_packet(struct sk_buff *skb, struct net_device *dev){  struct net_local *lp = (struct net_local *)dev->priv;  if (net_debug > 4)    {      printk("%s: sent %d byte packet of type %x\n",	     dev->name, skb->len,	     (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);    }        			    /* keep the upload from being interrupted, since we     ask the chip to start transmitting before the     whole packet has been completely uploaded. */  spin_lock_irq(&lp->lock);  netif_stop_queue(dev);  /* initiate a transmit sequence */  writereg(dev, PP_TxCMD, lp->send_cmd);  writereg(dev, PP_TxLength, skb->len);  /* Test to see if the chip has allocated memory for the packet */  if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0)    {      /*       * Gasp!  It hasn't.  But that shouldn't happen since       * we're waiting for TxOk, so return 1 and requeue this packet.       */		      spin_unlock_irq(&lp->lock);      if (net_debug)	printk("cs89x0: Tx buffer not free!\n");			      return 1;    }  /* Write the contents of the packet */  writeblock(dev, skb->data, skb->len);		  spin_unlock_irq(&lp->lock);  dev->trans_start = jiffies;  dev_kfree_skb(skb);  /*   * We DO NOT call netif_wake_queue() here.   * We also DO NOT call netif_start_queue().   *   * Either of these would cause another bottom half run through   * net_send_packet() before this packet has fully gone out.  That causes   * us to hit the "Gasp!" above and the send is rescheduled.  it runs like   * a dog.  We just return and wait for the Tx completion interrupt handler   * to restart the netdevice layer   */  return 0;}/* The typical workload of the driver:   Handle the network interface interrupts. */   static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs){  struct net_device *dev = dev_id;  struct net_local *lp;  int ioaddr, status;  if((_reg_PORTD_ISR & 0x80)==0)return;         ioaddr = dev->base_addr;  lp = (struct net_local *)dev->priv;	  Clear_interrupt();    	  while ((status = readword(dev, ISQ_PORT)))    {      if (net_debug > 4)	printk("%s: event=%04x\n", dev->name, status);      switch(status & ISQ_EVENT_MASK)	{	case ISQ_RECEIVER_EVENT:		  net_rx(dev);	  break;				case ISQ_TRANSMITTER_EVENT:	  lp->stats.tx_packets++;	  netif_wake_queue(dev);	/* Inform upper layers. */	  if ((status & (	TX_OK |				TX_LOST_CRS |				TX_SQE_ERROR |				TX_LATE_COL |				TX_16_COL)) != TX_OK)	    {	      if ((status & TX_OK) == 0) lp->stats.tx_errors++;	      if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;	      if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;	      if (status & TX_LATE_COL) lp->stats.tx_window_errors++;	      if (status & TX_16_COL) lp->stats.tx_aborted_errors++;	    }	  break;				case ISQ_BUFFER_EVENT:	  if (status & READY_FOR_TX)	    {	      /* we tried to transmit a packet earlier, but inexplicably ran out of buffers.	       * That shouldn't happen since we only ever load one packet.	       *	Shrug. Do the right thing anyway.	       */	      netif_wake_queue(dev);	/* Inform upper layers. */	    }	  if (status & TX_UNDERRUN)	    {	      if (net_debug > 0)		printk("%s: transmit underrun\n", dev->name);	      lp->send_underrun++;	      if (lp->send_underrun == 3)		lp->send_cmd = TX_AFTER_381;	      else if (lp->send_underrun == 6)		lp->send_cmd = TX_AFTER_ALL;	      /*	       * transmit cycle is done, although	frame wasn't transmitted - this	       * avoids having to wait for the upper	layers to timeout on us,	       * in the event of a tx underrun	       */	      netif_wake_queue(dev);	/* Inform upper layers. */	    }	  break;				case ISQ_RX_MISS_EVENT:	  lp->stats.rx_missed_errors += (status >>6);	  break;				case ISQ_TX_COL_EVENT:	  lp->stats.collisions += (status >>6);	  break;	default:	  if (net_debug > 3)	    printk("%s: event=%04x\n", dev->name, status);	}    }	}static voidcount_rx_errors(int status, struct net_local *lp){  lp->stats.rx_errors++;  if (status & RX_RUNT) lp->stats.rx_length_errors++;  if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++;  if (status & RX_CRC_ERROR)    if (!(status & (RX_EXTRA_DATA|RX_RUNT)))      /* per str 172 */      lp->stats.rx_crc_errors++;  if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++;  return;}static voidnet_rx(struct net_device *dev){  struct net_local *lp = (struct net_local *)dev->priv;  struct sk_buff *skb;  int status = 0, length = 0;   status = readreg(dev, PP_RxStatus);  if ((status & RX_OK) == 0) {    count_rx_errors(status, lp);    return;  }  length = readreg(dev, PP_RxLength);  /* Malloc up new buffer. */  skb = alloc_skb(length+2, GFP_ATOMIC);  skb_reserve(skb, 2);  if (skb == NULL)    {      lp->stats.rx_dropped++;      return;    }  skb->len = length;  skb->dev = dev;  readblock(dev, skb->data, skb->len); if (net_debug > 4)    {      printk("%s: received %d byte packet of type %x\n",	     dev->name, length,	     (skb->data[ETH_ALEN+ETH_ALEN] << 8) | skb->data[ETH_ALEN+ETH_ALEN+1]);    }  skb->protocol=eth_type_trans(skb,dev);  netif_rx(skb);  lp->stats.rx_packets++;  lp->stats.rx_bytes+=skb->len;  return;}/* The inverse routine to net_open(). */static intnet_close(struct net_device *dev){  netif_stop_queue(dev);	  writereg(dev, PP_RxCFG, 0);  writereg(dev, PP_TxCFG, 0);  writereg(dev, PP_BufCFG, 0);  writereg(dev, PP_BusCTL, 0);  free_irq(dev->irq, dev);  /* Update the statistics here. */  MOD_DEC_USE_COUNT;  return 0;}/* Get the current statistics.	This may be called with the card open or   closed. */static struct net_device_stats *net_get_stats(struct net_device *dev){  struct net_local *lp = (struct net_local *)dev->priv;  unsigned long flags;  spin_lock_irqsave(&lp->lock, flags);  /* Update the statistics from the device registers. */  lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);  lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);  spin_unlock_irqrestore(&lp->lock, flags);  return &lp->stats;}static void set_multicast_list(struct net_device *dev){  struct net_local *lp = (struct net_local *)dev->priv;  unsigned long flags;  spin_lock_irqsave(&lp->lock, flags);  if(dev->flags&IFF_PROMISC)    {      lp->rx_mode = RX_ALL_ACCEPT;    }  else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)    {      /* The multicast-accept list is initialized to accept-all, and we	 rely on higher-level filtering for now. */      lp->rx_mode = RX_MULTCAST_ACCEPT;    }   else    lp->rx_mode = 0;  writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);  /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */  writereg(dev, PP_RxCFG, lp->curr_rx_cfg |	   (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));  spin_unlock_irqrestore(&lp->lock, flags);}static int set_mac_address(struct net_device *dev, void *addr){  int i;  if (netif_running(dev))    return -EBUSY;  if (net_debug)    {      printk("%s: Setting MAC address to ", dev->name);      for (i = 0; i < 6; i++)	printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);      printk(".\n");    }  /* set the Ethernet address */  for (i=0; i < ETH_ALEN/2; i++)    writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));  return 0;}#ifdef MODULE//static char namespace[16] = "";static struct net_device dev_cs89x0 = {  "eth%d",  0, 0, 0, 0,  0, 0,  0, 0, 0, NULL, NULL };/* * Support the 'debug' module parm even if we're compiled for non-debug to  * avoid breaking someone's startup scripts  */static int io=0xf5000300;static int irq;static int debug=0;static char * MAC=0;//static int duplex=-1;//static int use_dma = 0;			/* These generate unused var warnings if ALLOW_DMA = 0 *///static int dma=0;//static int dmasize=16;			/* or 64 */MODULE_PARM(io, "i");MODULE_PARM(irq, "i");MODULE_PARM(debug, "i");MODULE_PARM(MAC, "s");MODULE_PARM(duplex, "i");MODULE_PARM(dma , "i");MODULE_PARM(dmasize , "i");MODULE_PARM(use_dma , "i");/*MODULE_AUTHORcified on command-line    * CS8920 defaults to autoneg if not specified on command-line    * Use reset defaults for other config parameters* Assumptions:  * media type specified is supported (circuitry is present)  * if memory address is > 1MB, then required mem decode hw is present  * if 10B-2, then agent other than driver will enable DC/DC converter    (hw or software util)*/void cs8900MX1Init(void){  volatile U16 tmp;  // assume ext UART 20MHz max access time with no wait states  // set up wait state of CS4  //_reg_CS4_CTRLL = 0x30301501;	// Data port sized is D[7:0], EBC set	  //_reg_CS4_CTRLH = 0xf00;	// if HCLK(BCLK) is 96MHz, add 5 wait states  // set up the GPIO muxing to use Chip Select 4  //_reg_PTA_GIUS &= 0xFF3FFFFF;  //_reg_PTA_GPR  &= 0xFF3FFFFF;	  //   *(volatile P_U32)(0xf0220000) = 0xf00;     // *(volatile P_U32)(0xf0220004) = 0x30301d01;   *(volatile P_U32)(0xf0220020)  = 0x00000F00;  *(volatile P_U32)(0xf0220024)  = 0x30301501;  *(volatile P_U32)(0xf021C320) |= 0x80;  *(volatile P_U32)(0xf021C338) &= 0xFFFFFFBF;  tmp = *(P_U16)(0xf500000C);}unsigned char MACconvert(char p) {  if(p>='0'&&p<='9')    return (unsigned char)(p-0x30);  else if(p>='a'&&p<='f')    return (unsigned char)(p-0x57);  else if(p>='A'&&p<='F')    return (unsigned char)(p-0x37);	  else     return 0xff;}intinit_module(void){  struct net_local *lp;  char MACaddress[18];  int len,i,j=0;  unsigned char add;  unsigned char Addr[6];    irq = 62; 	  if(MAC==0)    {printk("Useage: insmod cs89x0.o MAC=xx:xx:xx:xx:xx:xx\n");return -1;}	  len = strlen(MAC);  if(len!=17)    {printk("Error! MAC is 48bit address.\n");return -1;}				  strcpy(MACaddress,MAC);  MACaddress[17]=':';	  for(i=0;i<18;i++)    {      add=MACconvert(MACaddress[i]);      if(add==0xff)goto MACerror;		      Addr[j]=add*16;      i++;      add=MACconvert(MACaddress[i]);		      if(add==0xff)goto MACerror;      Addr[j]+=add;      i++;      if(MACaddress[i]!=':')goto MACerror;      j++;    }	  memcpy(MacAddr,Addr,6);			  cs8900MX1Init();#if DEBUGGING  net_debug = debug;#endif	  dev_cs89x0.irq = irq;  dev_cs89x0.base_addr = io;  dev_cs89x0.init = cs89x0_probe;  dev_cs89x0.priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);  if (dev_cs89x0.priv == 0)    {      printk(KERN_ERR "cs89x0.c: Out of memory.\n");      return -ENOMEM;    }  memset(dev_cs89x0.priv, 0, sizeof(struct net_local));  lp = (struct net_local *)dev_cs89x0.priv;	  spin_lock_init(&lp->lock);  if (register_netdev(&dev_cs89x0) != 0) {    printk(KERN_ERR "cs89x0.c: No chip found at 0x%x\n", io);    return -ENXIO;  }  return 0; MACerror:  printk("MAC address error!\n");  return -1;}voidcleanup_module(void){  writeword(&dev_cs89x0, ADD_PORT, PP_ChipID);  if (dev_cs89x0.priv != NULL) {    /* Free up the private structure, or leak memory :-)  */    unregister_netdev(&dev_cs89x0);    kfree(dev_cs89x0.priv);    dev_cs89x0.priv = NULL;	/* gets re-allocated by cs89x0_probe1 */    /* If we don't do this, we can't re-insmod it later. */    release_region(dev_cs89x0.base_addr, NETCARD_IO_EXTENT);  }}#endif /* MODULE */

⌨️ 快捷键说明

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