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

📄 wavelan.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Read bytes from the Frequency EEPROM (frequency select cards). */static voidfee_read(u_long		ioaddr,	/* I/O port of the card */	 u_short	o,	/* destination offset */	 u_short *	b,	/* data buffer */	 int		n)	/* number of registers */{  b += n;		/* Position at the end of the area */  /* Write the address */  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);  /* Loop on all buffer */  while(n-- > 0)    {      /* Write the read command */      mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ);      /* Wait until EEPROM is ready (should be quick). */      fee_wait(ioaddr, 10, 100);      /* Read the value. */      *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) |	      mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));    }}#ifdef WIRELESS_EXT	/* if the wireless extension exists in the kernel *//*------------------------------------------------------------------*//* * Write bytes from the Frequency EEPROM (frequency select cards). * This is a bit complicated, because the frequency EEPROM has to * be unprotected and the write enabled. * Jean II */static voidfee_write(u_long	ioaddr,	/* I/O port of the card */	  u_short	o,	/* destination offset */	  u_short *	b,	/* data buffer */	  int		n)	/* number of registers */{  b += n;		/* Position at the end of the area. */#ifdef EEPROM_IS_PROTECTED	/* disabled */#ifdef DOESNT_SEEM_TO_WORK	/* disabled */  /* Ask to read the protected register */  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);  fee_wait(ioaddr, 10, 100);  /* Read the protected register. */  printk("Protected 2:  %02X-%02X\n",	 mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)),	 mmc_in(ioaddr, mmroff(0, mmr_fee_data_l)));#endif	/* DOESNT_SEEM_TO_WORK */  /* Enable protected register. */  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN);  fee_wait(ioaddr, 10, 100);  /* Unprotect area. */  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n);  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);#ifdef DOESNT_SEEM_TO_WORK	/* disabled */  /* or use: */  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR);#endif	/* DOESNT_SEEM_TO_WORK */  fee_wait(ioaddr, 10, 100);#endif	/* EEPROM_IS_PROTECTED */  /* Write enable. */  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN);  fee_wait(ioaddr, 10, 100);  /* Write the EEPROM address. */  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1);  /* Loop on all buffer */  while(n-- > 0)    {      /* Write the value. */      mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8);      mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF);      /* Write the write command. */      mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE);      /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */      mdelay(10);      fee_wait(ioaddr, 10, 100);    }  /* Write disable. */  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS);  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS);  fee_wait(ioaddr, 10, 100);#ifdef EEPROM_IS_PROTECTED	/* disabled */  /* Reprotect EEPROM. */  mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00);  mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);  fee_wait(ioaddr, 10, 100);#endif	/* EEPROM_IS_PROTECTED */}#endif	/* WIRELESS_EXT *//************************ I82586 SUBROUTINES *************************//* * Useful subroutines to manage the Ethernet controller *//*------------------------------------------------------------------*//* * Read bytes from the on-board RAM. * Why does inlining this function make it fail? */static /*inline*/ voidobram_read(u_long	ioaddr,	   u_short	o,	   u_char *	b,	   int		n){  outw(o, PIOR1(ioaddr));  insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);}/*------------------------------------------------------------------*//* * Write bytes to the on-board RAM. */static inline voidobram_write(u_long	ioaddr,	    u_short	o,	    u_char *	b,	    int		n){  outw(o, PIOR1(ioaddr));  outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1);}/*------------------------------------------------------------------*//* * Acknowledge the reading of the status issued by the i82586. */static voidwv_ack(device *		dev){  net_local *	lp = (net_local *)dev->priv;  u_long	ioaddr = dev->base_addr;  u_short	scb_cs;  int		i;  obram_read(ioaddr, scboff(OFFSET_SCB, scb_status),	     (unsigned char *) &scb_cs, sizeof(scb_cs));  scb_cs &= SCB_ST_INT;  if(scb_cs == 0)    return;  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),	      (unsigned char *) &scb_cs, sizeof(scb_cs));  set_chan_attn(ioaddr, lp->hacr);  for(i = 1000; i > 0; i--)    {      obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), (unsigned char *)&scb_cs, sizeof(scb_cs));      if(scb_cs == 0)	break;      udelay(10);    }  udelay(100);#ifdef DEBUG_CONFIG_ERROR  if(i <= 0)    printk(KERN_INFO "%s: wv_ack(): board not accepting command.\n",	   dev->name);#endif}/*------------------------------------------------------------------*//* * Set channel attention bit and busy wait until command has * completed, then acknowledge completion of the command. */static inline intwv_synchronous_cmd(device *	dev,		   const char *	str){  net_local *	lp = (net_local *)dev->priv;  u_long	ioaddr = dev->base_addr;  u_short	scb_cmd;  ach_t		cb;  int		i;  scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO;  obram_write(ioaddr, scboff(OFFSET_SCB, scb_command),	      (unsigned char *) &scb_cmd, sizeof(scb_cmd));  set_chan_attn(ioaddr, lp->hacr);  for (i = 1000; i > 0; i--)    {      obram_read(ioaddr, OFFSET_CU, (unsigned char *)&cb, sizeof(cb));      if (cb.ac_status & AC_SFLD_C)	break;      udelay(10);    }  udelay(100);  if(i <= 0 || !(cb.ac_status & AC_SFLD_OK))    {#ifdef DEBUG_CONFIG_ERROR      printk(KERN_INFO "%s: %s failed; status = 0x%x\n",	     dev->name, str, cb.ac_status);#endif#ifdef DEBUG_I82586_SHOW      wv_scb_show(ioaddr);#endif      return -1;    }  /* Ack the status */  wv_ack(dev);  return 0;}/*------------------------------------------------------------------*//* * Configuration commands completion interrupt. * Check if done, and if OK. */static inline intwv_config_complete(device *	dev,		   u_long	ioaddr,		   net_local *	lp){  unsigned short	mcs_addr;  unsigned short	status;  int			ret;#ifdef DEBUG_INTERRUPT_TRACE  printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name);#endif  mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t)    + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t);  /* Read the status of the last command (set mc list). */  obram_read(ioaddr, acoff(mcs_addr, ac_status), (unsigned char *)&status, sizeof(status));  /* If not completed -> exit */  if((status & AC_SFLD_C) == 0)    ret = 0;		/* Not ready to be scrapped */  else    {#ifdef DEBUG_CONFIG_ERROR      unsigned short	cfg_addr;      unsigned short	ias_addr;      /* Check mc_config command */      if((status & AC_SFLD_OK) != 0)	printk(KERN_INFO "wv_config_complete(): set_multicast_address failed; status = 0x%x\n",	       dev->name, str, status);      /* check ia-config command */      ias_addr = mcs_addr - sizeof(ac_ias_t);      obram_read(ioaddr, acoff(ias_addr, ac_status), (unsigned char *)&status, sizeof(status));      if((status & AC_SFLD_OK) != 0)	printk(KERN_INFO "wv_config_complete(): set_MAC_address; status = 0x%x\n",	       dev->name, str, status);      /* Check config command. */      cfg_addr = ias_addr - sizeof(ac_cfg_t);      obram_read(ioaddr, acoff(cfg_addr, ac_status), (unsigned char *)&status, sizeof(status));      if((status & AC_SFLD_OK) != 0)	printk(KERN_INFO "wv_config_complete(): configure; status = 0x%x\n",	       dev->name, str, status);#endif	/* DEBUG_CONFIG_ERROR */      ret = 1;		/* Ready to be scrapped */    }#ifdef DEBUG_INTERRUPT_TRACE  printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name, ret);#endif  return ret;}/*------------------------------------------------------------------*//* * Command completion interrupt. * Reclaim as many freed tx buffers as we can. */static intwv_complete(device *	dev,	    u_long	ioaddr,	    net_local *	lp){  int	nreaped = 0;#ifdef DEBUG_INTERRUPT_TRACE  printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name);#endif  /* Loop on all the transmit buffers */  while(lp->tx_first_in_use != I82586NULL)    {      unsigned short	tx_status;      /* Read the first transmit buffer */      obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), (unsigned char *)&tx_status, sizeof(tx_status));      /* Hack for reconfiguration */      if(tx_status == 0xFFFF)	if(!wv_config_complete(dev, ioaddr, lp))	  break;	/* Not completed */      /* If not completed -> exit */      if((tx_status & AC_SFLD_C) == 0)	break;      /* We now remove this buffer */      nreaped++;      --lp->tx_n_in_use;/*if (lp->tx_n_in_use > 0)	printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]);*/      /* Was it the last one? */      if(lp->tx_n_in_use <= 0)	lp->tx_first_in_use = I82586NULL;      else	{	  /* Next one in the chain */	  lp->tx_first_in_use += TXBLOCKZ;	  if(lp->tx_first_in_use >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ)	    lp->tx_first_in_use -= NTXBLOCKS * TXBLOCKZ;	}      /* Hack for reconfiguration */      if(tx_status == 0xFFFF)	continue;      /* Now, check status of the finished command */      if(tx_status & AC_SFLD_OK)	{	  int	ncollisions;	  lp->stats.tx_packets++;	  ncollisions = tx_status & AC_SFLD_MAXCOL;	  lp->stats.collisions += ncollisions;#ifdef DEBUG_INTERRUPT_INFO	  if(ncollisions > 0)	    printk(KERN_DEBUG "%s: wv_complete(): tx completed after %d collisions.\n",		   dev->name, ncollisions);#endif	}      else	{	  lp->stats.tx_errors++;#ifndef IGNORE_NORMAL_XMIT_ERRS	  if(tx_status & AC_SFLD_S10)	    {	      lp->stats.tx_carrier_errors++;#ifdef DEBUG_INTERRUPT_ERROR	      printk(KERN_INFO "%s: wv_complete(): tx error: no CS.\n",		     dev->name);#endif	    }#endif	/* IGNORE_NORMAL_XMIT_ERRS */	  if(tx_status & AC_SFLD_S9)	    {	      lp->stats.tx_carrier_errors++;#ifdef DEBUG_INTERRUPT_ERROR	      printk(KERN_INFO "%s: wv_complete(): tx error: lost CTS.\n",		     dev->name);#endif	    }	  if(tx_status & AC_SFLD_S8)	    {	      lp->stats.tx_fifo_errors++;#ifdef DEBUG_INTERRUPT_ERROR	      printk(KERN_INFO "%s: wv_complete(): tx error: slow DMA.\n",		     dev->name);#endif	    }#ifndef IGNORE_NORMAL_XMIT_ERRS	  if(tx_status & AC_SFLD_S6)	    {	      lp->stats.tx_heartbeat_errors++;#ifdef DEBUG_INTERRUPT_ERROR	      printk(KERN_INFO "%s: wv_complete(): tx error: heart beat.\n",		     dev->name);#endif	    }	  if(tx_status & AC_SFLD_S5)	    {	      lp->stats.tx_aborted_errors++;#ifdef DEBUG_INTERRUPT_ERROR	      printk(KERN_INFO "%s: wv_complete(): tx error: too many collisions.\n",		     dev->name);#endif	    }#endif	/* IGNORE_NORMAL_XMIT_ERRS */	}#ifdef DEBUG_INTERRUPT_INFO      printk(KERN_DEBUG "%s: wv_complete(): tx completed, tx_status 0x%04x\n",	     dev->name, tx_status);#endif    }#ifdef DEBUG_INTERRUPT_INFO  if(nreaped > 1)    printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n", dev->name, nreaped);#endif  /*   * Inform upper layers.   */  if(lp->tx_n_in_use < NTXBLOCKS - 1)    {      dev->tbusy = 0;      mark_bh(NET_BH);    }#ifdef DEBUG_INTERRUPT_TRACE  printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name);#endif  return nreaped;}/*------------------------------------------------------------------*//* * Reconfigure the i82586, or at least ask for it. * Because wv_82586_config uses a transmission buffer, we must do it * when we are sure that there is one left, so we do it now * or in wavelan_packet_xmit() (I can't find any better place, * wavelan_interrupt is not an option), so you may experience * delays sometimes. */static inline voidwv_82586_reconfig(device *	dev){  net_local *	lp = (net_local *)dev->priv;  /* Check if we can do it now ! */  if(!(dev->start) || (test_and_set_bit(0, (void *)&dev->tbusy) != 0))    {      lp->reconfig_82586 = 1;#ifdef DEBUG_CONFIG_INFO      printk(KERN_DEBUG "%s: wv_82586_reconfig(): delayed (busy = %ld, start = %d)\n",	     dev->name, dev->tbusy, dev->start);#endif    }  else    wv_82586_config(dev);}/********************* DEBUG & INFO SUBROUTINES *********************/

⌨️ 快捷键说明

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