📄 atmel.c
字号:
case REG_DOMAIN_DOC: r = "Canada"; break; case REG_DOMAIN_ETSI: r = "Europe"; break; case REG_DOMAIN_SPAIN: r = "Spain"; break; case REG_DOMAIN_FRANCE: r = "France"; break; case REG_DOMAIN_MKK: r = "Japan (MKK)"; break; case REG_DOMAIN_MKK1: r = "Japan (MKK1)"; break; case REG_DOMAIN_ISRAEL: r = "Israel"; break; default: r = "<unknown>"; } p += sprintf(p, "MAC memory type:\t%s\n", c); p += sprintf(p, "Regulatory domain:\t%s\n", r); p += sprintf(p, "Host CRC checking:\t%s\n", priv->do_rx_crc ? "On" : "Off"); } switch(priv->station_state) { case STATION_STATE_INITIALIZING: s = "Initialising"; break; case STATION_STATE_SCANNING: s = "Scanning"; break; case STATION_STATE_JOINNING: s = "Joining"; break; case STATION_STATE_AUTHENTICATING: s = "Authenticating"; break; case STATION_STATE_ASSOCIATING: s = "Associating"; break; case STATION_STATE_READY: s = "Ready"; break; case STATION_STATE_REASSOCIATING: s = "Reassociating"; break; case STATION_STATE_FORCED_JOINNING: s = "Forced joining"; break; case STATION_STATE_FORCED_JOIN_FAILURE: s = "Forced join failure"; break; case STATION_STATE_NO_CARD: s = "No card"; break; case STATION_STATE_MGMT_ERROR: s = "Management error"; break; case STATION_STATE_DOWN: s = "Down"; break; default: s = "<unknown>"; } p += sprintf(p, "Current state:\t\t%s\n", s); return p - buf;}static int atmel_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ struct atmel_private *priv = (struct atmel_private *)data; int len = atmel_proc_output (page, priv); if (len <= off+count) *eof = 1; *start = page + off; len -= off; if (len>count) len = count; if (len<0) len = 0; return len;}struct net_device *init_atmel_card( unsigned short irq, int port, char *firmware_id, int is3com, int (*card_present)(void *), void *card){ struct net_device *dev; struct atmel_private *priv; int rc; /* Create the network device object. */ dev = alloc_etherdev(sizeof(*priv)); if (!dev) { printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n"); return NULL; } if (dev_alloc_name(dev, dev->name) < 0) { printk(KERN_ERR "atmel: Couldn't get name!\n"); goto err_out_free; } priv = dev->priv; priv->dev = dev; priv->present_callback = card_present; priv->card = card; priv->firmware = NULL; if (firmware) /* module parameter */ strcpy(priv->firmware_id, firmware); else if (firmware_id) /* from PCMCIA card-matching or PCI */ strcpy(priv->firmware_id, firmware_id); else priv->firmware_id[0] = '\0'; priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI; priv->station_state = STATION_STATE_DOWN; priv->is3com = is3com; priv->do_rx_crc = 0; /* For PCMCIA cards, some chips need CRC, some don't so we have to probe. */ if (priv->bus_type == BUS_TYPE_PCCARD) { priv->probe_crc = 1; priv->crc_ok_cnt = priv->crc_ko_cnt = 0; } else priv->probe_crc = 0; memset(&priv->stats, 0, sizeof(priv->stats)); memset(&priv->wstats, 0, sizeof(priv->wstats)); priv->last_qual = jiffies; priv->last_beacon_timestamp = 0; memset(priv->frag_source, 0xff, sizeof(priv->frag_source)); memset(priv->BSSID, 0, 6); priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */ priv->station_was_associated = 0; priv->last_survey = jiffies; priv->preamble = LONG_PREAMBLE; priv->operating_mode = IW_MODE_INFRA; priv->connect_to_any_BSS = 0; priv->tx_rate = 3; priv->auto_tx_rate = 1; priv->channel = 4; priv->power_mode = 0; priv->SSID[0] = '\0'; priv->SSID_size = 0; priv->new_SSID_size = 0; priv->frag_threshold = 2346; priv->rts_threshold = 2347; priv->short_retry = 7; priv->long_retry = 4; priv->wep.wep_is_on = 0; priv->wep.default_key = 0; priv->wep.encryption_level = 0; priv->default_beacon_period = priv->beacon_period = 100; priv->listen_interval = 1; init_timer(&priv->management_timer); spin_lock_init(&priv->irqlock); spin_lock_init(&priv->timerlock); priv->management_timer.function = atmel_management_timer; priv->management_timer.data = (unsigned long) dev; dev->open = atmel_open; dev->stop = atmel_close; dev->change_mtu = atmel_change_mtu; dev->set_mac_address = atmel_set_mac_address; dev->hard_start_xmit = start_tx; dev->get_stats = atmel_get_stats; dev->get_wireless_stats = atmel_get_wireless_stats; dev->wireless_handlers = (struct iw_handler_def *)&atmel_handler_def; dev->do_ioctl = atmel_ioctl; dev->irq = irq; dev->base_addr = port; if ((rc = request_irq(dev->irq, service_interrupt, SA_SHIRQ, dev->name, dev))) { printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc ); goto err_out_free; } if (priv->bus_type == BUS_TYPE_PCI && !request_region( dev->base_addr, 64, dev->name )) { goto err_out_irq; } if (register_netdev(dev)) goto err_out_res; if (!probe_atmel_card(dev)) goto err_out_res; create_proc_read_entry ("driver/atmel", 0, 0, atmel_read_proc, priv); printk(KERN_INFO "%s: Atmel at76c50x wireless. Version %d.%d simon@thekelleys.org.uk\n", dev->name, DRIVER_MAJOR, DRIVER_MINOR); SET_MODULE_OWNER(dev); return dev; err_out_res: if (priv->bus_type == BUS_TYPE_PCI) release_region( dev->base_addr, 64 ); err_out_irq: free_irq(dev->irq, dev); err_out_free: kfree(dev); return NULL;}EXPORT_SYMBOL(init_atmel_card);void stop_atmel_card(struct net_device *dev, int freeres){ struct atmel_private *priv = dev->priv; unregister_netdev(dev); /* put a brick on it... */ if (priv->bus_type == BUS_TYPE_PCCARD) atmel_write16(dev, GCR, 0x0060); atmel_write16(dev, GCR, 0x0040); remove_proc_entry("driver/atmel", NULL); del_timer_sync(&priv->management_timer); free_irq(dev->irq, dev); if (priv->firmware) kfree(priv->firmware); if (freeres) { /* PCMCIA frees this stuff, so only for PCI */ release_region(dev->base_addr, 64); } kfree( dev );}EXPORT_SYMBOL(stop_atmel_card);static const struct { int reg_domain; int min, max;} channel_table[] = { { REG_DOMAIN_FCC, 1, 11}, { REG_DOMAIN_DOC, 1, 11}, { REG_DOMAIN_ETSI, 1, 13}, { REG_DOMAIN_SPAIN, 10, 11}, { REG_DOMAIN_FRANCE, 10, 13}, { REG_DOMAIN_MKK, 14, 14}, { REG_DOMAIN_MKK1, 1, 14}, { REG_DOMAIN_ISRAEL, 9} };static int atmel_validate_channel(struct atmel_private *priv, int channel){ /* check that channel is OK, if so return zero, else return suitable default channel */ int i; for (i = 0; i < sizeof(channel_table)/sizeof(channel_table[0]); i++) if (priv->reg_domain == channel_table[i].reg_domain) { if (channel >= channel_table[i].min && channel <= channel_table[i].max) return 0; else return channel_table[i].min; } return 1;}static int atmel_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct atmel_private *priv = dev->priv; /* Check if we asked for `any' */ if(dwrq->flags == 0) { priv->connect_to_any_BSS = 1; } else { int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; priv->connect_to_any_BSS = 0; /* Check the size of the string */ if (dwrq->length > MAX_SSID_LENGTH + 1) return -E2BIG ; if (index != 0) return -EINVAL; memcpy(priv->new_SSID, extra, dwrq->length - 1); priv->new_SSID_size = dwrq->length - 1; } return -EINPROGRESS;}static int atmel_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct atmel_private *priv = dev->priv; /* Get the current SSID */ if (priv->SSID_size == 0) { memcpy(extra, priv->new_SSID, priv->new_SSID_size); extra[priv->new_SSID_size] = '\0'; dwrq->length = priv->new_SSID_size + 1; } else { memcpy(extra, priv->SSID, priv->SSID_size); extra[priv->SSID_size] = '\0'; dwrq->length = priv->SSID_size + 1; } dwrq->flags = !priv->connect_to_any_BSS; /* active */ return 0;}static int atmel_get_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra){ struct atmel_private *priv = dev->priv; memcpy(awrq->sa_data, priv->CurrentBSSID, 6); awrq->sa_family = ARPHRD_ETHER; return 0;}static int atmel_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct atmel_private *priv = dev->priv; /* Basic checking: do we have a key to set ? * Note : with the new API, it's impossible to get a NULL pointer. * Therefore, we need to check a key size == 0 instead. * New version of iwconfig properly set the IW_ENCODE_NOKEY flag * when no key is present (only change flags), but older versions * don't do it. - Jean II */ if (dwrq->length > 0) { int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; int current_index = priv->wep.default_key; /* Check the size of the key */ if (dwrq->length > 13) { return -EINVAL; } /* Check the index (none -> use current) */ if (index < 0 || index >= 4) index = current_index; else priv->wep.default_key = index; /* Set the length */ if (dwrq->length > 5) priv->wep_key_len[index] = 13; else if (dwrq->length > 0) priv->wep_key_len[index] = 5; else /* Disable the key */ priv->wep_key_len[index] = 0; /* Check if the key is not marked as invalid */ if(!(dwrq->flags & IW_ENCODE_NOKEY)) { /* Cleanup */ memset(priv->wep.wep_keys[index], 0, 13); /* Copy the key in the driver */ memcpy(priv->wep.wep_keys[index], extra, dwrq->length); } /* WE specify that if a valid key is set, encryption * should be enabled (user may turn it off later) * This is also how "iwconfig ethX key on" works */ if (index == current_index && priv->wep_key_len[index] > 0) { priv->wep.wep_is_on = 1; priv->wep.exclude_unencrypted = 1; if (priv->wep_key_len[index] > 5) priv->wep.encryption_level = 2; else priv->wep.encryption_level = 1; } } else { /* Do we want to just set the transmit key index ? */ int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; if ( index>=0 && index < 4 ) { priv->wep.default_key = index; } else /* Don't complain if only change the mode */ if(!dwrq->flags & IW_ENCODE_MODE) { return -EINVAL; } } /* Read the flags */ if(dwrq->flags & IW_ENCODE_DISABLED) { priv->wep.wep_is_on = 0; priv->wep.encryption_level = 0; } else { priv->wep.wep_is_on = 1; if (priv->wep_key_len[priv->wep.default_key] > 5) priv->wep.encryption_level = 2; else priv->wep.encryption_level = 1; } if(dwrq->flags & IW_ENCODE_RESTRICTED) priv->wep.exclude_unencrypted = 1; if(dwrq->flags & IW_ENCODE_OPEN) priv->wep.exclude_unencrypted = 0; return -EINPROGRESS; /* Call commit handler */}static int atmel_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct atmel_private *priv = dev->priv; int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; if (!priv->wep.wep_is_on) dwrq->flags = IW_ENCODE_DISABLED; else if (priv->wep.exclude_unencrypted) dwrq->flags = IW_ENCODE_RESTRICTED; else dwrq->flags = IW_ENCODE_OPEN; /* Which key do we want ? -1 -> tx index */ if (index < 0 || index >= 4) index = priv->wep.default_key; dwrq->flags |= index + 1; /* Copy the key to the user buffer */ dwrq->length = priv->wep_key_len[index]; if (dwrq->length > 16) { dwrq->length=0; } else { memset(extra, 0, 16); memcpy(extra, priv->wep.wep_keys[index], dwrq->length); } return 0;}static int atmel_get_name(struct net_device *dev, struct iw_request_info *info, char *cwrq, char *extra){ strcpy(cwrq, "IEEE 802.11-DS"); return 0;}static int atmel_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ struct atmel_private *priv = dev->priv; if (vwrq->fixed == 0) { priv->tx_rate = 3; priv->auto_tx_rate = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -