📄 wavelan_cs.c
字号:
{ 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 + -