Only in clients: .depfiles
diff -ur ../temp/pcmcia-cs-3.0.8/clients/wavelan_cs.c clients/wavelan_cs.c
--- ../temp/pcmcia-cs-3.0.8/clients/wavelan_cs.c	Thu Dec 24 15:33:43 1998
+++ clients/wavelan_cs.c	Wed Jan 27 14:45:56 1999
@@ -4,8 +4,27 @@
  *		Jean II - HPLB '96
  *
  * Reorganisation and extension of the driver.
- * Original copyrigth follow. See wavelan_cs.h for details.
+ * Original copyright follows. See wavelan_cs.h for details.
+ * 
+ * Joseph O'Sullivan & John Langford (josullvn@cs.cmu.edu & jcl@cs.cmu.edu)
+ * feb 25 '98  made changes to bring the i82593 control/int handling
+ *             in line with offical specs...
+ *            Design Specification for Wavelan PCMCIA HOST Adapter 
+ *                           Engineering Document 407-0024222 RevB
+ *            Interface Specification for Wavelan Host Adapter 
+ *                             TYPE IBM AT 
+ *                           Engineering Document 407-0023326 RevA
+ *            PSA Contents Definition
+ *                           Engineering Document 407-0030558 RevC
+ *            CIS for Wavelan PCMCIA 915
+ *                           Engineering Document 407-0024222 RevB
+ *            rvb@cs provided the spec, and braam@cs a laptop.
+ * April 2 '98 Ready for release
  */
+/* Leave this defined for environments with lots of wavestations 
+ * Mar 98: josullvn@cs.cmu.edu
+ */
+#define WAVELAN_HIGH_COVERAGE
 
 /*
  *	This code is derived from Anthony D. Joseph's code and all the changes here
@@ -518,6 +537,317 @@
 }
 #endif	/* WIRELESS_EXT */
 
+/******************* WaveLAN Roaming routines... ********************/
+#ifdef WAVELAN_ROAMING 
+
+unsigned char                   WAVELAN_BEACON_ADDRESS[]=        /* WavePoint Beacon Address... */
+                                {0x09,0x00,0x0e,0x20,0x03,0x00};
+ 
+void
+wv_roam_init(struct device *dev)
+{
+        net_local  *lp= (net_local *)dev->priv;
+
+	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=(int)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 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);
+
+	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         x;
+ 
+#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 */
+  x = wv_splhi();
+
+  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);
+
+  /* ReEnable interrupts & restore flags */
+  wv_splx(x);
+
+  if(mode==NWID_PROMISC)
+	lp->cell_search=1;
+  else
+	lp->cell_search=0;
+}
+
+/* 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_HIGH_COVERAGE
+	/* This prints out far too much information in a busy environment */
+#if WAVELAN_ROAMING_DEBUG>1
+	printk(KERN_DEBUG "WaveLAN: New Wavepoint, NWID:%.4X\n",nwid);
+#endif
+#else
+#ifdef WAVELAN_ROAMING_DEBUG	
+	printk(KERN_DEBUG "WaveLAN: New Wavepoint, NWID:%.4X\n",nwid);
+#endif
+#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_HIGH_COVERAGE
+#if WAVELAN_ROAMING_DEBUG>1
+			printk(KERN_DEBUG "WaveLAN: Bye bye %.4X\n",wavepoint->nwid);
+#endif
+#else
+#ifdef WAVELAN_ROAMING_DEBUG	
+	printk(KERN_DEBUG "WaveLAN: New Wavepoint, NWID:%.4X\n",nwid);
+#endif
+#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 in the */
+			wavepoint->qualptr %=WAVEPOINT_HISTORY;     /* 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)
+{
+  unsigned short        base = lp->dev->base_addr;  
+  mm_t                  m;
+  unsigned long         x;
+
+  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 */
+  x = wv_splhi();
+
+  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(x);
+
+  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);          /* NWID of WavePoint */
+	unsigned short		domain=ntohs(beacon->domain_id);   /* Domain of WavePoint */
+	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 */
+
+#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",domain,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 WavePoint is getting */
+	  if(!lp->cell_search)                                   /* faint, start looking for a new one  */
+	    wv_nwid_filter(NWID_PROMISC,lp);
+
+	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 getting better, drop */
+	  if(lp->cell_search)                                    /* 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
+
 /************************ I82593 SUBROUTINES *************************/
 /*
  * Usefull subroutines to manage the Ethernet controler
@@ -2205,7 +2535,7 @@
      
   /* Statistics gathering & stuff associated.
    * It seem a bit messy with all the define, but it's really simple... */
-#if defined(WIRELESS_SPY) || defined(HISTOGRAM)
+#if defined(WIRELESS_SPY) || defined(HISTOGRAM) || defined(WAVELAN_ROAMING)
   if(
 #ifdef WIRELESS_SPY
      (lp->spy_number > 0) ||
@@ -2213,6 +2543,9 @@
 #ifdef HISTOGRAM
      (lp->his_number > 0) ||
 #endif	/* HISTOGRAM */
+#ifdef WAVELAN_ROAMING
+     (1) ||
+#endif /* WAVELAN ROAMING */
      0)
     {
       u_char	stats[3];	/* Signal level, Noise level, Signal quality */
@@ -2225,6 +2558,11 @@
 	     dev->name, stats[0] & 0x3F, stats[1] & 0x3F, stats[2] & 0x0F);
 #endif
 
+#ifdef WAVELAN_ROAMING 
+      if(WAVELAN_BEACON(skb->data)){
+	wl_roam_gather(dev, skb->data, stats);
+      }
+#endif
       /* Spying stuff */
 #ifdef WIRELESS_SPY
       /* Same as above */
@@ -2348,7 +2686,16 @@
       len = c[2] | (c[3] << 8);
 
       /* Check status */
+#ifdef WAVELAN_HIGH_COVERAGE
+      /* josullvn@cs.cmu.edu:
+       * We are more restrictive about the types of errors that are problems. 
+       * Most importantly RX_NO_AD_MATCH and RX_IA_MATCH are status messages in
+       * CMU like situations.
+       */
+      if ((status &  0x4270) != 0x0010)
+#else
       if(!(status & RX_RCV_OK))
+#endif
 	{
 	  lp->stats.rx_errors++;
 	  if(status & RX_NO_SFD)
@@ -2433,6 +2780,9 @@
 
   /* Indicate end of transmit chain */
   outb(OP0_NOP, PIOP(base));
+#ifdef WAVELAN_HIGH_COVERAGE
+  outb(OP0_NOP, PIOP(base));  /* josullvn@cs.cmu.edu: need to send a second NOP for alignment... */
+#endif
 
   /* Reset the transmit DMA pointer */
   hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET);
@@ -2446,6 +2796,11 @@
   lp->stats.tx_bytes += length;
 #endif	/* 2.1.25 */
 
+#ifndef WAVELAN_HIGH_COVERAGE
+  /* josullvn@cs.cmu.edu: 
+   * This watch dog thing is a nasty hack, and flares up 
+   * badly in our environment
+   */
   /* If watchdog not already active, activate it... */
   if(lp->watchdog.prev == (timer_list *) NULL)
     {
@@ -2453,6 +2808,7 @@
       lp->watchdog.expires = jiffies + WATCHDOG_JIFFIES;
       add_timer(&lp->watchdog);
     }
+#endif
 
   wv_splx(x); 
 
@@ -2980,6 +3336,31 @@
   cfblk.tx_eop = TRUE;  	/* Signal EOP on packet transmission */
   cfblk.rbuf_size = RX_SIZE>>11;	/* Set receive buffer size */
   cfblk.rcvstop = TRUE; 	/* Enable Receive Stop Register */
+#ifdef WAVELAN_HIGH_COVERAGE
+  /* josullvn@cs.cmu.edu:
+   * This are some of the more significant changes I made. Not
+   * all of them may be necessary, and some may not be correct.
+   * Basically, the configuration now exactly matches that of the datasheets
+   * driver. This is obviously stupid if the Linux code doesn't handle
+   * those things the same way. However, wished to fix the occurances
+   * of NO_CTS errors and HEART_BEAT errors. If the new cfblk changes
+   * introduced below are removed, they return. However, these changes
+   * introduce some error in frame handling - those errors are recoverable
+   * but should be fixed.
+   */
+  cfblk.fifo_limit = 8;        
+  cfblk.fifo_32 = 1;
+  cfblk.throttle_enb = 0;     //
+  cfblk.preamb_len = 0;       // this seems to be necessary to kill
+			      // those heartbeat messages... 
+  cfblk.exp_prio = 5;	      ///* conform to 802.3 backoff algoritm */       
+  cfblk.bof_met = 1;	      ///* conform to 802.3 backoff algoritm */
+  cfblk.ifrm_spc = 2;	      //
+  cfblk.slottim_low = 1;
+  cfblk.slottim_hi =  0;
+  cfblk.rcvstop = 0; 	      //
+  cfblk.syncrqs = 0; 	
+#endif
 
 #ifdef DEBUG_I82593_SHOW
   {
@@ -3023,6 +3404,12 @@
 		   OP0_IA_SETUP, SR0_IA_SETUP_DONE))
     return(FALSE);
 
+#ifdef WAVELAN_ROAMING
+  /* If roaming is enabled, join the "Beacon Request" multicast group...*/
+  /* But only if it's not in there already! */
+
+  dev_mc_add(dev,WAVELAN_BEACON_ADDRESS, WAVELAN_ADDR_SIZE, 1); 
+#endif
   /* If any multicast address to set */
   if(lp->mc_count)
     {
@@ -3895,6 +4282,10 @@
 
   /* If the device is currently in use, we won't release until it is
    * actually closed. */
+
+#ifdef WAVELAN_ROAMING
+  wv_roam_cleanup(dev);
+#endif
   if(link->open)
     {
 #ifdef DEBUG_CONFIG_INFO
@@ -4049,6 +4440,10 @@
       wavelan_detach(link);
       return NULL;
     }
+
+#ifdef WAVELAN_ROAMING
+  wv_roam_init(dev);
+#endif
 
 #ifdef DEBUG_CALLBACK_TRACE
   printk(KERN_DEBUG "<- wavelan_attach()\n");
diff -ur ../temp/pcmcia-cs-3.0.8/clients/wavelan_cs.h clients/wavelan_cs.h
--- ../temp/pcmcia-cs-3.0.8/clients/wavelan_cs.h	Sun May 10 08:14:20 1998
+++ clients/wavelan_cs.h	Wed Jan 27 14:45:56 1999
@@ -336,9 +336,57 @@
 
 /* Wavelan declarations */
 #include "i82593.h"	/* Definitions for the Intel chip */
-
 #include "wavelan.h"	/* Others bits of the hardware */
 
+/*************************** WaveLAN Roaming  **************************/
+#define WAVELAN_ROAMING 
+#define WAVELAN_ROAMING_DEBUG           1               /* 1 = Trace of handover decisions  */
+                                                        /* 2 = Info on each beacon rcvd... */
+#define MAX_WAVEPOINTS			7		/* Max visible at one time */
+#define WAVEPOINT_HISTORY		5		/* SNR sample hist. slow search */
+#define WAVEPOINT_FAST_HISTORY		2		/* SNR sample hist. fast search */
+#define SEARCH_THRESH_LOW		10		/* SNR to enter cell search */	
+#define SEARCH_THRESH_HIGH		13		/* SNR to leave cell search */	
+#define WAVELAN_ROAMING_DELTA		1		/* Hysteresis value (+/- SNR) */
+#define CELL_TIMEOUT			2*HZ		/* in jiffies */	
+
+#define FAST_CELL_SEARCH		1		/* Boolean values... */
+#define NWID_PROMISC			1		/* for code clarity. */
+
+typedef struct wavepoint_beacon
+{
+  unsigned char         dsap,                 /* Unused */
+                        ssap,                 /* Unused */
+                        ctrl,                 /* Unused */
+                        O,U,I,                /* Unused */
+                        spec_id1,             /* Unused */
+                        spec_id2,             /* Unused */
+                        pdu_type,             /* Unused */
+                        seq;                  /* WavePoint beacon sequence no. */
+  unsigned short        domain_id,            /* WavePoint Domain ID */
+                        nwid;                 /* WavePoint NWID */
+} wavepoint_beacon;
+
+typedef struct wavepoint_history
+{
+  unsigned short  	nwid;                      /* WavePoint's NWID */
+  int			average_slow;              /* SNR running average */
+  int			average_fast;              /* SNR running average */
+  unsigned char		sigqual[WAVEPOINT_HISTORY];/* Ringbuffer of recent SNR's */
+  unsigned char		qualptr;                   /* Index into ringbuffer */
+  unsigned char		last_seq;                  /* Last seq. no seen for WavePoint */
+  struct wavepoint_history *next;                  /* Next WavePoint in table */
+  struct wavepoint_history *prev;                  /* Prev Wavepoint in table */
+  unsigned long		last_seen;                 /* Time of last beacon recvd, jiffies */
+} wavepoint_history;
+
+struct wavepoint_table
+{
+  wavepoint_history	*head;                     /* Start of ringbuffer */
+  int			num_wavepoints;            /* No. of WavePoints visible */
+  unsigned char		locked;                    /* Table lock */
+};
+
 /****************************** DEBUG ******************************/
 
 #undef DEBUG_MODULE_TRACE	/* Module insertion/removal */
@@ -458,9 +506,28 @@
   u_char	his_range[16];		/* Boundaries of interval ]n-1; n] */
   u_long	his_sum[16];		/* Sum in interval */
 #endif	/* HISTOGRAM */
+#ifdef WAVELAN_ROAMING
+  struct wavepoint_table        wavepoint_table;  /* Table of visible WavePoints */
+  wavepoint_history *           curr_point;       /* Current wavepoint */
+  int			        cell_search;	  /* Searching for new cell? */      
+  struct timer_list	        cell_timer;       /* Garbage collection */
+#endif
 };
 
 /**************************** PROTOTYPES ****************************/
+
+/* ----------------------- ROAMING SUBROUTINES --------------------- */
+
+wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp);
+wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local *lp);
+void wl_del_wavepoint(wavepoint_history *wavepoint, net_local *lp);
+void wl_cell_expiry(unsigned long data);
+wavepoint_history *wl_best_sigqual(int fast_search, net_local *lp);
+void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq);
+void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp);
+void wv_nwid_filter(unsigned char mode, net_local *lp);
+void wv_roam_init(struct device *dev);
+void wv_roam_cleanup(struct device *dev);
 
 /* ----------------------- MISC SUBROUTINES ------------------------ */
 static inline unsigned long	/* flags */
