📄 wvlan_cs.c
字号:
{ int chlist = wvlan_hw_getchannellist(ifbp); int i, k = 0; /* Compute maximum number of freq to scan */ if(max > 15) max = 15; /* Check availability */ for(i = 0; i < max; i++) if((1 << i) & chlist) {#if WIRELESS_EXT > 7 list[k].i = i + 1; /* Set the list index */#endif /* WIRELESS_EXT */ list[k].m = frequency_list[i] * 100000; list[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */ } return k;}static inline int wvlan_getbitratelist(IFBP ifbp, __s32 *list, int max){ char brlist[9]; int brnum = wvlan_hw_getratelist(ifbp, brlist, sizeof(brlist)); int i; /* Compute maximum number of freq to scan */ if(brnum > max) brnum = max; /* Convert to Mb/s */ for(i = 0; i < max; i++) list[i] = (brlist[i] & 0x7F) * 500000; return brnum;}static int wvlan_hw_setpower (IFBP ifbp, int enabled, int cmd){ CFG_ID_STRCT ltv; int rc; ltv.len = 2; ltv.typ = cmd; ltv.id[0] = cpu_to_le16(enabled); rc = hcf_put_info(ifbp, (LTVP) <v); DEBUG(DEBUG_NOISY, "%s: hcf_put_info(0x%x:0x%x) returned 0x%x\n", dev_info, cmd, enabled, rc); return rc;}static int wvlan_hw_getpower (IFBP ifbp, int cmd){ CFG_ID_STRCT ltv; int rc, enabled; ltv.len = 2; ltv.typ = cmd; rc = hcf_get_info(ifbp, (LTVP) <v); enabled = le16_to_cpup(<v.id[0]); DEBUG(DEBUG_NOISY, "%s: hcf_get_info(0x%x):0x%x returned 0x%x\n", dev_info, cmd, enabled, rc); return rc ? 0 : enabled;}static inline int wvlan_hw_setpmsleep (IFBP ifbp, int duration){ CFG_ID_STRCT ltv; int rc; ltv.len = 2; ltv.typ = CFG_CNF_MAX_SLEEP_DURATION; ltv.id[0] = cpu_to_le16(duration); rc = hcf_put_info(ifbp, (LTVP) <v); DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CNF_MAX_SLEEP_DURATION:0x%x) returned 0x%x\n", dev_info, duration, rc); return rc;}static inline int wvlan_hw_getpmsleep (IFBP ifbp){ CFG_ID_STRCT ltv; int rc, duration; ltv.len = 2; ltv.typ = CFG_CNF_MAX_SLEEP_DURATION; rc = hcf_get_info(ifbp, (LTVP) <v); duration = le16_to_cpup(<v.id[0]); DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CNF_MAX_SLEEP_DURATION):0x%x returned 0x%x\n", dev_info, duration, rc); return rc ? 0 : duration;}static int wvlan_hw_getprivacy (IFBP ifbp){ CFG_ID_STRCT ltv; int rc, privacy; // This function allow to distiguish bronze cards from other // types, to know if WEP exist... // This is stupid, we have no way to distinguish the silver // and gold cards, because the call below return 1 in all // cases. Yuk... ltv.len = 2; ltv.typ = CFG_PRIVACY_OPTION_IMPLEMENTED; rc = hcf_get_info(ifbp, (LTVP) <v); privacy = le16_to_cpup(<v.id[0]); DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_PRIVACY_OPTION_IMPLEMENTED):0x%x returned 0x%x\n", dev_info, privacy, rc); return rc ? 0 : privacy;}static int wvlan_hw_setprivacy (IFBP ifbp, int mode, int transmit, KEY_STRCT *keys){ CFG_ID_STRCT ltv; CFG_CNF_DEFAULT_KEYS_STRCT ltv_key; int rc; int i; if (mode) { // Set the index of the key used for transmission ltv.len = 2; ltv.typ = CFG_CNF_TX_KEY_ID; ltv.id[0] = cpu_to_le16(transmit); rc = hcf_put_info(ifbp, (LTVP) <v); DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_TX_KEY_ID:0x%x) returned 0x%x\n", dev_info, mode, rc); if (rc) return rc; // Set the keys themselves (all in on go !) ltv_key.len = sizeof(KEY_STRCT)*MAX_KEYS/2 + 1; ltv_key.typ = CFG_CNF_DEFAULT_KEYS; memcpy((char *) <v_key.key, (char *) keys, sizeof(KEY_STRCT)*MAX_KEYS); for (i = 0; i < MAX_KEYS; ++i) cpu_to_le16s(<v_key.key[i].len); rc = hcf_put_info(ifbp, (LTVP) <v_key); DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_TX_KEY_ID:0x%x) returned 0x%x\n", dev_info, mode, rc); if (rc) return rc; } // enable/disable encryption ltv.len = 2; ltv.typ = CFG_CNF_ENCRYPTION; ltv.id[0] = cpu_to_le16(mode); rc = hcf_put_info(ifbp, (LTVP) <v); DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_CNF_ENCRYPTION:0x%x) returned 0x%x\n", dev_info, mode, rc); return rc;}#endif /* WIRELESS_EXT */static int wvlan_hw_setpromisc (IFBP ifbp, int promisc){ CFG_ID_STRCT ltv; int rc; ltv.len = 2; ltv.typ = CFG_PROMISCUOUS_MODE; ltv.id[0] = cpu_to_le16(promisc); rc = hcf_put_info(ifbp, (LTVP) <v); DEBUG(DEBUG_NOISY, "%s: hcf_put_info(CFG_PROMISCUOUS_MODE:0x%x) returned 0x%x\n", dev_info, promisc, rc); return rc;}static inline int wvlan_hw_getfirmware (IFBP ifbp, int *vendor, int *major, int *minor){ CFG_ID_STRCT ltv; int rc; ltv.len = 32; ltv.typ = CFG_STA_IDENTITY; rc = hcf_get_info(ifbp, (LTVP) <v); DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_STA_IDENTITY) returned 0x%x\n", dev_info, rc); if (rc) return rc; /* Get the data we need (note : 16 bits operations) */ *vendor = le16_to_cpup(<v.id[1]); *major = le16_to_cpup(<v.id[2]); *minor = le16_to_cpup(<v.id[3]); /* There is more data after that, but I can't guess its use */ DEBUG(DEBUG_NOISY, "%s: hcf_get_info(CFG_STA_IDENTITY):%d-%d.%d\n", dev_info, *vendor, *major, *minor); return 0;}/******************************************************************** * HARDWARE CONFIG / SHUTDOWN / RESET *//*------------------------------------------------------------------*//* * Hardware configuration of the Wavelan * The caller *must* disable IRQs by himself before comming here. */static int wvlan_hw_config (struct net_device *dev){ struct net_local *local = (struct net_local *) dev->priv; int rc, i, chlist; int vendor, major, minor; /* Firmware revision */ int firmware; DEBUG(DEBUG_CALLTRACE, "-> wvlan_hw_config(%s)\n", dev->name); // Init the HCF library hcf_connect(&local->ifb, dev->base_addr); // Init hardware and turn on interrupts rc = hcf_action(&local->ifb, HCF_ACT_CARD_IN); DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_CARD_IN) returned 0x%x\n", dev_info, rc);#if defined(PCMCIA_DEBUG) && (PCMCIA_DEBUG>=DEBUG_INTERRUPT) local->ifb.IFB_IntEnMask |= HREG_EV_TICK;#endif rc = hcf_action(&local->ifb, HCF_ACT_INT_ON); DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_ON) returned 0x%x\n", dev_info, rc); /* Get MAC address (before we get a chance to fail) */ if (!rc) { rc = wvlan_hw_getmacaddr(&local->ifb, dev->dev_addr, ETH_ALEN); printk(KERN_INFO "%s: MAC address on %s is ", dev_info, dev->name); for (i=0; i<ETH_ALEN; i++) printk("%02x ", dev->dev_addr[i]); printk("\n"); } /* Get firmware revision of the card */ if (!rc) rc = wvlan_hw_getfirmware(&local->ifb, &vendor, &major, &minor); /* Process firmware info to know what it supports */ firmware = (major << 16) + minor; if(!rc) { switch(vendor) { case 0x1: /* This is a Lucent card : Wavelan IEEE, Orinoco, * Cabletron/Enterasys Roamabout or ELSA cards. * This is what we mainly support... * Note : this will work at least for Lucent * firmwares */ local->has_port3 = 1; local->has_ibssid = ((firmware >= 0x60006) + (firmware >= 0x60010)); local->has_mwo = (firmware >= 0x60000); local->has_wep = (firmware >= 0x40020); local->has_pwep = 0; local->has_pm = (firmware >= 0x40020); /* Note : I've tested the following firmwares : * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.06 and 6.16 * Jean II */ /* Tested CableTron 4.32 - Anton */ break; case 0x2: case 0x3: case 0x6: /* This is a PrismII card. It is is *very* similar * to the Lucent, and the driver work 95%, * therefore, we attempt to support it... */ printk(KERN_INFO "%s: PrismII card, rev 0x%X\n", dev_info, firmware); local->has_port3 = 1; local->has_ibssid = 0; local->has_mwo = 0; local->has_wep = 0; local->has_pwep = 1; local->has_pm = 1; /* Would need to reverse engineer encryption support, * somebody with a card should do that... */ /* Transmit rate also seem to be different. */ /* Note : currently untested... Jean II */ break; default: printk(KERN_NOTICE "%s: Unrecognised card, card return vendor = 0x%04X, please report...\n", dev_info, vendor); break; } } printk(KERN_INFO "%s: Found firmware 0x%X (vendor %d) - Firmware capabilities : %d-%d-%d-%d-%d\n", dev_info, firmware, vendor, local->has_port3, local->has_ibssid, local->has_mwo, local->has_wep, local->has_pm); if(!rc) { /* Check for a few user mistakes... Cut down on support ;-) */ if((!local->has_port3) && (local->port_type == 3)) { printk(KERN_NOTICE "%s: This firmware doesn't support ``port_type=3'', please use iwconfig.\n", dev_info); rc = 255; } if((!local->has_ibssid) && (local->allow_ibss)) { printk(KERN_NOTICE "%s: This firmware doesn't support ``allow_ibss=1'', please update it.\n", dev_info); rc = 255; } if((local->allow_ibss) && (local->has_ibssid == 1) && (local->network_name[0] == '\0')) { printk(KERN_NOTICE "%s: This firmware require an ESSID in Ad-Hoc mode, please use iwconfig.\n", dev_info); rc = 255; } if((local->has_ibssid) && (local->port_type == 3)) { printk(KERN_NOTICE "%s: Warning, you are using the old proprietary Ad-Hoc mode (not the IBSS Ad-Hoc mode).\n", dev_info); } } // Set hardware parameters if (!rc) rc = wvlan_hw_setmaxdatalen(&local->ifb, HCF_MAX_MSG); if (!rc) rc = wvlan_hw_setporttype(&local->ifb, local->port_type); if (!rc && *(local->network_name)) rc = wvlan_hw_setssid(&local->ifb, local->network_name, local->port_type); /* Firmware 4.08 doesn't like that at all :-( */ if (!rc && (local->has_ibssid)) rc = wvlan_hw_setallowibssflag(&local->ifb, local->allow_ibss);#ifdef WIRELESS_EXT // Set other hardware parameters if (!rc && *(local->station_name)) rc = wvlan_hw_setstationname(&local->ifb, local->station_name); if (!rc) rc = wvlan_hw_setthreshold(&local->ifb, local->ap_density, CFG_CNF_SYSTEM_SCALE); if (!rc) rc = wvlan_hw_setthreshold(&local->ifb, local->transmit_rate, CFG_TX_RATE_CONTROL); if (!rc) rc = wvlan_hw_setthreshold(&local->ifb, local->medium_reservation, CFG_RTS_THRH); /* Normal fragmentation for v4 and earlier */ if (!rc && (!local->has_mwo)) rc = wvlan_hw_setthreshold(&local->ifb, local->frag_threshold, CFG_FRAGMENTATION_THRH); /* MWO robustness for v6 and later */ if (!rc && (local->has_mwo)) rc = wvlan_hw_setthreshold(&local->ifb, local->mwo_robust, CFG_CNF_MICRO_WAVE); /* Firmware 4.08 doesn't like those at all :-( */ if (!rc && (local->has_wep)) rc = wvlan_hw_setprivacy(&local->ifb, local->wep_on, local->transmit_key, local->key); if (!rc && (local->has_pm)) rc = wvlan_hw_setpower(&local->ifb, local->pm_on, CFG_CNF_PM_ENABLED); if (!rc && (local->has_pm) && (local->pm_on)) rc = wvlan_hw_setpower(&local->ifb, local->pm_multi, CFG_CNF_MCAST_RX); if (!rc && (local->has_pm) && (local->pm_on)) rc = wvlan_hw_setpmsleep(&local->ifb, local->pm_period);#endif /* WIRELESS_EXT */ // Check valid channel settings if (!rc && ((local->port_type == 3) || (local->allow_ibss))) { chlist = wvlan_hw_getchannellist(&local->ifb); printk(KERN_INFO "%s: Valid channels: ", dev_info); for (i=1; i<17; i++) if (1<<(i-1) & chlist) printk("%d ", i); printk("\n"); if (local->channel < 1 || local->channel > 16 || !(1 << (local->channel - 1) & chlist)) printk(KERN_WARNING "%s: Channel value of %d is invalid!\n", dev_info, local->channel); else rc = wvlan_hw_setchannel(&local->ifb, local->channel); } // Enable hardware if (!rc) { rc = hcf_enable(&local->ifb, 0); DEBUG(DEBUG_NOISY, "%s: hcf_enable(0) returned 0x%x\n", dev_info, rc); } // Report error if any if (rc) printk(KERN_WARNING "%s: Initialization failed!\n", dev_info); DEBUG(DEBUG_CALLTRACE, "<- wvlan_hw_config()\n"); return rc;}/*------------------------------------------------------------------*//* * Wrapper for calling wvlan_hw_config() with irq disabled */static inline int wvlan_hw_config_locked (struct net_device *dev){ struct net_local *local = (struct net_local *) dev->priv; unsigned long flags; int ret; wv_driver_lock(local, &flags); ret = wvlan_hw_config(dev); wv_driver_unlock(local, &flags); return ret;}/*------------------------------------------------------------------*//* * Hardware de-configuration of the Wavelan (switch off the device) * The caller *must* disable IRQs by himself before comming here. */static int wvlan_hw_shutdown (struct net_device *dev){ struct net_local *local = (struct net_local *) dev->priv; int rc; DEBUG(DEBUG_CALLTRACE, "-> wvlan_hw_shutdown(%s)\n", dev->name); // Disable and shutdown hardware rc = hcf_disable(&local->ifb, 0); DEBUG(DEBUG_NOISY, "%s: hcf_disable(0) returned 0x%x\n", dev_info, rc); rc = hcf_action(&local->ifb, HCF_ACT_INT_OFF); DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_OFF) returned 0x%x\n", dev_info, rc); rc = hcf_action(&local->ifb, HCF_ACT_CARD_OUT); DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_CARD_OUT) returned 0x%x\n", dev_info, rc); // Release HCF library hcf_disconnect(&local->ifb); DEBUG(DEBUG_CALLTRACE, "<- wvlan_hw_shutdown()\n"); return 0;}/*------------------------------------------------------------------*//* * "light" hardware reset of the Wavelan * The caller *must* disable IRQs by himself before comming here. */static int wvlan_hw_reset (struct net_device *dev){ struct net_local *local = (struct net_local *) dev->priv; int rc; DEBUG(DEBUG_CALLTRACE, "-> wvlan_hw_reset(%s)\n", dev->name); // Disable hardware rc = hcf_disable(&local->ifb, 0); DEBUG(DEBUG_NOISY, "%s: hcf_disable(0) returned 0x%x\n", dev_info, rc); rc = hcf_action(&local->ifb, HCF_ACT_INT_OFF); DEBUG(DEBUG_NOISY, "%s: hcf_action(HCF_ACT_INT_OFF) returned 0x%x\n", dev_info, rc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -