diff -uprN -X 'netdev-2.6.git#ieee80211/Documentation/dontdiff' netdev-2.6.git#ieee80211/drivers/net/wireless/atheros/atheros5212/keys.c netdev-atheros/drivers/net/wireless/atheros/atheros5212/keys.c --- netdev-2.6.git#ieee80211/drivers/net/wireless/atheros/atheros5212/keys.c 1970-01-01 01:00:00.000000000 +0100 +++ netdev-atheros/drivers/net/wireless/atheros/atheros5212/keys.c 2005-08-05 03:48:36.000000000 +0200 @@ -0,0 +1,268 @@ +/* + * All the work was created by reverse engineering and porting + * for interoperability. The creator is Mateusz Berezecki, + * unless explicitly marked ( some parts are derived + * from GPL'ed parts of madwifi project located at http://madwifi.sf.net) + * + * derived or copied parts of code licensed under + * dual GPL/BSD license + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * All rights reserved. + * + * rest of the code has been reversed by me and is under copyright too + * Copyright (C) 2005 Mateusz Berezecki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/netdevice.h> + +#include <net/ieee80211.h> + +#include <linux/wireless.h> +#include <net/iw_handler.h> + +#include "atheros_id.h" +#include "atheros_dev.h" +#include "atheros_defs.h" +//#include "atheros_devops.h" +//#include "atheros_regops.h" +#include "atheros_registers.h" +#include "atheros.h" + + +unsigned int ath_keycache_valid(struct net_device *netdev, + unsigned short entry) +{ + struct atheros_priv *pdata; + unsigned int val; + + pdata = ieee80211_priv(netdev); + + if (entry > pdata->max_keycache) + return 0; + + val = ath_reg_read(netdev, 0x8800 + entry * 32 + 28); + + if (val & 0x8000) + return 1; + + return 0; +} + +unsigned int ath_reset_keycache(struct net_device *netdev, + unsigned short entry) +{ + struct atheros_priv *pdata; + unsigned int keytype; + + pdata = ieee80211_priv(netdev); + + if (entry > pdata->keycache_size) + return 0; + + keytype = ath_reg_read(netdev, (entry * 32) + 0x8814); + + ath_reg_write(netdev, (entry * 32) + 0x8800, 0); + ath_reg_write(netdev, (entry * 32) + 0x8804, 0); + ath_reg_write(netdev, (entry * 32) + 0x8808, 0); + ath_reg_write(netdev, (entry * 32) + 0x880c, 0); + ath_reg_write(netdev, (entry * 32) + 0x8810, 0); + ath_reg_write(netdev, (entry * 32) + 0x8814, 7); + ath_reg_write(netdev, (entry * 32) + 0x8818, 0); + ath_reg_write(netdev, (entry * 32) + 0x881c, 0); + + if (keytype != 4) + return 1; + + if (!pdata->ext_keycache) + return 1; + + ath_reg_write(netdev, ((entry + 64) * 32) + 0x8800, 0); + ath_reg_write(netdev, ((entry + 64) * 32) + 0x8804, 0); + ath_reg_write(netdev, ((entry + 64) * 32) + 0x8808, 0); + ath_reg_write(netdev, ((entry + 64) * 32) + 0x880c, 0); + + return 1; +} + +unsigned int ath_set_keycache_entry_mac(struct net_device *netdev, + unsigned short entry, unsigned char *mac) +{ + struct atheros_priv *pdata; + unsigned int mac1, mac2; + + pdata = ieee80211_priv(netdev); + + if (entry > pdata->max_keycache) + return 0; + + if (mac == NULL) { + mac1 = 0; + mac2 = 0; + } else { + mac1 = mac[5] << 8; + mac1 |= mac[4]; + + mac2 = mac[3] << 24; + mac2 |= mac[2] << 16; + mac2 |= mac[1] << 8; + mac2 |= mac[0]; + + mac2 = mac2 >> 1; + mac2 |= ((mac1 & 1)<< 31); + + mac1 = mac1 >> 1; + } + + ath_reg_write(netdev, (entry * 32) + 0x8800 + 24, mac2); + ath_reg_write(netdev, (entry * 32) + 0x8800 + 28, mac1 | 0x80); + + return 1; +} + +unsigned int ath_set_keycache_entry(struct net_device *netdev, + unsigned short entry, struct keyval *kv, + unsigned char *mac, int num) +{ + int flg = (num == 1) ? 0xffffffff : 0; + int cipher_opt; + int newentry; + struct atheros_priv *pdata = ieee80211_priv(netdev); + unsigned int part1, part2, part3, part4, part5; + + + flg &= 0xaaaaaaaa; + + if (entry > pdata->max_keycache) + return 0; + + switch (kv->kv_type) { + case CIPHER_AES_OCB: + cipher_opt = 5; + break; + + case CIPHER_AES_CCM: + /* fixme TODO FIXME */ + return 0; +// break; + + case CIPHER_TKIP: + cipher_opt = 4; + + if ((entry + 0x40) > pdata->max_keycache) + return 0; + + break; + + case CIPHER_WEP: + if (kv->kv_len <= 4) + return 0; + + cipher_opt = 0; + + if (kv->kv_len <= 5) + break; + + cipher_opt = (kv->kv_len == 14) ? 0 : 0xffffffff; + cipher_opt &= 0xfffffffe; + cipher_opt += 3; + + break; + + case CIPHER_CLR: + cipher_opt = 7; + break; + + default: + return 0; + } + + part1 = (kv->kv_val[0] | (kv->kv_val[1] << 8) | + (kv->kv_val[2] << 16) | (kv->kv_val[3] << 24)) ^ flg; + + + part2 = ((kv->kv_val[4] | (kv->kv_val[5] << 8)) ^ flg) & 0xffff; + + part4 = ((kv->kv_val[6] | (kv->kv_val[7] << 8) | + (kv->kv_val[8] << 16) | (kv->kv_val[9] << 24)) ^ flg); + + part3 = ((kv->kv_val[10] | (kv->kv_val[11] << 8)) ^ flg) & 0xffff; + + part5 = (kv->kv_val[12] | (kv->kv_val[13] << 8) | + (kv->kv_val[14] << 16) | (kv->kv_val[15] << 24)) ^ flg; + + if (kv->kv_len <= 13) + part5 &= 0xff; + + + /* if statement needs fixing */ + if (cipher_opt == 4 && pdata->turbo != 0) { + newentry = (entry << 5); + + ath_reg_write(netdev, 0x8800 + (entry << 5), ~part1); + ath_reg_write(netdev, 0x8804 + newentry, ~part2); + ath_reg_write(netdev, 0x8808 + newentry, part4); + ath_reg_write(netdev, 0x880c + newentry, part3); + ath_reg_write(netdev, 0x8810 + newentry, part5); + ath_reg_write(netdev, 0x8814 + newentry, 4); + + ath_set_keycache_entry_mac(netdev, entry, mac); + + ath_reg_write(netdev, 0x8800 + ((entry + 0x40) << 5), + (kv->kv_mic[0] | (kv->kv_mic[1] << 8) | + (kv->kv_mic[2] << 16) | (kv->kv_mic[3] << 24))); + + ath_reg_write(netdev, 0x8804 + ((entry + 0x40) << 5), 0); + + ath_reg_write(netdev, 0x8808 + ((entry + 0x40) << 5), + ( kv->kv_mic[4] | (kv->kv_mic[5] << 8) | + (kv->kv_mic[6] << 16) | (kv->kv_mic[7] << 24) ) ); + + ath_reg_write(netdev, 0x880c + ((entry + 0x40) << 5), 0); + ath_reg_write(netdev, 0x8810 + ((entry + 0x40) << 5), 0); + ath_reg_write(netdev, 0x8814 + ((entry + 0x40) << 5), 7); + ath_reg_write(netdev, 0x8818 + ((entry + 0x40) << 5), 0); + ath_reg_write(netdev, 0x881c + ((entry + 0x40) << 5), 0); + + ath_reg_write(netdev, 0x8800 + newentry, part1); + ath_reg_write(netdev, 0x8800 + newentry, part2); + + return 1; + } else { + ath_reg_write(netdev, 0x8800 + (entry << 5), part1); + ath_reg_write(netdev, 0x8804 + (entry << 5), part2); + ath_reg_write(netdev, 0x8808 + (entry << 5), part4); + ath_reg_write(netdev, 0x880c + (entry << 5), part3); + ath_reg_write(netdev, 0x8810 + (entry << 5), part5); + ath_reg_write(netdev, 0x8814 + (entry << 5), cipher_opt); + + ath_set_keycache_entry_mac(netdev, entry, mac); + return 1; + } + + return 0; +} +unsigned int ath_get_keycache_size(struct net_device *netdev) +{ + return 128; +} + diff -uprN -X 'netdev-2.6.git#ieee80211/Documentation/dontdiff' netdev-2.6.git#ieee80211/drivers/net/wireless/atheros/atheros5212/mode_tables.c netdev-atheros/drivers/net/wireless/atheros/atheros5212/mode_tables.c --- netdev-2.6.git#ieee80211/drivers/net/wireless/atheros/atheros5212/mode_tables.c 1970-01-01 01:00:00.000000000 +0100 +++ netdev-atheros/drivers/net/wireless/atheros/atheros5212/mode_tables.c 2005-08-05 03:48:36.000000000 +0200 @@ -0,0 +1,309 @@ +/* + * All the work was created by reverse engineering and porting + * for interoperability. The creator is Mateusz Berezecki, + * unless explicitly marked ( some parts are derived + * from GPL'ed parts of madwifi project located at http://madwifi.sf.net) + * + * the original binary and source code created by + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * All rights reserved. + * + * rest of the code has been reversed by me and is under copyright too + * Copyright (C) 2005 Mateusz Berezecki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/version.h> +#include <linux/init.h> +#include <linux/delay.h> +#include <linux/pci.h> +#include <linux/netdevice.h> + +#include <net/ieee80211.h> + +#include <linux/wireless.h> +#include <net/iw_handler.h> + +#include "mode_tables.h" +#include "chans.h" +#include "atheros_defs.h" +#include "atheros.h" +#include "atheros_dev.h" + + +/* + * ripping it out from madwifi is ... @#*$&@#&@[EMAIL PROTECTED] HARD!!! + */ + +struct rate_table mode_a = { + .rate_count = 8, + .code_to_idx = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + .info[0] = { /* 6 MB */ + .valid = 1, + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 6000, + .rateCode = 11, + .shortPreamble = 0, + .dot11Rate = (12 | 0x80), + .controlRate = 0, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[1] = { /* 9 MB */ + .valid = 1, + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 9000, + .rateCode = 15, + .shortPreamble = 0, + .dot11Rate = 18, + .controlRate = 0, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[2] = { /* 12 MB */ + .valid = 1, + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 12000, + .rateCode = 10, + .shortPreamble = 0, + .dot11Rate = (0x80|24), + .controlRate = 2, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[3] = { /* 18 MB */ + .valid = 1, + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 18000, + .rateCode = 14, + .shortPreamble = 0, + .dot11Rate = 36, + .controlRate = 2, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[4] = { /* 24 MB */ + .valid = 1, + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 24000, + .rateCode = 9, + .shortPreamble = 0, + .dot11Rate = (0x80|48), + .controlRate = 4, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[5] = { /* 36 MB */ + .valid = 1, + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 36000, + .rateCode = 13, + .shortPreamble = 0, + .dot11Rate = 72, + .controlRate = 4, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[6] = { /* 48 MB */ + .valid = 1, + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 48000, + .rateCode = 8, + .shortPreamble = 0, + .dot11Rate = 96, + .controlRate = 4, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[7] = { + .valid = 1, /* 54 MB */ + .phy = IEEE80211_OFDM_MODULATION, + .rateKbps = 54000, + .rateCode = 12, + .shortPreamble = 0, + .dot11Rate = 108, + .controlRate = 4, + .lpAckDuration = 0, + .spAckDuration = 0, + }, +}; + +struct rate_table mode_b = { + .rate_count = 4, /* +0 */ + .code_to_idx = { /* +4 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + .info[0] = { /* +32 */ + .valid = 1, /* 0 - 1 */ + .phy = 0, /* 1 - 2 */ + .rateKbps = 1000, /* 2 - 4 */ + .rateCode = 27, /* 4 - 5 */ + .shortPreamble = 0, /* 5 - 6 */ /* 12 bytes */ + .dot11Rate = 130, /* 6 - 7 */ + .controlRate = 0, /* 7 - 8 */ + .lpAckDuration = 0, /* 8 - 10 */ + .spAckDuration = 0, /* 10 - 12 */ + }, + .info[1] = { + .valid = 1, + .phy = 0, + .rateKbps = 2000, /* 2 MBps */ + .rateCode = 26, + .shortPreamble = 4, + .dot11Rate = 132, + .controlRate = 1, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[2] = { + .valid = 1, + .phy = 0, + .rateKbps = 5500, /* 5.5 MBps */ + .rateCode = 25, + .shortPreamble = 4, + .dot11Rate = 139, + .controlRate = 1, + .lpAckDuration = 0, + .spAckDuration = 0, + }, + .info[3] = { + .valid = 1, + .phy = 0, + .rateKbps = 11000, /* 11 MBps */ + .rateCode = 24, + .shortPreamble = 4, + .dot11Rate = 150, + .controlRate = 1, + .lpAckDuration = 0, + .spAckDuration = 0 + }, +}; + + +struct rate_table mode_g = { + .rate_count = 12, + .code_to_idx = { 0 }, + .info[0] = { 1, IEEE80211_CCK_MODULATION, 1000, 0x1b, 0, 2, 0 }, + .info[1] = { 1, IEEE80211_CCK_MODULATION, 2000, 0x1a, 4, 4, 1 }, + .info[2] = { 1, IEEE80211_CCK_MODULATION, 5500, 0x19, 4, 11, 1 }, + .info[3] = { 1, IEEE80211_CCK_MODULATION, 11000, 0x18, 4, 22, 1 }, + .info[4] = { 0, IEEE80211_OFDM_MODULATION, 6000, 0x0b, 0, 12, 4 }, + .info[5] = { 0, IEEE80211_OFDM_MODULATION, 9000, 0x0f, 0, 18, 4 }, + .info[6] = { 1, IEEE80211_OFDM_MODULATION, 12000, 0x0a, 0, 24, 6 }, + .info[7] = { 1, IEEE80211_OFDM_MODULATION, 18000, 0x0e, 0, 36, 6 }, + .info[8] = { 1, IEEE80211_OFDM_MODULATION, 24000, 0x09, 0, 48, 8 }, + .info[9] = { 1, IEEE80211_OFDM_MODULATION, 36000, 0x0d, 0, 72, 8 }, + .info[10] = { 1, IEEE80211_OFDM_MODULATION, 48000, 0x08, 0, 96, 8 }, + .info[11] = { 1, IEEE80211_OFDM_MODULATION, 54000, 0x0c, 0,108, 8 }, +}; + + +/* TODO: add Atheros eXtended Range rate table and also turbo g rates */ + + +struct rate_table *ath_get_rates(struct net_device *netdev, unsigned int mode) +{ + struct rate_table *rates = NULL; + + switch (mode) { + case MODE_11A: + rates = &mode_a; + break; + case MODE_11B: + rates = &mode_b; + break; + case MODE_11G: + rates = &mode_g; + + default: + printk(KERN_DEBUG"atheros: unsupported rate\n"); + return NULL; + } + + ath_setup_rates(netdev, rates); + return rates; +} + +void ath_setup_rates(struct net_device *netdev,struct rate_table *r) +{ + int i; + + if (r->code_to_idx[0] != 0) + return; + + for (i = 0; i < 32; i++) + r->code_to_idx[i] = 0xff; + + for (i = 0; i < r->rate_count; i++) { + unsigned char code = r->info[i].rateCode; + r->code_to_idx[code] = i; + r->code_to_idx[code | r->info[i].shortPreamble] = i; + } +} + +int ath_rate_setup(struct net_device *netdev, unsigned int mode) +{ + struct atheros_priv *p = ieee80211_priv(netdev); + struct rate_table *rt; + int i, maxrates; + + switch (mode) { + case MODE_11A: + p->rates[mode] = ath_get_rates(netdev, MODE_11A); + break; + case MODE_11B: + printk(KERN_DEBUG"MODE 802.11B\n"); + p->rates[mode] = ath_get_rates(netdev, MODE_11B); + break; + + case MODE_11G: + p->rates[mode] = ath_get_rates(netdev, MODE_11G); + break; + /* + case IEEE80211_MODE_TURBO_A: + p->rates[mode] = ath_getratetable(netdev, HAL_MODE_TURBO); + break; + case IEEE80211_MODE_TURBO_G: + p->rates[mode] = ath_getratetable(netdev, HAL_MODE_108G); + break; */ + default: + return 0; + } + rt = p->rates[mode]; + + if (rt == NULL) + return 0; + + if (rt->rate_count > IEEE80211_RATE_MAXSIZE) { + maxrates = IEEE80211_RATE_MAXSIZE; + } else + maxrates = rt->rate_count; + /* + rs = &ic->ic_sup_rates[mode]; + for (i = 0; i < maxrates; i++) + rs->rs_rates[i] = rt->info[i].dot11Rate; + rs->rs_nrates = maxrates; + */ + return 1; +} + diff -uprN -X 'netdev-2.6.git#ieee80211/Documentation/dontdiff' netdev-2.6.git#ieee80211/drivers/net/wireless/atheros/atheros5212/mode_tables.h netdev-atheros/drivers/net/wireless/atheros/atheros5212/mode_tables.h --- netdev-2.6.git#ieee80211/drivers/net/wireless/atheros/atheros5212/mode_tables.h 1970-01-01 01:00:00.000000000 +0100 +++ netdev-atheros/drivers/net/wireless/atheros/atheros5212/mode_tables.h 2005-08-05 03:48:36.000000000 +0200 @@ -0,0 +1,60 @@ +/* + * All the work was created by reverse engineering and porting + * for interoperability. The creator is Mateusz Berezecki, + * unless explicitly marked ( some parts are derived + * from GPL'ed parts of madwifi project located at http://madwifi.sf.net) + * + * derived or copied parts of code licensed under + * dual GPL/BSD license + * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting + * All rights reserved. + * + * rest of the code has been reversed by me and is under copyright too + * Copyright (C) 2005 Mateusz Berezecki + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + + +#ifndef _MODE_TABLES_H +#define _MODE_TABLES_H + +struct rate_info { + unsigned char valid; + unsigned char phy; + unsigned short rateKbps; + unsigned char rateCode; + unsigned char shortPreamble; + unsigned char dot11Rate; + unsigned char controlRate; + unsigned short lpAckDuration; + unsigned short spAckDuration; +}; + +struct rate_table { + int rate_count; + unsigned char code_to_idx[32]; /* back mapping */ + struct rate_info info[32]; +}; + +extern struct rate_table mode_a; +extern struct rate_table mode_b; + +void ath_setup_rates(struct net_device *,struct rate_table *); +struct rate_table *ath_get_rates(struct net_device *, unsigned int); +int ath_rate_setup(struct net_device *, unsigned int); +#endif + +