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

📄 wavelan.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
	  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 doc says : wait at least 10 ms for EEBUSY = 0 */      udelay(10000);      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 *************************//* * Usefull subroutines to manage the Ethernet controler *//*------------------------------------------------------------------*//* * Read bytes from the on-board RAM. * Why 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 the command completion. */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 use 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 * some delay sometime... */static inline voidwv_82586_reconfig(device *	dev){  net_local *	lp = (net_local *)dev->priv;  /* Check if we can do it now ! */  if(!(dev->start) || (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 *********************//* * This routines are used in the code to show debug informations. * Most of the time, it dump the content of hardware structures... */#ifdef DEBUG_PSA_SHOW/*------------------------------------------------------------------*//* * Print the formatted contents of the Parameter Storage Area. */static voidwv_psa_show(psa_t *	p){  printk(KERN_DEBUG "##### WaveLAN psa contents: #####\n");  printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n",	 p->psa_io_base_addr_1,	 p->psa_io_base_addr_2,	 p->psa_io_base_addr_3,	 p->psa_io_base_addr_4);  printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n",	 p->psa_rem_boot_addr_1,	 p->psa_rem_boot_addr_2,	 p->psa_rem_boot_addr_3);  printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params);  printk("psa_int_req_no: %d\n", p->psa_int_req_no);#ifdef DEBUG_SHOW_UNUSED  printk(KERN_DEBUG "psa_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X\n",	 p->psa_unused0[0],	 p->psa_unused0[1],	 p->psa_unused0[2],	 p->psa_unused0[3],	 p->psa_unused0[4],	 p->psa_unused0[5],	 p->psa_unused0[6]);#endif	/* DEBUG_SHOW_UNUSED */  printk(KERN_DEBUG "psa_univ_mac_addr[]: %02x:%02x:%02x:%02x:%02x:%02x\n",	 p->psa_univ_mac_addr[0],	 p->psa_univ_mac_addr[1],	 p->psa_univ_mac_addr[2],	 p->psa_univ_mac_addr[3],

⌨️ 快捷键说明

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