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

📄 wavelan_cs.c

📁 pcmcia source code
💻 C
📖 第 1 页 / 共 5 页
字号:
{  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(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD);  fee_wait(base, 10, 100);  /* Read the protected register */  printk("Protected 2 : %02X-%02X\n",	 mmc_in(base, mmroff(0, mmr_fee_data_h)),	 mmc_in(base, mmroff(0, mmr_fee_data_l)));#endif	/* DOESNT_SEEM_TO_WORK */  /* Enable protected register */  mmc_out(base, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);  mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN);  fee_wait(base, 10, 100);  /* Unprotect area */  mmc_out(base, mmwoff(0, mmw_fee_addr), o + n);  mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);#ifdef DOESNT_SEEM_TO_WORK	/* disabled */  /* Or use : */  mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR);#endif	/* DOESNT_SEEM_TO_WORK */  fee_wait(base, 10, 100);#endif	/* EEPROM_IS_PROTECTED */  /* Write enable */  mmc_out(base, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN);  mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN);  fee_wait(base, 10, 100);  /* Write the EEprom address */  mmc_out(base, mmwoff(0, mmw_fee_addr), o + n - 1);  /* Loop on all buffer */  while(n-- > 0)    {      /* Write the value */      mmc_out(base, mmwoff(0, mmw_fee_data_h), (*--b) >> 8);      mmc_out(base, mmwoff(0, mmw_fee_data_l), *b & 0xFF);      /* Write the write command */      mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE);      /* Wavelan doc says : wait at least 10 ms for EEBUSY = 0 */      mdelay(10);      fee_wait(base, 10, 100);    }  /* Write disable */  mmc_out(base, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS);  mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS);  fee_wait(base, 10, 100);#ifdef EEPROM_IS_PROTECTED	/* disabled */  /* Reprotect EEprom */  mmc_out(base, mmwoff(0, mmw_fee_addr), 0x00);  mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE);  fee_wait(base, 10, 100);#endif	/* EEPROM_IS_PROTECTED */}#endif	/* WIRELESS_EXT *//******************* WaveLAN Roaming routines... ********************/#ifdef WAVELAN_ROAMING	/* Conditional compile, see wavelan_cs.h */unsigned char WAVELAN_BEACON_ADDRESS[]= {0x09,0x00,0x0e,0x20,0x03,0x00};  void wv_roam_init(struct net_device *dev){  net_local  *lp= (net_local *)dev->priv;  /* Won't enable roaming if the interface is down */  if (!lp->link->open || !netif_running(dev) || netif_queue_stopped(dev))    return;  /* Do not remove this unless you have a good reason */  printk(KERN_NOTICE "%s: Warning, you have enabled roaming on"	 " device %s !\n", dev->name, dev->name);  printk(KERN_NOTICE "Roaming is currently an experimental unsupported feature"	 " of the Wavelan driver.\n");  printk(KERN_NOTICE "It may work, but may also make the driver behave in"	 " erratic ways or crash.\n");  lp->wavepoint_table.head=NULL;           /* Initialise WavePoint table */  lp->wavepoint_table.num_wavepoints=0;  lp->wavepoint_table.locked=0;  lp->curr_point=NULL;                        /* No default WavePoint */  lp->cell_search=0;    lp->cell_timer.data=(long)lp;               /* Start cell expiry timer */  lp->cell_timer.function=wl_cell_expiry;  lp->cell_timer.expires=jiffies+CELL_TIMEOUT;  add_timer(&lp->cell_timer);    wv_nwid_filter(NWID_PROMISC,lp) ;    /* Enter NWID promiscuous mode */  /* to build up a good WavePoint */                                           /* table... */  printk(KERN_DEBUG "WaveLAN: Roaming enabled on device %s\n",dev->name);} void wv_roam_cleanup(struct net_device *dev){  wavepoint_history *ptr,*old_ptr;  net_local *lp= (net_local *)dev->priv;    printk(KERN_DEBUG "WaveLAN: Roaming Disabled on device %s\n",dev->name);    /* Fixme : maybe we should check that the timer exist before deleting it */  del_timer(&lp->cell_timer);          /* Remove cell expiry timer       */  ptr=lp->wavepoint_table.head;        /* Clear device's WavePoint table */  while(ptr!=NULL)    {      old_ptr=ptr;      ptr=ptr->next;	      wl_del_wavepoint(old_ptr,lp);	    }}/* Enable/Disable NWID promiscuous mode on a given device */void wv_nwid_filter(unsigned char mode, net_local *lp){  mm_t                  m;  unsigned long         flags;  #ifdef WAVELAN_ROAMING_DEBUG  printk(KERN_DEBUG "WaveLAN: NWID promisc %s, device %s\n",(mode==NWID_PROMISC) ? "on" : "off", lp->dev->name);#endif    /* Disable interrupts & save flags */  wv_splhi(lp, &flags);    m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00;  mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1);    if(mode==NWID_PROMISC)    lp->cell_search=1;  else    lp->cell_search=0;  /* ReEnable interrupts & restore flags */  wv_splx(lp, &flags);}/* Find a record in the WavePoint table matching a given NWID */wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp){  wavepoint_history	*ptr=lp->wavepoint_table.head;    while(ptr!=NULL){    if(ptr->nwid==nwid)      return ptr;	    ptr=ptr->next;  }  return NULL;}/* Create a new wavepoint table entry */wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp){  wavepoint_history *new_wavepoint;#ifdef WAVELAN_ROAMING_DEBUG	  printk(KERN_DEBUG "WaveLAN: New Wavepoint, NWID:%.4X\n",nwid);#endif    if(lp->wavepoint_table.num_wavepoints==MAX_WAVEPOINTS)    return NULL;    new_wavepoint=(wavepoint_history *) kmalloc(sizeof(wavepoint_history),GFP_ATOMIC);  if(new_wavepoint==NULL)    return NULL;    new_wavepoint->nwid=nwid;                       /* New WavePoints NWID */  new_wavepoint->average_fast=0;                    /* Running Averages..*/  new_wavepoint->average_slow=0;  new_wavepoint->qualptr=0;                       /* Start of ringbuffer */  new_wavepoint->last_seq=seq-1;                /* Last sequence no.seen */  memset(new_wavepoint->sigqual,0,WAVEPOINT_HISTORY);/* Empty ringbuffer */    new_wavepoint->next=lp->wavepoint_table.head;/* Add to wavepoint table */  new_wavepoint->prev=NULL;    if(lp->wavepoint_table.head!=NULL)    lp->wavepoint_table.head->prev=new_wavepoint;    lp->wavepoint_table.head=new_wavepoint;    lp->wavepoint_table.num_wavepoints++;     /* no. of visible wavepoints */    return new_wavepoint;}/* Remove a wavepoint entry from WavePoint table */void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp){  if(wavepoint==NULL)    return;    if(lp->curr_point==wavepoint)    lp->curr_point=NULL;    if(wavepoint->prev!=NULL)    wavepoint->prev->next=wavepoint->next;    if(wavepoint->next!=NULL)    wavepoint->next->prev=wavepoint->prev;    if(lp->wavepoint_table.head==wavepoint)    lp->wavepoint_table.head=wavepoint->next;    lp->wavepoint_table.num_wavepoints--;  kfree(wavepoint);}/* Timer callback function - checks WavePoint table for stale entries */ void wl_cell_expiry(unsigned long data){  net_local *lp=(net_local *)data;  wavepoint_history *wavepoint=lp->wavepoint_table.head,*old_point;  #if WAVELAN_ROAMING_DEBUG > 1  printk(KERN_DEBUG "WaveLAN: Wavepoint timeout, dev %s\n",lp->dev->name);#endif    if(lp->wavepoint_table.locked)    {#if WAVELAN_ROAMING_DEBUG > 1      printk(KERN_DEBUG "WaveLAN: Wavepoint table locked...\n");#endif            lp->cell_timer.expires=jiffies+1; /* If table in use, come back later */      add_timer(&lp->cell_timer);      return;    }    while(wavepoint!=NULL)    {      if(wavepoint->last_seen < jiffies-CELL_TIMEOUT)	{#ifdef WAVELAN_ROAMING_DEBUG	  printk(KERN_DEBUG "WaveLAN: Bye bye %.4X\n",wavepoint->nwid);#endif	  	  old_point=wavepoint;	  wavepoint=wavepoint->next;	  wl_del_wavepoint(old_point,lp);	}      else	wavepoint=wavepoint->next;    }  lp->cell_timer.expires=jiffies+CELL_TIMEOUT;  add_timer(&lp->cell_timer);}/* Update SNR history of a wavepoint */void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq)	{  int i=0,num_missed=0,ptr=0;  int average_fast=0,average_slow=0;    num_missed=(seq-wavepoint->last_seq)%WAVEPOINT_HISTORY;/* Have we missed							    any beacons? */  if(num_missed)    for(i=0;i<num_missed;i++)      {	wavepoint->sigqual[wavepoint->qualptr++]=0; /* If so, enter them as 0's */	wavepoint->qualptr %=WAVEPOINT_HISTORY;    /* in the ringbuffer. */      }  wavepoint->last_seen=jiffies;                 /* Add beacon to history */  wavepoint->last_seq=seq;	  wavepoint->sigqual[wavepoint->qualptr++]=sigqual;            wavepoint->qualptr %=WAVEPOINT_HISTORY;  ptr=(wavepoint->qualptr-WAVEPOINT_FAST_HISTORY+WAVEPOINT_HISTORY)%WAVEPOINT_HISTORY;    for(i=0;i<WAVEPOINT_FAST_HISTORY;i++)       /* Update running averages */    {      average_fast+=wavepoint->sigqual[ptr++];      ptr %=WAVEPOINT_HISTORY;    }    average_slow=average_fast;  for(i=WAVEPOINT_FAST_HISTORY;i<WAVEPOINT_HISTORY;i++)    {      average_slow+=wavepoint->sigqual[ptr++];      ptr %=WAVEPOINT_HISTORY;    }    wavepoint->average_fast=average_fast/WAVEPOINT_FAST_HISTORY;  wavepoint->average_slow=average_slow/WAVEPOINT_HISTORY;	}/* Perform a handover to a new WavePoint */void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp){  ioaddr_t              base = lp->dev->base_addr;    mm_t                  m;  unsigned long         flags;  if(wavepoint==lp->curr_point)          /* Sanity check... */    {      wv_nwid_filter(!NWID_PROMISC,lp);      return;    }  #ifdef WAVELAN_ROAMING_DEBUG  printk(KERN_DEBUG "WaveLAN: Doing handover to %.4X, dev %s\n",wavepoint->nwid,lp->dev->name);#endif 	  /* Disable interrupts & save flags */  wv_splhi(lp, &flags);  m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF;  m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8;    mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2);    /* ReEnable interrupts & restore flags */  wv_splx(lp, &flags);  wv_nwid_filter(!NWID_PROMISC,lp);  lp->curr_point=wavepoint;}/* Called when a WavePoint beacon is received */static inline void wl_roam_gather(device *  dev,				  u_char *  hdr,   /* Beacon header */				  u_char *  stats) /* SNR, Signal quality 						      of packet */{  wavepoint_beacon *beacon= (wavepoint_beacon *)hdr; /* Rcvd. Beacon */  unsigned short nwid=ntohs(beacon->nwid);    unsigned short sigqual=stats[2] & MMR_SGNL_QUAL;   /* SNR of beacon */  wavepoint_history *wavepoint=NULL;                /* WavePoint table entry */  net_local *lp=(net_local *)dev->priv;              /* Device info */#ifdef I_NEED_THIS_FEATURE  /* Some people don't need this, some other may need it */  nwid=nwid^ntohs(beacon->domain_id);#endif#if WAVELAN_ROAMING_DEBUG > 1  printk(KERN_DEBUG "WaveLAN: beacon, dev %s:\n",dev->name);  printk(KERN_DEBUG "Domain: %.4X NWID: %.4X SigQual=%d\n",ntohs(beacon->domain_id),nwid,sigqual);#endif    lp->wavepoint_table.locked=1;                            /* <Mutex> */    wavepoint=wl_roam_check(nwid,lp);            /* Find WavePoint table entry */  if(wavepoint==NULL)                    /* If no entry, Create a new one... */    {      wavepoint=wl_new_wavepoint(nwid,beacon->seq,lp);      if(wavepoint==NULL)	goto out;    }  if(lp->curr_point==NULL)             /* If this is the only WavePoint, */    wv_roam_handover(wavepoint, lp);	         /* Jump on it! */    wl_update_history(wavepoint, sigqual, beacon->seq); /* Update SNR history							 stats. */    if(lp->curr_point->average_slow < SEARCH_THRESH_LOW) /* If our current */    if(!lp->cell_search)                  /* WavePoint is getting faint, */      wv_nwid_filter(NWID_PROMISC,lp);    /* start looking for a new one */    if(wavepoint->average_slow >      lp->curr_point->average_slow + WAVELAN_ROAMING_DELTA)    wv_roam_handover(wavepoint, lp);   /* Handover to a better WavePoint */    if(lp->curr_point->average_slow > SEARCH_THRESH_HIGH) /* If our SNR is */    if(lp->cell_search)  /* getting better, drop out of cell search mode */      wv_nwid_filter(!NWID_PROMISC,lp);  out:  lp->wavepoint_table.locked=0;                        /* </MUTEX>   :-) */}/* Test this MAC frame a WavePoint beacon */static inline int WAVELAN_BEACON(unsigned char *data){  wavepoint_beacon *beacon= (wavepoint_beacon *)data;  static wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00};    if(memcmp(beacon,&beacon_template,9)==0)    return 1;  else    return 0;}#endif	/* WAVELAN_ROAMING *//************************ I82593 SUBROUTINES *************************//* * Useful subroutines to manage the Ethernet controller *//*------------------------------------------------------------------*//* * Routine to synchronously send a command to the i82593 chip.  * Should be called with interrupts disabled. * (called by wv_packet_write(), wv_ru_stop(), wv_ru_start(), *  wv_82593_config() & wv_diag()) */static intwv_82593_cmd(device *	dev,	     char *	str,	     int	cmd,	     int	result){  ioaddr_t	base = dev->base_addr;  int		status;  int		wait_completed;  long		spin;  /* Spin until the chip finishes executing its current command (if any) */  spin = 1000;  do    {      /* Time calibration of the loop */      udelay(10);      /* Read the interrupt register */      outb(OP0_NOP | CR0_STATUS_3, LCCR(base));      status = inb(LCSR(base));    }  while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0));  /* If the interrupt hasn't be posted */  if(spin <= 0)    {#ifdef DEBUG_INTERRUPT_ERROR      printk(KERN_INFO "wv_82593_cmd: %s timeout (previous command), status 0x%02x\n",	     str, status);#endif      return(FALSE);    }  /* Issue the command to the controller */  outb(cmd, LCCR(base));  /* If we don't have to check the result of the command   * Note : this mean that the irq handler will deal with that */  if(result == SR0_NO_RESULT)    return(TRUE);  /* We are waiting for command completion */

⌨️ 快捷键说明

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