netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] acxsm: merge from acx 0.3.32
@ 2006-02-03 12:14 Denis Vlasenko
  2006-02-07 15:41 ` Denis Vlasenko
  0 siblings, 1 reply; 3+ messages in thread
From: Denis Vlasenko @ 2006-02-03 12:14 UTC (permalink / raw)
  To: John W. Linville; +Cc: netdev, acx100-devel

[-- Attachment #1: Type: text/plain, Size: 298 bytes --]

Standalone acx driver had several fixes since
acxsm fork, this patch merges them:
- initial support for new TNETW1450 USB chip
- support for firmware 2.3.1.31

Also we had one report that acxsm is actually working.
That's quite unexpected.

Signed-off-by: Denis Vlasenko <vda@ilport.com.ua>
--
vda

[-- Attachment #2: acx.diff --]
[-- Type: text/x-diff, Size: 60797 bytes --]

diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/Changelog wireless-2.6.git.acx/drivers/net/wireless/tiacx/Changelog
--- wireless-2.6.git/drivers/net/wireless/tiacx/Changelog	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/Changelog	Fri Feb  3 13:38:12 2006
@@ -70,6 +70,12 @@ TODO: from Efthym <efthym@gmx.net>:
 13:13:32 wlan0: tx error 0x20, buf 05!
 13:13:32 wlan0: tx error 0x20, buf 06!
 
+[20060203] 0.4.3
+* merge from acx 0.3.32
+
+[20060123] 0.4.2
+* conv.c removed
+
 [20060117] 0.4.1
 * Lots of code commented out
 
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/acx_config.h wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_config.h
--- wireless-2.6.git/drivers/net/wireless/tiacx/acx_config.h	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_config.h	Fri Feb  3 13:38:12 2006
@@ -1,10 +1,10 @@
-#define ACX_RELEASE "v0.4.2"
+#define ACX_RELEASE "v0.4.3"
 
 /* set to 0 if you don't want any debugging code to be compiled in */
 /* set to 1 if you want some debugging */
 /* set to 2 if you want extensive debug log */
 #define ACX_DEBUG 2
-#define ACX_DEFAULT_MSG 0
+#define ACX_DEFAULT_MSG (L_ASSOC|L_INIT)
 
 /* assume 32bit I/O width
  * (16bit is also compatible with Compact Flash) */
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/acx_func.h wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_func.h
--- wireless-2.6.git/drivers/net/wireless/tiacx/acx_func.h	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_func.h	Fri Feb  3 13:38:12 2006
@@ -565,14 +565,7 @@ acx_l_tx_data(acx_device_t *adev, tx_t *
 static inline wlan_hdr_t*
 acx_get_wlan_hdr(acx_device_t *adev, const rxbuffer_t *rxbuf)
 {
-	if (!(adev->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR))
-		return (wlan_hdr_t*)&rxbuf->hdr_a3;
-
-	/* take into account phy header in front of packet */
-	if (IS_ACX111(adev))
-		return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 8);
-
-	return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + 4);
+	return (wlan_hdr_t*)((u8*)&rxbuf->hdr_a3 + adev->phy_header_len);
 }
 
 void acxpci_l_power_led(acx_device_t *adev, int enable);
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/acx_struct.h wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_struct.h
--- wireless-2.6.git/drivers/net/wireless/tiacx/acx_struct.h	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/acx_struct.h	Fri Feb  3 13:38:12 2006
@@ -105,6 +105,10 @@ enum { acx_debug = 0 };
 #define DEVTYPE_PCI		0
 #define DEVTYPE_USB		1
 
+#if !defined(CONFIG_ACX_PCI) && !defined(CONFIG_ACX_USB)
+#error Driver must include PCI and/or USB support. You selected neither.
+#endif
+
 #if defined(CONFIG_ACX_PCI)
  #if !defined(CONFIG_ACX_USB)
   #define IS_PCI(adev)	1
@@ -148,6 +152,7 @@ enum { acx_debug = 0 };
 #define RADIO_UNKNOWN_17	0x17
 /* FwRad19.bin was found in a Safecom driver; must be an ACX111 radio: */
 #define RADIO_UNKNOWN_19	0x19
+#define RADIO_UNKNOWN_1B	0x1b    /* radio in SafeCom SWLUT-54125 USB adapter; entirely unknown!! */
 
 /* Controller Commands */
 /* can be found in table cmdTable in firmware "Rev. 1.5.0" (FW150) */
@@ -174,13 +179,18 @@ enum { acx_debug = 0 };
 #define ACX1xx_CMD_WAKE			0x10
 #define ACX1xx_CMD_UNKNOWN_11		0x11	/* mapped to unknownCMD in FW150 */
 #define ACX100_CMD_INIT_MEMORY		0x12
+#define ACX1FF_CMD_DISABLE_RADIO	0x12	/* new firmware? TNETW1450? */
 #define ACX1xx_CMD_CONFIG_BEACON	0x13
 #define ACX1xx_CMD_CONFIG_PROBE_RESPONSE	0x14
 #define ACX1xx_CMD_CONFIG_NULL_DATA	0x15
 #define ACX1xx_CMD_CONFIG_PROBE_REQUEST	0x16
-#define ACX1xx_CMD_TEST			0x17
+#define ACX1xx_CMD_FCC_TEST		0x17
 #define ACX1xx_CMD_RADIOINIT		0x18
 #define ACX111_CMD_RADIOCALIB		0x19
+#define ACX1FF_CMD_NOISE_HISTOGRAM	0x1c /* new firmware? TNETW1450? */
+#define ACX1FF_CMD_RX_RESET		0x1d /* new firmware? TNETW1450? */
+#define ACX1FF_CMD_LNA_CONTROL		0x20 /* new firmware? TNETW1450? */
+#define ACX1FF_CMD_CONTROL_DBG_TRACE	0x21 /* new firmware? TNETW1450? */
 
 /* 'After Interrupt' Commands */
 #define ACX_AFTER_IRQ_CMD_STOP_SCAN	0x01
@@ -229,18 +239,22 @@ enum { acx_debug = 0 };
 /* these are handled by real_cfgtable in firmware "Rev 1.5.0" (FW150) */
 DEF_IE(1xx_IE_UNKNOWN_00		,0x0000, -1);	/* mapped to cfgInvalid in FW150 */
 DEF_IE(100_IE_ACX_TIMER			,0x0001, 0x10);
-DEF_IE(1xx_IE_POWER_MGMT		,0x0002, 0x06);
+DEF_IE(1xx_IE_POWER_MGMT		,0x0002, 0x06); /* TNETW1450: length 0x18!! */
 DEF_IE(1xx_IE_QUEUE_CONFIG		,0x0003, 0x1c);
 DEF_IE(100_IE_BLOCK_SIZE		,0x0004, 0x02);
+DEF_IE(1FF_IE_SLOT_TIME			,0x0004, 0x08); /* later firmware versions only? */
 DEF_IE(1xx_IE_MEMORY_CONFIG_OPTIONS	,0x0005, 0x14);
-DEF_IE(1xx_IE_RATE_FALLBACK		,0x0006, 0x01);
+DEF_IE(1FF_IE_QUEUE_HEAD		,0x0005, 0x14 /* FIXME: length? */);
+DEF_IE(1xx_IE_RATE_FALLBACK		,0x0006, 0x01); /* TNETW1450: length 2 */
 DEF_IE(100_IE_WEP_OPTIONS		,0x0007, 0x03);
 DEF_IE(111_IE_RADIO_BAND		,0x0007, -1);
-DEF_IE(1xx_IE_MEMORY_MAP		,0x0008, 0x28); /* huh? */
+DEF_IE(1FF_IE_TIMING_CFG		,0x0007, -1);	/* later firmware versions; TNETW1450 only? */
 DEF_IE(100_IE_SSID			,0x0008, 0x20); /* huh? */
+DEF_IE(1xx_IE_MEMORY_MAP		,0x0008, 0x28); /* huh? TNETW1450 has length 0x40!! */
 DEF_IE(1xx_IE_SCAN_STATUS		,0x0009, 0x04); /* mapped to cfgInvalid in FW150 */
 DEF_IE(1xx_IE_ASSOC_ID			,0x000a, 0x02);
 DEF_IE(1xx_IE_UNKNOWN_0B		,0x000b, -1);	/* mapped to cfgInvalid in FW150 */
+DEF_IE(1FF_IE_TX_POWER_LEVEL_TABLE	,0x000b, 0x18); /* later firmware versions; TNETW1450 only? */
 DEF_IE(100_IE_UNKNOWN_0C		,0x000c, -1);	/* very small implementation in FW150! */
 /* ACX100 has an equivalent struct in the cmd mailbox directly after reset.
  * 0x14c seems extremely large, will trash stack on failure (memset!)
@@ -253,30 +267,47 @@ DEF_IE(1xx_IE_RXCONFIG			,0x0010, 0x04);
 DEF_IE(100_IE_UNKNOWN_11		,0x0011, -1);	/* NONBINARY: large implementation in FW150! link quality readings or so? */
 DEF_IE(111_IE_QUEUE_THRESH		,0x0011, -1);
 DEF_IE(100_IE_UNKNOWN_12		,0x0012, -1);	/* NONBINARY: VERY large implementation in FW150!! */
-DEF_IE(111_IE_BSS_POWER_SAVE		,0x0012, -1);
-DEF_IE(1xx_IE_FIRMWARE_STATISTICS	,0x0013, 0x9c);
+DEF_IE(111_IE_BSS_POWER_SAVE		,0x0012, /* -1 */ 2);
+DEF_IE(1xx_IE_FIRMWARE_STATISTICS	,0x0013, 0x9c); /* TNETW1450: length 0x134!! */
+DEF_IE(1FF_IE_RX_INTR_CONFIG		,0x0014, 0x14); /* later firmware versions, TNETW1450 only? */
 DEF_IE(1xx_IE_FEATURE_CONFIG		,0x0015, 0x08);
 DEF_IE(111_IE_KEY_CHOOSE		,0x0016, 0x04);	/* for rekeying. really len=4?? */
+DEF_IE(1FF_IE_MISC_CONFIG_TABLE		,0x0017, 0x04); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_WONE_CONFIG		,0x0018, -1);	/* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_TID_CONFIG		,0x001a, 0x2c); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_CALIB_ASSESSMENT		,0x001e, 0x04); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_BEACON_FILTER_OPTIONS	,0x001f, 0x02); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_LOW_RSSI_THRESH_OPT	,0x0020, 0x04); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_NOISE_HISTOGRAM_RESULTS	,0x0021, 0x30); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_PACKET_DETECT_THRESH	,0x0023, 0x04); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_TX_CONFIG_OPTIONS		,0x0024, 0x04); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_CCA_THRESHOLD		,0x0025, 0x02); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_EVENT_MASK		,0x0026, 0x08); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_DTIM_PERIOD		,0x0027, 0x02); /* later firmware versions, TNETW1450 only? */
+DEF_IE(1FF_IE_ACI_CONFIG_SET		,0x0029, 0x06); /* later firmware versions; maybe TNETW1450 only? */
+DEF_IE(1FF_IE_EEPROM_VER		,0x0030, 0x04); /* later firmware versions; maybe TNETW1450 only? */
 DEF_IE(1xx_IE_DOT11_STATION_ID		,0x1001, 0x06);
 DEF_IE(100_IE_DOT11_UNKNOWN_1002	,0x1002, -1);	/* mapped to cfgInvalid in FW150 */
-DEF_IE(111_IE_DOT11_FRAG_THRESH		,0x1002, -1);	/* mapped to cfgInvalid in FW150 */
+DEF_IE(111_IE_DOT11_FRAG_THRESH		,0x1002, -1);	/* mapped to cfgInvalid in FW150; TNETW1450 has length 2!! */
 DEF_IE(100_IE_DOT11_BEACON_PERIOD	,0x1003, 0x02);	/* mapped to cfgInvalid in FW150 */
 DEF_IE(1xx_IE_DOT11_DTIM_PERIOD		,0x1004, -1);	/* mapped to cfgInvalid in FW150 */
-DEF_IE(1xx_IE_DOT11_SHORT_RETRY_LIMIT	,0x1005, 0x01);
-DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT	,0x1006, 0x01);
-DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE	,0x1007, 0x20);	/* configure default keys */
+DEF_IE(1FF_IE_DOT11_MAX_RX_LIFETIME	,0x1004, -1);	/* later firmware versions; maybe TNETW1450 only? */
+DEF_IE(1xx_IE_DOT11_SHORT_RETRY_LIMIT	,0x1005, 0x01); /* TNETW1450: length 2 */
+DEF_IE(1xx_IE_DOT11_LONG_RETRY_LIMIT	,0x1006, 0x01); /* TNETW1450: length 2 */
+DEF_IE(100_IE_DOT11_WEP_DEFAULT_KEY_WRITE	,0x1007, 0x20);	/* configure default keys; TNETW1450 has length 0x24!! */
 DEF_IE(1xx_IE_DOT11_MAX_XMIT_MSDU_LIFETIME	,0x1008, 0x04);
 DEF_IE(1xx_IE_DOT11_GROUP_ADDR		,0x1009, -1);
 DEF_IE(1xx_IE_DOT11_CURRENT_REG_DOMAIN	,0x100a, 0x02);
 //It's harmless to have larger struct. Use USB case always.
 DEF_IE(1xx_IE_DOT11_CURRENT_ANTENNA	,0x100b, 0x02);	/* in fact len=1 for PCI */
 DEF_IE(1xx_IE_DOT11_UNKNOWN_100C	,0x100c, -1);	/* mapped to cfgInvalid in FW150 */
-DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL	,0x100d, 0x01);
+DEF_IE(1xx_IE_DOT11_TX_POWER_LEVEL	,0x100d, 0x01); /* TNETW1450 has length 2!! */
 DEF_IE(1xx_IE_DOT11_CURRENT_CCA_MODE	,0x100e, 0x02);	/* in fact len=1 for PCI */
 //USB doesn't return anything - len==0?!
 DEF_IE(100_IE_DOT11_ED_THRESHOLD	,0x100f, 0x04);
-DEF_IE(1xx_IE_DOT11_WEP_DEFAULT_KEY_SET	,0x1010, 0x01);	/* set default key ID */
+DEF_IE(1xx_IE_DOT11_WEP_DEFAULT_KEY_SET	,0x1010, 0x01);	/* set default key ID; TNETW1450: length 2 */
 DEF_IE(100_IE_DOT11_UNKNOWN_1011	,0x1011, -1);	/* mapped to cfgInvalid in FW150 */
+DEF_IE(1FF_IE_DOT11_CURR_5GHZ_REGDOM	,0x1011, -1);	/* later firmware versions; maybe TNETW1450 only? */
 DEF_IE(100_IE_DOT11_UNKNOWN_1012	,0x1012, -1);	/* mapped to cfgInvalid in FW150 */
 DEF_IE(100_IE_DOT11_UNKNOWN_1013	,0x1013, -1);	/* mapped to cfgInvalid in FW150 */
 
@@ -479,15 +510,15 @@ typedef struct phy_hdr {
  * Some seem to have different meanings... */
 
 #define RXBUF_HDRSIZE 12
-#define PHY_HDR(rxbuf) ((phy_hdr_t*)&rxbuf->hdr_a3)
-#define RXBUF_BYTES_RCVD(rxbuf) (le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff)
+#define RXBUF_BYTES_RCVD(adev, rxbuf) \
+		((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) - (adev)->phy_header_len)
 #define RXBUF_BYTES_USED(rxbuf) \
-		((le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE)
+		((le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0xfff) + RXBUF_HDRSIZE)
 /* USBism */
-#define RXBUF_IS_TXSTAT(rxbuf) (le16_to_cpu(rxbuf->mac_cnt_rcvd) & 0x8000)
+#define RXBUF_IS_TXSTAT(rxbuf) (le16_to_cpu((rxbuf)->mac_cnt_rcvd) & 0x8000)
 /*
 mac_cnt_rcvd:
-    12 bits: length of frame from control field to last byte of FCS
+    12 bits: length of frame from control field to first byte of FCS
     3 bits: reserved
     1 bit: 1 = it's a tx status info, not a rx packet (USB only)
 
@@ -603,31 +634,6 @@ typedef struct fw_ver {
 
 #define FW_ID_SIZE 20
 
-
-/*--- WEP stuff --------------------------------------------------------------*/
-#define DOT11_MAX_DEFAULT_WEP_KEYS	4
-
-/* non-firmware struct, no packing necessary */
-typedef struct wep_key {
-	size_t	size; /* most often used member first */
-	u8	index;
-	u8	key[29];
-	u16	strange_filler;
-} wep_key_t;			/* size = 264 bytes (33*8) */
-/* FIXME: We don't have size 264! Or is there 2 bytes beyond the key
- * (strange_filler)? */
-
-/* non-firmware struct, no packing necessary */
-typedef struct key_struct {
-	u8	addr[ETH_ALEN];	/* 0x00 */
-	u16	filler1;	/* 0x06 */
-	u32	filler2;	/* 0x08 */
-	u32	index;		/* 0x0c */
-	u16	len;		/* 0x10 */
-	u8	key[29];	/* 0x12; is this long enough??? */
-} key_struct_t;			/* size = 276. FIXME: where is the remaining space?? */
-
-
 /*--- Client (peer) info -----------------------------------------------------*/
 /* adev->sta_list[] is used for:
 ** accumulating and processing of scan results
@@ -1108,6 +1114,9 @@ struct acx_device {
 	/* most frequent accesses first (dereferencing and cache line!) */
 
 	/*** Locking ***/
+	/* FIXME: try to convert semaphore to more efficient mutex according
+	   to Ingo Molnar's docs (but not before driver is in mainline or
+		 pre-mutex Linux 2.6.10 is very outdated). */
 	struct semaphore	sem;
 	spinlock_t		lock;
 #if defined(PARANOID_LOCKING) /* Lock debugging */
@@ -1286,14 +1295,6 @@ struct acx_device {
 	u8		rate_supported_len;
 	u8		rate_supported[13];
 
-	/*** Encryption settings (WEP) ***/
-	u32		auth_alg;		/* used in transmit_authen1 */
-	u8		wep_enabled;
-	u8		wep_restricted;
-	u8		wep_current_index;
-	wep_key_t	wep_keys[DOT11_MAX_DEFAULT_WEP_KEYS];	/* the default WEP keys */
-	key_struct_t	wep_key_struct[10];
-
 	/*** Unknown ***/
 	u8		dtim_interval;
 
@@ -1303,6 +1304,7 @@ struct acx_device {
 	u16		memblocksize;
 	unsigned int	tx_free;
 	unsigned int	tx_head; /* keep as close as possible to Tx stuff below (cache line) */
+	u16		phy_header_len;
 
 /*************************************************************************
  *** PCI/USB/... must be last or else hw agnostic code breaks horribly ***
@@ -1380,9 +1382,10 @@ struct acx_device {
 static inline acx_device_t*
 ndev2adev(struct net_device *ndev)
 {
-        return ieee80211softmac_priv(ndev);
+	return ieee80211softmac_priv(ndev);
 }
 
+
 /* For use with ACX1xx_IE_RXCONFIG */
 /*  bit     description
  *    13   include additional header (length etc.) *required*
@@ -1852,7 +1855,7 @@ typedef struct acx_joinbss {
 */
 typedef struct mem_read_write {
 	u16	addr ACX_PACKED;
-	u16	type ACX_PACKED; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg. */
+	u16	type ACX_PACKED; /* 0x0 int. RAM / 0xffff MAC reg. / 0x81 PHY RAM / 0x82 PHY reg.; or maybe it's actually 0x30 for MAC? Better verify it by writing and reading back and checking whether the value holds! */
 	u32	len ACX_PACKED;
 	u32	data ACX_PACKED;
 } mem_read_write_t;
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/common.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/common.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/common.c	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/common.c	Fri Feb  3 13:38:12 2006
@@ -631,13 +631,6 @@ acx_s_get_firmware_version(acx_device_t 
 			printk("acx: firmware '%s' is known to be buggy, "
 				"please upgrade\n", adev->firmware_version);
 		}
-		if (adev->firmware_numver == 0x02030131) {
-			/* With this one, all rx packets look mangled
-			** Most probably we simply do not know how to use it
-			** properly */
-			printk("acx: firmware '%s' does not work well "
-				"with this driver\n", adev->firmware_version);
-		}
 	}
 
 	adev->firmware_id = le32_to_cpu(fw.hw_id);
@@ -655,6 +648,9 @@ acx_s_get_firmware_version(acx_device_t 
 		case 0x03010000:
 			adev->chip_name = "TNETW1130";
 			break;
+		case 0x04030000: /* 0x04030101 is TNETW1450 */
+			adev->chip_name = "TNETW1450";
+			break;
 		default:
 			printk("acx: unknown chip ID 0x%08X, "
 				"please report\n", adev->firmware_id);
@@ -679,9 +675,6 @@ acx_display_hardware_details(acx_device_
 
 	switch (adev->radio_type) {
 	case RADIO_MAXIM_0D:
-		/* hmm, the DWL-650+ seems to have two variants,
-		 * according to a windows driver changelog comment:
-		 * RFMD and Maxim. */
 		radio_str = "Maxim";
 		break;
 	case RADIO_RFMD_11:
@@ -701,8 +694,11 @@ acx_display_hardware_details(acx_device_
 	case RADIO_UNKNOWN_19:
 		radio_str = "A radio used by Safecom cards?! Please report";
 		break;
+	case RADIO_UNKNOWN_1B:
+		radio_str = "An unknown radio used by TNETW1450 USB adapters";
+		break;
 	default:
-		radio_str = "UNKNOWN, please report the radio type name!";
+		radio_str = "UNKNOWN, please report radio type name!";
 		break;
 	}
 
@@ -861,6 +857,32 @@ acx100_ie_len[] = {
 	0,
 	ACX1xx_IE_FEATURE_CONFIG_LEN,
 	ACX111_IE_KEY_CHOOSE_LEN,
+	ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
+	ACX1FF_IE_WONE_CONFIG_LEN,
+	0,
+	ACX1FF_IE_TID_CONFIG_LEN,
+	0,
+	0,
+	0,
+	ACX1FF_IE_CALIB_ASSESSMENT_LEN,
+	ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
+	ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
+	ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
+	0,
+	ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
+	ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
+	ACX1FF_IE_CCA_THRESHOLD_LEN,
+	ACX1FF_IE_EVENT_MASK_LEN,
+	ACX1FF_IE_DTIM_PERIOD_LEN,
+	0,
+	ACX1FF_IE_ACI_CONFIG_SET_LEN,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	ACX1FF_IE_EEPROM_VER_LEN,
 };
 
 static const u16
@@ -912,6 +934,32 @@ acx111_ie_len[] = {
 	0,
 	ACX1xx_IE_FEATURE_CONFIG_LEN,
 	ACX111_IE_KEY_CHOOSE_LEN,
+	ACX1FF_IE_MISC_CONFIG_TABLE_LEN,
+	ACX1FF_IE_WONE_CONFIG_LEN,
+	0,
+	ACX1FF_IE_TID_CONFIG_LEN,
+	0,
+	0,
+	0,
+	ACX1FF_IE_CALIB_ASSESSMENT_LEN,
+	ACX1FF_IE_BEACON_FILTER_OPTIONS_LEN,
+	ACX1FF_IE_LOW_RSSI_THRESH_OPT_LEN,
+	ACX1FF_IE_NOISE_HISTOGRAM_RESULTS_LEN,
+	0,
+	ACX1FF_IE_PACKET_DETECT_THRESH_LEN,
+	ACX1FF_IE_TX_CONFIG_OPTIONS_LEN,
+	ACX1FF_IE_CCA_THRESHOLD_LEN,
+	ACX1FF_IE_EVENT_MASK_LEN,
+	ACX1FF_IE_DTIM_PERIOD_LEN,
+	0,
+	ACX1FF_IE_ACI_CONFIG_SET_LEN,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	ACX1FF_IE_EEPROM_VER_LEN,
 };
 
 static const u16
@@ -992,6 +1040,8 @@ acx_s_interrogate_debug(acx_device_t *ad
 	u16 len;
 	int res;
 
+	/* FIXME: no check whether this exceeds the array yet.
+	 * We should probably remember the number of entries... */
 	if (type < 0x1000)
 		len = adev->ie_len[type];
 	else
@@ -1137,8 +1187,8 @@ acx_s_proc_diag_output(char *buf, acx_de
 		"WEP ena %d, restricted %d, idx %d\n",
 		adev->essid, adev->essid_active, (int)adev->essid_len,
 		adev->essid_for_assoc, adev->nick,
-		adev->wep_enabled, adev->wep_restricted,
-		adev->wep_current_index);
+		adev->ieee->sec.enabled, adev->ieee->sec.auth_mode,
+		adev->ieee->sec.active_key);
 	p += sprintf(p, "dev_addr  "MACSTR"\n", MAC(adev->dev_addr));
 	p += sprintf(p, "bssid     "MACSTR"\n", MAC(adev->bssid));
 	p += sprintf(p, "ap_filter "MACSTR"\n", MAC(adev->ap));
@@ -2087,6 +2137,12 @@ acx_s_initialize_rx_config(acx_device_t 
 	}
 	adev->rx_config_1 |= RX_CFG1_INCLUDE_RXBUF_HDR;
 
+	if ((adev->rx_config_1 & RX_CFG1_INCLUDE_PHY_HDR)
+	 || (adev->firmware_numver >= 0x02000000))
+		adev->phy_header_len = IS_ACX111(adev) ? 8 : 4;
+	else
+		adev->phy_header_len = 0;
+
 	log(L_INIT, "setting RXconfig to %04X:%04X\n",
 			adev->rx_config_1, adev->rx_config_2);
 	cfg.rx_cfg1 = cpu_to_le16(adev->rx_config_1);
@@ -2105,6 +2161,19 @@ acx_s_set_defaults(acx_device_t *adev)
 
 	FN_ENTER;
 
+	/* do it before getting settings, prevent bogus channel 0 warning */
+	adev->channel = 1;
+
+	/* query some settings from the card.
+	 * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
+	 * query is REQUIRED, otherwise the card won't work correctly! */
+	adev->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
+	/* Only ACX100 supports ED and CCA */
+	if (IS_ACX100(adev))
+		adev->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
+
+	acx_s_update_card_settings(adev);
+
 	acx_lock(adev, flags);
 
 	/* set our global interrupt mask */
@@ -2115,8 +2184,11 @@ acx_s_set_defaults(acx_device_t *adev)
 	adev->brange_max_quality = 60; /* LED blink max quality is 60 */
 	adev->brange_time_last_state_change = jiffies;
 
+	/* copy the MAC address we just got from the card
+	 * into our MAC address used during current 802.11 session */
 	MAC_COPY(adev->dev_addr, adev->ndev->dev_addr);
 	MAC_BCAST(adev->ap);
+
 	adev->essid_len =
 		snprintf(adev->essid, sizeof(adev->essid), "STA%02X%02X%02X",
 			adev->dev_addr[3], adev->dev_addr[4], adev->dev_addr[5]);
@@ -2131,23 +2203,19 @@ acx_s_set_defaults(acx_device_t *adev)
 		adev->reg_dom_id = adev->cfgopt_domains.list[0];
 	}
 
-	adev->channel = 1;
 	/* 0xffff would be better, but then we won't get a "scan complete"
 	 * interrupt, so our current infrastructure will fail: */
 	adev->scan_count = 1;
 	adev->scan_mode = ACX_SCAN_OPT_ACTIVE;
-
 	adev->scan_duration = 100;
 	adev->scan_probe_delay = 200;
 	/* reported to break scanning: adev->scan_probe_delay = adev->cfgopt_probe_delay; */
 	adev->scan_rate = ACX_SCAN_RATE_1;
 
-	adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
-	adev->preamble_mode = 2; /* auto */
+	adev->mode = ACX_MODE_2_STA;
+	adev->ieee->sec.auth_mode = WLAN_AUTH_OPEN;
 	adev->listen_interval = 100;
 	adev->beacon_interval = DEFAULT_BEACON_INTERVAL;
-	adev->mode = ACX_MODE_2_STA;
-	adev->monitor_type = ARPHRD_IEEE80211_PRISM;
 	adev->dtim_interval = DEFAULT_DTIM_INTERVAL;
 
 	adev->msdu_lifetime = DEFAULT_MSDU_LIFETIME;
@@ -2159,6 +2227,7 @@ acx_s_set_defaults(acx_device_t *adev)
 	adev->short_retry = 7; /* max. retries for (short) non-RTS packets */
 	adev->long_retry = 4; /* max. retries for long (RTS) packets */
 
+	adev->preamble_mode = 2; /* auto */
 	adev->fallback_threshold = 3;
 	adev->stepup_threshold = 10;
 	adev->rate_bcast = RATE111_1;
@@ -2170,9 +2239,12 @@ acx_s_set_defaults(acx_device_t *adev)
 	} else {
 		adev->rate_oper = RATE111_ACX100_COMPAT;
 	}
-	/* build 802.11 style ratevector (802.11 7.3.2.2) */
+
+	/* Supported Rates element - the rates here are given in units of
+	 * 500 kbit/s, plus 0x80 added. See 802.11-1999.pdf item 7.3.2.2 */
 	acx_l_update_ratevector(adev);
 
+	/* set some more defaults */
 	if (IS_ACX111(adev)) {
 		/* 30mW (15dBm) is default, at least in my acx111 card: */
 		adev->tx_level_dbm = 15;
@@ -2183,7 +2255,6 @@ acx_s_set_defaults(acx_device_t *adev)
 		adev->tx_level_dbm = 18;
 	}
 	/* adev->tx_level_auto = 1; */
-
 	if (IS_ACX111(adev)) {
 		/* start with sensitivity level 1 out of 3: */
 		adev->sensitivity = 1;
@@ -2204,31 +2275,24 @@ acx_s_set_defaults(acx_device_t *adev)
 	adev->ps_enhanced_transition_time = 0;
 #endif
 
+	/* These settings will be set in fw on ifup */
 	adev->set_mask = 0
-		/* better re-init the antenna value we got */
-		| GETSET_ANTENNA
-		| GETSET_TXPOWER
-		| SET_RXCONFIG
-		/* configure card to do rate fallback when in auto rate mode. */
 		| GETSET_RETRY
 		| SET_MSDU_LIFETIME
+	/* configure card to do rate fallback when in auto rate mode */
 		| SET_RATE_FALLBACK
+		| SET_RXCONFIG
+		| GETSET_TXPOWER
+	/* better re-init the antenna value we got above */
+		| GETSET_ANTENNA
 #if POWER_SAVE_80211
 		| GETSET_POWER_80211
 #endif
 		;
-	/* query some settings from the card.
-	 * NOTE: for some settings, e.g. CCA and ED (ACX100!), an initial
-	 * query is REQUIRED, otherwise the card won't work correctly!! */
-	adev->get_mask = GETSET_ANTENNA|GETSET_SENSITIVITY|GETSET_STATION_ID|GETSET_REG_DOMAIN;
-	/* Only ACX100 supports ED and CCA */
-	if (IS_ACX100(adev))
-		adev->get_mask |= GETSET_CCA|GETSET_ED_THRESH;
 
 	acx_unlock(adev, flags);
 	acx_lock_unhold(); /* hold time 844814 CPU ticks @2GHz */
 
-	acx_s_update_card_settings(adev);
 	acx_s_initialize_rx_config(adev);
 
 	FN_EXIT0;
@@ -2576,14 +2640,14 @@ void
 acx_l_process_rxbuf(acx_device_t *adev, rxbuffer_t *rxbuf)
 {
 	struct wlan_hdr *hdr;
-	unsigned int buf_len;
 	unsigned int qual;
+	int buf_len;
 	u16 fc;
 
 	hdr = acx_get_wlan_hdr(adev, rxbuf);
-	/* length of frame from control field to last byte of FCS */
 	fc = le16_to_cpu(hdr->fc);
-	buf_len = RXBUF_BYTES_RCVD(rxbuf);
+	/* length of frame from control field to first byte of FCS */
+	buf_len = RXBUF_BYTES_RCVD(adev, rxbuf);
 
 	if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
 	  || (acx_debug & L_XFER_BEACON)
@@ -2739,16 +2803,14 @@ acx_l_softmac_process_rxbuf(acx_device_t
 	struct ieee80211_rx_stats stats;
 	struct wlan_hdr *hdr;
 	struct sk_buff *skb;
-	int buf_len;
 	int skb_len;
-	int payload_offset;
 	u16 fc;
 
 	FN_ENTER;
 
+	skb_len = RXBUF_BYTES_RCVD(adev, rxbuf);
 	hdr = acx_get_wlan_hdr(adev, rxbuf);
 	fc = le16_to_cpu(hdr->fc);
-	buf_len = RXBUF_BYTES_RCVD(rxbuf);
 
 	if ( ((WF_FC_FSTYPE & fc) != WF_FSTYPE_BEACON)
 	  || (acx_debug & L_XFER_BEACON)
@@ -2758,7 +2820,7 @@ acx_l_softmac_process_rxbuf(acx_device_t
 			"phystat:%02X phyrate:%u status:%u\n",
 			acx_get_packet_type_string(fc),
 			le32_to_cpu(rxbuf->time),
-			buf_len,
+			skb_len,
 			acx_signal_to_winlevel(rxbuf->phy_level),
 			acx_signal_to_winlevel(rxbuf->phy_snr),
 			rxbuf->mac_status,
@@ -2768,8 +2830,8 @@ acx_l_softmac_process_rxbuf(acx_device_t
 	}
 
 	if (unlikely(acx_debug & L_DATA)) {
-		printk("rx: 802.11 buf[%u]: ", buf_len);
-		acx_dump_bytes(hdr, buf_len);
+		printk("rx: 802.11 buf[%u]: ", skb_len);
+		acx_dump_bytes(hdr, skb_len);
 	}
 
 	/* FIXME: should check for Rx errors (rxbuf->mac_status?
@@ -2779,8 +2841,6 @@ acx_l_softmac_process_rxbuf(acx_device_t
 	/* we are in big luck: the acx100 doesn't modify any of the fields */
 	/* in the 802.11 frame. just pass this packet into the PF_PACKET */
 	/* subsystem. yeah. */
-	payload_offset = ((u8*)acx_get_wlan_hdr(adev, rxbuf) - (u8*)rxbuf);
-	skb_len = RXBUF_BYTES_USED(rxbuf) - payload_offset;
 
 	/* sanity check */
 	if (unlikely(skb_len > WLAN_A4FR_MAXLEN_WEP)) {
@@ -2798,7 +2858,7 @@ acx_l_softmac_process_rxbuf(acx_device_t
 	}
 
 	skb_put(skb, skb_len);
-	memcpy(skb->data, ((unsigned char*)rxbuf)+payload_offset, skb_len);
+	memcpy(skb->data, hdr, skb_len);
 
 	memset(&stats, 0, sizeof(stats));
 	stats.mac_time = le16_to_cpu(rxbuf->time);
@@ -3477,7 +3537,7 @@ acx_i_timer(unsigned long address)
 	case ACX_STATUS_3_AUTHENTICATED:
 		/* was set to 0 by set_status() */
 		if (++adev->auth_or_assoc_retries < 10) {
-			log(L_ASSOC,	"resend assoc request (attempt %d)\n",
+			log(L_ASSOC, "resend assoc request (attempt %d)\n",
 					adev->auth_or_assoc_retries + 1);
 			//sm? acx_l_transmit_assoc_req(adev);
 		} else {
@@ -4061,10 +4121,10 @@ acx_l_process_data_frame_master(acx_devi
 		/* To_DS = 0, From_DS = 1 */
 		hdr->fc = WF_FC_FROMDSi + WF_FTYPE_DATAi;
 
-		len = RXBUF_BYTES_RCVD(rxbuf);
 		txbuf = acx_l_get_txbuf(adev, tx);
 		if (txbuf) {
-			memcpy(txbuf, &rxbuf->hdr_a3, len);
+			len = RXBUF_BYTES_RCVD(adev, rxbuf);
+			memcpy(txbuf, hdr, len);
 			acx_l_tx_data(adev, tx, len);
 		} else {
 			acx_l_dealloc_tx(adev, tx);
@@ -4219,7 +4279,7 @@ acx_l_process_mgmt_frame(acx_device_t *a
 		return NOT_OK;
 	}
 
-	len = RXBUF_BYTES_RCVD(rxbuf);
+	len = RXBUF_BYTES_RCVD(adev, rxbuf);
 	if (WF_FC_ISWEPi & hdr->fc)
 		len -= 0x10;
 
@@ -5434,14 +5494,14 @@ acx100_s_set_wepkey(acx_device_t *adev)
 	ie_dot11WEPDefaultKey_t dk;
 	int i;
 
-	for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
-		if (adev->wep_keys[i].size != 0) {
+	for (i = 0; i < WEP_KEYS; i++) {
+		if (adev->ieee->sec.key_sizes[i] != 0) {
 			log(L_INIT, "setting WEP key: %d with "
-				"total size: %d\n", i, (int) adev->wep_keys[i].size);
+				"total size: %d\n", i, (int) adev->ieee->sec.key_sizes[i]);
 			dk.action = 1;
-			dk.keySize = adev->wep_keys[i].size;
+			dk.keySize = adev->ieee->sec.key_sizes[i];
 			dk.defaultKeyNum = i;
-			memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
+			memcpy(dk.key, adev->ieee->sec.keys[i], dk.keySize);
 			acx_s_configure(adev, &dk, ACX100_IE_DOT11_WEP_DEFAULT_KEY_WRITE);
 		}
 	}
@@ -5453,20 +5513,20 @@ acx111_s_set_wepkey(acx_device_t *adev)
 	acx111WEPDefaultKey_t dk;
 	int i;
 
-	for (i = 0; i < DOT11_MAX_DEFAULT_WEP_KEYS; i++) {
-		if (adev->wep_keys[i].size != 0) {
+	for (i = 0; i < WEP_KEYS; i++) {
+		if (adev->ieee->sec.key_sizes[i] != 0) {
 			log(L_INIT, "setting WEP key: %d with "
-				"total size: %d\n", i, (int) adev->wep_keys[i].size);
+				"total size: %d\n", i, (int) adev->ieee->sec.key_sizes[i]);
 			memset(&dk, 0, sizeof(dk));
 			dk.action = cpu_to_le16(1); /* "add key"; yes, that's a 16bit value */
-			dk.keySize = adev->wep_keys[i].size;
+			dk.keySize = adev->ieee->sec.key_sizes[i];
 
 			/* are these two lines necessary? */
 			dk.type = 0;              /* default WEP key */
 			dk.index = 0;             /* ignored when setting default key */
 
 			dk.defaultKeyNum = i;
-			memcpy(dk.key, adev->wep_keys[i].key, dk.keySize);
+			memcpy(dk.key, adev->ieee->sec.keys[i], dk.keySize);
 			acx_s_issue_cmd(adev, ACX1xx_CMD_WEP_MGMT, &dk, sizeof(dk));
 		}
 	}
@@ -5513,7 +5573,7 @@ acx100_s_init_wep(acx_device_t *adev)
 	}
 
 	/* let's choose maximum setting: 4 default keys, plus 10 other keys: */
-	options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
+	options.NumKeys = cpu_to_le16(WEP_KEYS + 10);
 	options.WEPOption = 0x00;
 
 	log(L_ASSOC, "%s: writing WEP options\n", __func__);
@@ -5521,10 +5581,10 @@ acx100_s_init_wep(acx_device_t *adev)
 
 	acx100_s_set_wepkey(adev);
 
-	if (adev->wep_keys[adev->wep_current_index].size != 0) {
+	if (adev->ieee->sec.key_sizes[adev->ieee->sec.active_key] != 0) {
 		log(L_ASSOC, "setting active default WEP key number: %d\n",
-				adev->wep_current_index);
-		dk.KeyID = adev->wep_current_index;
+				adev->ieee->sec.active_key);
+		dk.KeyID = adev->ieee->sec.active_key;
 		acx_s_configure(adev, &dk, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET); /* 0x1010 */
 	}
 	/* FIXME!!! wep_key_struct is filled nowhere! But adev
@@ -6580,7 +6640,7 @@ acx_s_update_card_settings(acx_device_t 
 
 		acx_s_set_wepkey(adev);
 
-		dkey.KeyID = adev->wep_current_index;
+		dkey.KeyID = adev->ieee->sec.active_key;
 		log(L_INIT, "setting WEP key %u as default\n", dkey.KeyID);
 		acx_s_configure(adev, &dkey, ACX1xx_IE_DOT11_WEP_DEFAULT_KEY_SET);
 #ifdef DEBUG_WEP
@@ -6601,7 +6661,7 @@ acx_s_update_card_settings(acx_device_t 
 
 			/* let's choose maximum setting: 4 default keys,
 			 * plus 10 other keys: */
-			options.NumKeys = cpu_to_le16(DOT11_MAX_DEFAULT_WEP_KEYS + 10);
+			options.NumKeys = cpu_to_le16(WEP_KEYS + 10);
 			/* don't decrypt default key only,
 			 * don't override decryption: */
 			options.WEPOption = 0;
@@ -6904,7 +6964,7 @@ acx_update_capabilities(acx_device_t *ad
 	/* other types of stations do not emit beacons */
 	}
 
-	if (adev->wep_restricted) {
+	if (adev->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY) {
 		SET_BIT(cap, WF_MGMT_CAP_PRIVACY);
 	}
 	if (adev->cfgopt_dot11ShortPreambleOption) {
@@ -7134,10 +7194,74 @@ module_exit(acx_e_cleanup_module)
 
 //SM
 void
-acx_e_ieee80211_set_security(struct net_device *dev,
+acx_e_ieee80211_set_security(struct net_device *ndev,
 		struct ieee80211_security *sec)
 {
-//todo
+/* Shamelessly copied from the rt2x00 project. */
+	acx_device_t *adev = ndev2adev(ndev);
+	unsigned long flags;
+	int i;
+
+	acx_sem_lock(adev);
+	acx_lock(adev, flags);
+
+	for (i = 0; i < WEP_KEYS; ++i) {
+		/* This gives us the flag for the 4 WEP keys. */
+		if (sec->flags & (1 << i)) {
+			adev->ieee->sec.encode_alg[i] = sec->encode_alg[i];
+			adev->ieee->sec.key_sizes[i] = sec->key_sizes[i];
+
+			if (sec->key_sizes[i] != 0) {
+				memcpy(adev->ieee->sec.keys[i], sec->keys[i],
+				       sec->key_sizes[i]);
+				/* Make sure WEP flag is set. */
+				adev->ieee->sec.flags |= (1 << i);
+			} else if (sec->level != SEC_LEVEL_1)
+				/* Make sure WEP flag isn't set. */
+				adev->ieee->sec.flags &= ~(1 << i);
+		}
+		SET_BIT(adev->set_mask, SET_WEP_OPTIONS);
+	}
+
+	if (sec->flags & SEC_ACTIVE_KEY) {
+		/* Check the key number is valid. */
+		if (sec->active_key < WEP_KEYS) {
+			adev->ieee->sec.active_key = sec->active_key;
+			adev->ieee->sec.flags |= SEC_ACTIVE_KEY;
+		} else
+			adev->ieee->sec.flags &= ~SEC_ACTIVE_KEY;
+		
+	} else
+		adev->ieee->sec.flags &= ~SEC_ACTIVE_KEY;
+
+	if (sec->flags & SEC_AUTH_MODE) {
+		adev->ieee->sec.auth_mode = sec->auth_mode;
+		adev->ieee->sec.flags |= SEC_AUTH_MODE;
+		SET_BIT(adev->set_mask, SET_WEP_OPTIONS);
+	}
+
+	if (sec->flags & SEC_ENCRYPT) {
+		adev->ieee->sec.encrypt = sec->encrypt;
+		adev->ieee->sec.flags |= SEC_ENCRYPT;
+		SET_BIT(adev->set_mask, GETSET_WEP);
+	}
+
+	if (sec->flags & SEC_ENABLED) {
+		adev->ieee->sec.enabled = sec->enabled;
+		adev->ieee->sec.flags |= SEC_ENABLED;
+		SET_BIT(adev->set_mask, GETSET_WEP);
+	}
+
+	if (sec->flags & SEC_LEVEL) {
+		adev->ieee->sec.level = sec->level;
+		adev->ieee->sec.flags |= SEC_LEVEL;
+		SET_BIT(adev->set_mask, GETSET_WEP);
+	}
+	
+	acx_unlock(adev, flags);
+	acx_sem_unlock(adev);
+
+	acx_s_update_card_settings(adev);
 }
 
 
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/ioctl.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/ioctl.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/ioctl.c	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/ioctl.c	Fri Feb  3 13:38:12 2006
@@ -1024,7 +1024,7 @@ acx_ioctl_set_encode(
 	if (dwrq->length > 0) {
 		/* if index is 0 or invalid, use default key */
 		if ((index < 0) || (index > 3))
-			index = (int)adev->wep_current_index;
+			index = (int)adev->ieee->sec.active_key;
 
 		if (0 == (dwrq->flags & IW_ENCODE_NOKEY)) {
 			if (dwrq->length > 29)
@@ -1032,26 +1032,26 @@ acx_ioctl_set_encode(
 
 			if (dwrq->length > 13) {
 				/* 29*8 == 232, WEP256 */
-				adev->wep_keys[index].size = 29;
+				adev->ieee->sec.key_sizes[index] = 29;
 			} else if (dwrq->length > 5) {
 				/* 13*8 == 104bit, WEP128 */
-				adev->wep_keys[index].size = 13;
+				adev->ieee->sec.key_sizes[index] = 13;
 			} else if (dwrq->length > 0) {
 				/* 5*8 == 40bit, WEP64 */
-				adev->wep_keys[index].size = 5;
+				adev->ieee->sec.key_sizes[index] = 5;
 			} else {
 				/* disable key */
-				adev->wep_keys[index].size = 0;
+				adev->ieee->sec.key_sizes[index] = 0;
 			}
 
-			memset(adev->wep_keys[index].key, 0,
-				sizeof(adev->wep_keys[index].key));
-			memcpy(adev->wep_keys[index].key, extra, dwrq->length);
+			memset(adev->ieee->sec.keys[index], 0,
+				sizeof(adev->ieee->sec.keys[index]));
+			memcpy(adev->ieee->sec.keys[index], extra, dwrq->length);
 		}
 	} else {
 		/* set transmit key */
 		if ((index >= 0) && (index <= 3))
-			adev->wep_current_index = index;
+			adev->ieee->sec.active_key = index;
 		else if (0 == (dwrq->flags & IW_ENCODE_MODE)) {
 			/* complain if we were not just setting
 			 * the key mode */
@@ -1060,15 +1060,13 @@ acx_ioctl_set_encode(
 		}
 	}
 
-	adev->wep_enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
+	adev->ieee->sec.enabled = !(dwrq->flags & IW_ENCODE_DISABLED);
 
 	if (dwrq->flags & IW_ENCODE_OPEN) {
-		adev->auth_alg = WLAN_AUTH_ALG_OPENSYSTEM;
-		adev->wep_restricted = 0;
+		adev->ieee->sec.auth_mode = WLAN_AUTH_OPEN;
 
 	} else if (dwrq->flags & IW_ENCODE_RESTRICTED) {
-		adev->auth_alg = WLAN_AUTH_ALG_SHAREDKEY;
-		adev->wep_restricted = 1;
+	  adev->ieee->sec.auth_mode = WLAN_AUTH_SHARED_KEY;
 	}
 
 	/* set flag to make sure the card WEP settings get updated */
@@ -1078,11 +1076,11 @@ acx_ioctl_set_encode(
 		dwrq->length, extra, dwrq->flags);
 
 	for (index = 0; index <= 3; index++) {
-		if (adev->wep_keys[index].size) {
+		if (adev->ieee->sec.key_sizes[index]) {
 			log(L_IOCTL,	"index=%d, size=%d, key at 0x%p\n",
-				adev->wep_keys[index].index,
-				(int) adev->wep_keys[index].size,
-				adev->wep_keys[index].key);
+				adev->ieee->sec.active_key,
+				(int) adev->ieee->sec.key_sizes[index],
+				adev->ieee->sec.keys[index]);
 		}
 	}
 	result = -EINPROGRESS;
@@ -1111,18 +1109,18 @@ acx_ioctl_get_encode(
 
 	FN_ENTER;
 
-	if (adev->wep_enabled == 0) {
+	if (adev->ieee->sec.enabled == 0) {
 		dwrq->flags = IW_ENCODE_DISABLED;
 	} else {
 		if ((index < 0) || (index > 3))
-			index = (int)adev->wep_current_index;
+			index = (int)adev->ieee->sec.active_key;
 
-		dwrq->flags = (adev->wep_restricted == 1) ?
+		dwrq->flags = (adev->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY) ?
 				IW_ENCODE_RESTRICTED : IW_ENCODE_OPEN;
-		dwrq->length = adev->wep_keys[index].size;
+		dwrq->length = adev->ieee->sec.key_sizes[index];
 
-		memcpy(extra, adev->wep_keys[index].key,
-			      adev->wep_keys[index].size);
+		memcpy(extra, adev->ieee->sec.keys[index],
+			      adev->ieee->sec.key_sizes[index]);
 	}
 
 	/* set the current index */
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/pci.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/pci.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/pci.c	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/pci.c	Fri Feb  3 13:38:12 2006
@@ -476,23 +476,23 @@ acxpci_s_write_phy_reg(acx_device_t *ade
 **
 ** Arguments:
 **	adev		wlan device structure
-**	apfw_image	firmware image.
+**	fw_image	firmware image.
 **
 ** Returns:
 **	1	firmware image corrupted
 **	0	success
 */
 static int
-acxpci_s_write_fw(acx_device_t *adev, const firmware_image_t *apfw_image, u32 offset)
+acxpci_s_write_fw(acx_device_t *adev, const firmware_image_t *fw_image, u32 offset)
 {
 	int len, size;
 	u32 sum, v32;
 	/* we skip the first four bytes which contain the control sum */
-	const u8 *image = (u8*)apfw_image + 4;
+	const u8 *p = (u8*)fw_image + 4;
 
 	/* start the image checksum by adding the image size value */
-	sum = image[0]+image[1]+image[2]+image[3];
-	image += 4;
+	sum = p[0]+p[1]+p[2]+p[3];
+	p += 4;
 
 	write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
 
@@ -505,12 +505,12 @@ acxpci_s_write_fw(acx_device_t *adev, co
 #endif
 
 	len = 0;
-	size = le32_to_cpu(apfw_image->size) & (~3);
+	size = le32_to_cpu(fw_image->size) & (~3);
 
 	while (likely(len < size)) {
-		v32 = be32_to_cpu(*(u32*)image);
-		sum += image[0]+image[1]+image[2]+image[3];
-		image += 4;
+		v32 = be32_to_cpu(*(u32*)p);
+		sum += p[0]+p[1]+p[2]+p[3];
+		p += 4;
 		len += 4;
 
 #if NO_AUTO_INCREMENT
@@ -521,10 +521,10 @@ acxpci_s_write_fw(acx_device_t *adev, co
 	}
 
 	log(L_DEBUG, "firmware written, size:%d sum1:%x sum2:%x\n",
-			size, sum, le32_to_cpu(apfw_image->chksum));
+			size, sum, le32_to_cpu(fw_image->chksum));
 
 	/* compare our checksum with the stored image checksum */
-	return (sum != le32_to_cpu(apfw_image->chksum));
+	return (sum != le32_to_cpu(fw_image->chksum));
 }
 
 
@@ -536,25 +536,25 @@ acxpci_s_write_fw(acx_device_t *adev, co
 **
 ** Arguments:
 **	adev		wlan device structure
-**   apfw_image  firmware image.
+**   fw_image  firmware image.
 **
 ** Returns:
 **	NOT_OK	firmware image corrupted or not correctly written
 **	OK	success
 */
 static int
-acxpci_s_validate_fw(acx_device_t *adev, const firmware_image_t *apfw_image,
+acxpci_s_validate_fw(acx_device_t *adev, const firmware_image_t *fw_image,
 				u32 offset)
 {
 	u32 sum, v32, w32;
 	int len, size;
 	int result = OK;
 	/* we skip the first four bytes which contain the control sum */
-	const u8 *image = (u8*)apfw_image + 4;
+	const u8 *p = (u8*)fw_image + 4;
 
 	/* start the image checksum by adding the image size value */
-	sum = image[0]+image[1]+image[2]+image[3];
-	image += 4;
+	sum = p[0]+p[1]+p[2]+p[3];
+	p += 4;
 
 	write_reg32(adev, IO_ACX_SLV_END_CTL, 0);
 
@@ -566,11 +566,11 @@ acxpci_s_validate_fw(acx_device_t *adev,
 #endif
 
 	len = 0;
-	size = le32_to_cpu(apfw_image->size) & (~3);
+	size = le32_to_cpu(fw_image->size) & (~3);
 
 	while (likely(len < size)) {
-		v32 = be32_to_cpu(*(u32*)image);
-		image += 4;
+		v32 = be32_to_cpu(*(u32*)p);
+		p += 4;
 		len += 4;
 
 #if NO_AUTO_INCREMENT
@@ -593,7 +593,7 @@ acxpci_s_validate_fw(acx_device_t *adev,
 
 	/* sum control verification */
 	if (result != NOT_OK) {
-		if (sum != le32_to_cpu(apfw_image->chksum)) {
+		if (sum != le32_to_cpu(fw_image->chksum)) {
 			printk("acx: FATAL: firmware upload: "
 				"checksums don't match!\n");
 			result = NOT_OK;
@@ -612,10 +612,10 @@ acxpci_s_validate_fw(acx_device_t *adev,
 static int
 acxpci_s_upload_fw(acx_device_t *adev)
 {
-	firmware_image_t *apfw_image = NULL;
+	firmware_image_t *fw_image = NULL;
 	int res = NOT_OK;
 	int try;
-	u32 size;
+	u32 file_size;
 	char filename[sizeof("tiacx1NNcNN")];
 
 	FN_ENTER;
@@ -625,22 +625,22 @@ acxpci_s_upload_fw(acx_device_t *adev)
 	snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
 		IS_ACX111(adev)*11, adev->radio_type);
 
-	apfw_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
-	if (!apfw_image) {
+	fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
+	if (!fw_image) {
 		adev->need_radio_fw = 1;
 		filename[sizeof("tiacx1NN")-1] = '\0';
-		apfw_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
-		if (!apfw_image) {
+		fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
+		if (!fw_image) {
 			FN_EXIT1(NOT_OK);
 			return NOT_OK;
 		}
 	}
 
 	for (try = 1; try <= 5; try++) {
-		res = acxpci_s_write_fw(adev, apfw_image, 0);
+		res = acxpci_s_write_fw(adev, fw_image, 0);
 		log(L_DEBUG|L_INIT, "acx_write_fw (main/combined):%d\n", res);
 		if (OK == res) {
-			res = acxpci_s_validate_fw(adev, apfw_image, 0);
+			res = acxpci_s_validate_fw(adev, fw_image, 0);
 			log(L_DEBUG|L_INIT, "acx_validate_fw "
 					"(main/combined):%d\n", res);
 		}
@@ -654,7 +654,7 @@ acxpci_s_upload_fw(acx_device_t *adev)
 		acx_s_msleep(1000); /* better wait for a while... */
 	}
 
-	vfree(apfw_image);
+	vfree(fw_image);
 
 	FN_EXIT1(res);
 	return res;
@@ -930,22 +930,22 @@ acxpci_s_reset_dev(acx_device_t *adev)
 	acx_unlock(adev, flags);
 
 	/* need to know radio type before fw load */
- 	/* Need to wait for arrival of this information in a loop,
- 	 * most probably since eCPU runs some init code from EEPROM
- 	 * (started burst read in reset_mac()) which also
- 	 * sets the radio type ID */
- 
- 	count = 0xffff;
- 	do {
- 		hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
- 		if (!--count) {
- 			msg = "eCPU didn't indicate radio type";
- 			goto end_fail;
- 		}
- 		cpu_relax();
- 	} while (!(hardware_info & 0xff00)); /* radio type still zero? */
- 
- 	/* printk("DEBUG: count %d\n", count); */
+	/* Need to wait for arrival of this information in a loop,
+	 * most probably since eCPU runs some init code from EEPROM
+	 * (started burst read in reset_mac()) which also
+	 * sets the radio type ID */
+
+	count = 0xffff;
+	do {
+		hardware_info = read_reg16(adev, IO_ACX_EEPROM_INFORMATION);
+		if (!--count) {
+			msg = "eCPU didn't indicate radio type";
+			goto end_fail;
+		}
+		cpu_relax();
+	} while (!(hardware_info & 0xff00)); /* radio type still zero? */
+
+	/* printk("DEBUG: count %d\n", count); */
 	adev->form_factor = hardware_info & 0xff;
 	adev->radio_type = hardware_info >> 8;
 
@@ -1641,6 +1641,10 @@ acxpci_e_probe(struct pci_dev *pdev, con
 	adev->softmac = ieee80211_priv(ndev);
 	adev->softmac->set_channel = acx_e_ieee80211_set_chan;
 
+	adev->ieee->sec.encrypt = 0;
+	adev->ieee->sec.enabled = 0;
+	adev->ieee->sec.auth_mode = WLAN_AUTH_OPEN;
+
 #ifdef NONESSENTIAL_FEATURES
 	acx_show_card_eeprom_id(adev);
 #endif /* NONESSENTIAL_FEATURES */
@@ -1668,9 +1672,6 @@ acxpci_e_probe(struct pci_dev *pdev, con
 	if (OK != acxpci_s_reset_dev(adev))
 		goto fail_reset;
 
-	if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
-		goto fail_read_eeprom_version;
-
 	if (IS_ACX100(adev)) {
 		/* ACX100: configopt struct in cmd mailbox - directly after reset */
 		memcpy_fromio(&co, adev->cmd_area, sizeof(co));
@@ -1728,7 +1729,6 @@ fail_register_netdev:
 	pci_set_drvdata(pdev, NULL);
 
 fail_init_mac:
-fail_read_eeprom_version:
 fail_reset:
 
 	acxpci_s_device_chain_remove(ndev);
diff -urpN wireless-2.6.git/drivers/net/wireless/tiacx/usb.c wireless-2.6.git.acx/drivers/net/wireless/tiacx/usb.c
--- wireless-2.6.git/drivers/net/wireless/tiacx/usb.c	Thu Feb  2 17:17:50 2006
+++ wireless-2.6.git.acx/drivers/net/wireless/tiacx/usb.c	Fri Feb  3 13:54:06 2006
@@ -78,14 +78,25 @@
 
 /***********************************************************************
 */
+/* ACX100 (TNETW1100) USB device: D-Link DWL-120+ */
 #define ACX100_VENDOR_ID 0x2001
 #define ACX100_PRODUCT_ID_UNBOOTED 0x3B01
 #define ACX100_PRODUCT_ID_BOOTED 0x3B00
 
+/* TNETW1450 USB devices */
+#define VENDOR_ID_DLINK		0x07b8 /* D-Link Corp. */
+#define PRODUCT_ID_WUG2400	0xb21a /* AboCom WUG2400 or SafeCom SWLUT-54125 */
+#define VENDOR_ID_AVM_GMBH	0x057c
+#define PRODUCT_ID_AVM_WLAN_USB	0x5601
+#define VENDOR_ID_ZCOM		0x0cde
+#define PRODUCT_ID_ZCOM_XG750	0x0017 /* not tested yet */
+#define VENDOR_ID_TI		0x0451
+#define PRODUCT_ID_TI_UNKNOWN	0x60c5 /* not tested yet */
+
 #define ACX_USB_CTRL_TIMEOUT	5500   /* steps in ms */
 
-/* Buffer size for fw upload */
-#define ACX_USB_RWMEM_MAXLEN	2048
+/* Buffer size for fw upload, same for both ACX100 USB and TNETW1450 */
+#define USB_RWMEM_MAXLEN	2048
 
 /* The number of bulk URBs to use */
 #define ACX_TX_URB_CNT		8
@@ -106,7 +117,7 @@ static void acxusb_i_complete_rx(struct 
 static int acxusb_e_open(struct net_device *);
 static int acxusb_e_close(struct net_device *);
 static void acxusb_i_set_rx_mode(struct net_device *);
-static int acxusb_boot(struct usb_device *);
+static int acxusb_boot(struct usb_device *, int is_tnetw1450, int *radio_type);
 
 static void acxusb_l_poll_rx(acx_device_t *adev, usb_rx_t* rx);
 
@@ -132,6 +143,10 @@ static const struct usb_device_id
 acxusb_ids[] = {
 	{ USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_BOOTED) },
 	{ USB_DEVICE(ACX100_VENDOR_ID, ACX100_PRODUCT_ID_UNBOOTED) },
+	{ USB_DEVICE(VENDOR_ID_DLINK, PRODUCT_ID_WUG2400) },
+	{ USB_DEVICE(VENDOR_ID_AVM_GMBH, PRODUCT_ID_AVM_WLAN_USB) },
+	{ USB_DEVICE(VENDOR_ID_ZCOM, PRODUCT_ID_ZCOM_XG750) },
+	{ USB_DEVICE(VENDOR_ID_TI, PRODUCT_ID_TI_UNKNOWN) },
 	{}
 };
 
@@ -443,107 +458,262 @@ bad:
 ** firmware and transmitting the checksum, the device resets and appears
 ** as a new device on the USB bus (the device we can finally deal with)
 */
+static inline int
+acxusb_fw_needs_padding(firmware_image_t *fw_image, unsigned int usb_maxlen)
+{
+	unsigned int num_xfers = ((fw_image->size - 1) / usb_maxlen) + 1;
+
+	return ((num_xfers % 2) == 0);
+}
+
 static int
-acxusb_boot(struct usb_device *usbdev)
+acxusb_boot(struct usb_device *usbdev, int is_tnetw1450, int *radio_type)
 {
-	static const char filename[] = "tiacx100usb";
+	char filename[sizeof("tiacx1NNusbcRR")];
 
-	char *firmware = NULL;
+	firmware_image_t *fw_image = NULL;
 	char *usbbuf;
 	unsigned int offset;
-	unsigned int len, inpipe, outpipe;
-	u32 checksum;
-	u32 size;
-	int result;
+	unsigned int blk_len, inpipe, outpipe;
+	u32 num_processed;
+	u32 img_checksum, sum;
+	u32 file_size;
+	int result = -EIO;
+	int i;
 
 	FN_ENTER;
 
-	usbbuf = kmalloc(ACX_USB_RWMEM_MAXLEN, GFP_KERNEL);
+	/* dump_device(usbdev); */
+
+	usbbuf = kmalloc(USB_RWMEM_MAXLEN, GFP_KERNEL);
 	if (!usbbuf) {
-		printk(KERN_ERR "acx: no memory for USB transfer buffer ("
-			STRING(ACX_USB_RWMEM_MAXLEN)" bytes)\n");
+		printk(KERN_ERR "acx: no memory for USB transfer buffer (%d bytes)\n", USB_RWMEM_MAXLEN);
 		result = -ENOMEM;
 		goto end;
 	}
-	firmware = (char *)acx_s_read_fw(&usbdev->dev, filename, &size);
-	if (!firmware) {
+	if (is_tnetw1450) {
+		/* Obtain the I/O pipes */
+		outpipe = usb_sndbulkpipe(usbdev, 1);
+		inpipe = usb_rcvbulkpipe(usbdev, 2);
+
+		printk(KERN_DEBUG "wait for device ready\n");
+		for (i = 0; i <= 2; i++) {
+			result = usb_bulk_msg(usbdev, inpipe,
+				usbbuf,
+				USB_RWMEM_MAXLEN,
+				&num_processed,
+				2000
+				);
+
+			if ((*(u32 *)&usbbuf[4] == 0x40000001)
+			&& (*(u16 *)&usbbuf[2] == 0x1)
+			&& ((*(u16 *)usbbuf & 0x3fff) == 0)
+			&& ((*(u16 *)usbbuf & 0xc000) == 0xc000))
+				break;
+			msleep(10);
+		}
+		if (i == 2)
+			goto fw_end;
+
+		*radio_type = usbbuf[8];
+	} else {
+		/* Obtain the I/O pipes */
+		outpipe = usb_sndctrlpipe(usbdev, 0);
+		inpipe = usb_rcvctrlpipe(usbdev, 0);
+
+		/* FIXME: shouldn't be hardcoded */
+		*radio_type = RADIO_MAXIM_0D;
+	}
+
+	snprintf(filename, sizeof(filename), "tiacx1%02dusbc%02X",
+				is_tnetw1450 * 11, *radio_type);
+
+	fw_image = acx_s_read_fw(&usbdev->dev, filename, &file_size);
+	if (!fw_image) {
 		result = -EIO;
 		goto end;
 	}
-	log(L_INIT, "firmware size: %d bytes\n", size);
+	log(L_INIT, "firmware size: %d bytes\n", file_size);
 
-	/* Obtain the I/O pipes */
-	outpipe = usb_sndctrlpipe(usbdev, 0);
-	inpipe = usb_rcvctrlpipe(usbdev, 0);
+	img_checksum = le32_to_cpu(fw_image->chksum);
+
+	if (is_tnetw1450) {
+		u8 cmdbuf[20];
+		const u8 *p;
+		u8 need_padding;
+		u32 tmplen, val;
+
+		memset(cmdbuf, 0, 16);
+
+		need_padding = acxusb_fw_needs_padding(fw_image, USB_RWMEM_MAXLEN);
+		tmplen = need_padding ? file_size-4 : file_size-8;
+		*(u16 *)&cmdbuf[0] = 0xc000;
+		*(u16 *)&cmdbuf[2] = 0x000b;
+		*(u32 *)&cmdbuf[4] = tmplen;
+		*(u32 *)&cmdbuf[8] = file_size-8;
+		*(u32 *)&cmdbuf[12] = img_checksum;
+
+		result = usb_bulk_msg(usbdev, outpipe, cmdbuf, 16, &num_processed, HZ);
+		if (result < 0)
+			goto fw_end;
+
+		p = (const u8 *)&fw_image->size;
+
+		/* first calculate checksum for image size part */
+		sum = p[0]+p[1]+p[2]+p[3];
+		p += 4;
+
+		/* now continue checksum for firmware data part */
+		tmplen = le32_to_cpu(fw_image->size);
+		for (i = 0; i < tmplen /* image size */; i++) {
+			sum += *p++;
+		}
+
+		if (sum != le32_to_cpu(fw_image->chksum)) {
+			printk("acx: FATAL: firmware upload: "
+				"checksums don't match! "
+				"(0x%08x vs. 0x%08x)\n",
+					sum, fw_image->chksum);
+			goto fw_end;
+		}
+
+		offset = 8;
+		while (offset < file_size) {
+			blk_len = file_size - offset;
+			if (blk_len > USB_RWMEM_MAXLEN) {
+				blk_len = USB_RWMEM_MAXLEN;
+			}
+
+			log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
+							blk_len, offset);
+			memcpy(usbbuf, ((u8 *)fw_image) + offset, blk_len);
+
+			p = usbbuf;
+			for (i = 0; i < blk_len; i += 4) {
+				*(u32 *)p = be32_to_cpu(*(u32 *)p);
+				p += 4;
+			}
 
-	/* now upload the firmware, slice the data into blocks */
-	offset = 8;
-	while (offset < size) {
-		len = size - offset;
-		if (len >= ACX_USB_RWMEM_MAXLEN) {
-			len = ACX_USB_RWMEM_MAXLEN;
+			result = usb_bulk_msg(usbdev, outpipe, usbbuf, blk_len, &num_processed, HZ);
+			if ((result < 0) || (num_processed != blk_len))
+				goto fw_end;
+			offset += blk_len;
+		}
+		if (need_padding) {
+			printk(KERN_DEBUG "send padding\n");
+			memset(usbbuf, 0, 4);
+			result = usb_bulk_msg(usbdev, outpipe, usbbuf, 4, &num_processed, HZ);
+			if ((result < 0) || (num_processed != 4))
+				goto fw_end;
+		}
+		printk(KERN_DEBUG "read firmware upload result\n");
+		memset(cmdbuf, 0, 20); /* additional memset */
+		result = usb_bulk_msg(usbdev, inpipe, cmdbuf, 20, &num_processed, 2000);
+		if (result < 0)
+			goto fw_end;
+		if (*(u32 *)&cmdbuf[4] == 0x40000003)
+			goto fw_end;
+		if (*(u32 *)&cmdbuf[4])
+			goto fw_end;
+		if (*(u16 *)&cmdbuf[16] != 1)
+			goto fw_end;
+
+		val = *(u32 *)&cmdbuf[0];
+		if ((val & 0x3fff)
+		||  ((val & 0xc000) != 0xc000))
+			goto fw_end;
+
+		val = *(u32 *)&cmdbuf[8];
+		if (val & 2) {
+			result = usb_bulk_msg(usbdev, inpipe, cmdbuf, 20, &num_processed, 2000);
+			if (result < 0)
+				goto fw_end;
+			val = *(u32 *)&cmdbuf[8];
+		}
+		/* yup, no "else" here! */
+		if (val & 1) {
+			memset(usbbuf, 0, 4);
+			result = usb_bulk_msg(usbdev, outpipe, usbbuf, 4, &num_processed, HZ);
+			if ((result < 0) || (!num_processed))
+				goto fw_end;
 		}
-		log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
-						len, offset);
+
+		printk("TNETW1450 firmware upload successful!\n");
 		result = 0;
-		memcpy(usbbuf, firmware + offset, len);
+		goto end;
+fw_end:
+		result = -EIO;
+		goto end;
+	} else {
+		/* ACX100 USB */
+
+		/* now upload the firmware, slice the data into blocks */
+		offset = 8;
+		while (offset < file_size) {
+			blk_len = file_size - offset;
+			if (blk_len > USB_RWMEM_MAXLEN) {
+				blk_len = USB_RWMEM_MAXLEN;
+			}
+			log(L_INIT, "uploading firmware (%d bytes, offset=%d)\n",
+							blk_len, offset);
+			memcpy(usbbuf, ((u8 *)fw_image) + offset, blk_len);
+			result = usb_control_msg(usbdev, outpipe,
+				ACX_USB_REQ_UPLOAD_FW,
+				USB_TYPE_VENDOR|USB_DIR_OUT,
+				(file_size - 8) & 0xffff, /* value */
+				(file_size - 8) >> 16, /* index */
+				usbbuf, /* dataptr */
+				blk_len, /* size */
+				3000 /* timeout in ms */
+			);
+			offset += blk_len;
+			if (result < 0) {
+				printk(KERN_ERR "acx: error %d during upload "
+					"of firmware, aborting\n", result);
+				goto end;
+			}
+		}
+
+		/* finally, send the checksum and reboot the device */
+		/* does this trigger the reboot? */
 		result = usb_control_msg(usbdev, outpipe,
 			ACX_USB_REQ_UPLOAD_FW,
 			USB_TYPE_VENDOR|USB_DIR_OUT,
-			size - 8, /* value */
-			0, /* index */
+			img_checksum & 0xffff, /* value */
+			img_checksum >> 16, /* index */
+			NULL, /* dataptr */
+			0, /* size */
+			3000 /* timeout in ms */
+		);
+		if (result < 0) {
+			printk(KERN_ERR "acx: error %d during tx of checksum, "
+					"aborting\n", result);
+			goto end;
+		}
+		result = usb_control_msg(usbdev, inpipe,
+			ACX_USB_REQ_ACK_CS,
+			USB_TYPE_VENDOR|USB_DIR_IN,
+			img_checksum & 0xffff, /* value */
+			img_checksum >> 16, /* index */
 			usbbuf, /* dataptr */
-			len, /* size */
+			8, /* size */
 			3000 /* timeout in ms */
 		);
-		offset += len;
 		if (result < 0) {
-			printk(KERN_ERR "acx: error %d during upload "
-				"of firmware, aborting\n", result);
+			printk(KERN_ERR "acx: error %d during ACK of checksum, "
+					"aborting\n", result);
 			goto end;
 		}
+		if (*usbbuf != 0x10) {
+			printk(KERN_ERR "acx: invalid checksum?\n");
+			result = -EINVAL;
+			goto end;
+		}
+		result = 0;
 	}
 
-	/* finally, send the checksum and reboot the device */
-	checksum = le32_to_cpu(*(u32 *)firmware);
-	/* is this triggers the reboot? */
-	result = usb_control_msg(usbdev, outpipe,
-		ACX_USB_REQ_UPLOAD_FW,
-		USB_TYPE_VENDOR|USB_DIR_OUT,
-		checksum & 0xffff, /* value */
-		checksum >> 16, /* index */
-		NULL, /* dataptr */
-		0, /* size */
-		3000 /* timeout in ms */
-	);
-	if (result < 0) {
-		printk(KERN_ERR "acx: error %d during tx of checksum, "
-				"aborting\n", result);
-		goto end;
-	}
-	result = usb_control_msg(usbdev, inpipe,
-		ACX_USB_REQ_ACK_CS,
-		USB_TYPE_VENDOR|USB_DIR_IN,
-		checksum & 0xffff, /* value */
-		checksum >> 16, /* index */
-		usbbuf, /* dataptr */
-		8, /* size */
-		3000 /* timeout in ms */
-	);
-	if (result < 0) {
-		printk(KERN_ERR "acx: error %d during ACK of checksum, "
-				"aborting\n", result);
-		goto end;
-	}
-	if (*usbbuf != 0x10) {
-		kfree(usbbuf);
-		printk(KERN_ERR "acx: invalid checksum?\n");
-		result = -EINVAL;
-		goto end;
-	}
-	result = 0;
 end:
-	vfree(firmware);
+	vfree(fw_image);
 	kfree(usbbuf);
 
 	FN_EXIT1(result);
@@ -551,16 +721,28 @@ end:
 }
 
 
+/* FIXME: maybe merge it with usual eeprom reading, into common code? */
+static void
+acxusb_s_read_eeprom_version(acx_device_t *adev)
+{
+	u8 eeprom_ver[0x8];
+
+	memset(eeprom_ver, 0, sizeof(eeprom_ver));
+	acx_s_interrogate(adev, &eeprom_ver, ACX1FF_IE_EEPROM_VER);
+
+	/* FIXME: which one of those values to take? */
+	adev->eeprom_version = eeprom_ver[5];
+}
+
+
 /*
  * temporary helper function to at least fill important cfgopt members with
  * useful replacement values until we figure out how one manages to fetch
  * the configoption struct in the USB device case...
  */
-int
+static int
 acxusb_s_fill_configoption(acx_device_t *adev)
 {
-	printk("FIXME: haven't figured out how to fetch configoption struct "
-		"from USB device, passing hardcoded values instead\n");
 	adev->cfgopt_probe_delay = 200;
 	adev->cfgopt_dot11CCAModes = 4;
 	adev->cfgopt_dot11Diversity = 1;
@@ -572,6 +754,7 @@ acxusb_s_fill_configoption(acx_device_t 
 	return OK;
 }
 
+
 /***********************************************************************
 ** acxusb_e_probe()
 **
@@ -598,28 +781,41 @@ acxusb_e_probe(struct usb_interface *int
 	int numconfigs, numfaces, numep;
 	int result = OK;
 	int i;
+	int radio_type;
+	/* this one needs to be more precise in case there appears a TNETW1450 from the same vendor */
+	int is_tnetw1450 = (usbdev->descriptor.idVendor != ACX100_VENDOR_ID);
 
 	FN_ENTER;
 
-	/* First check if this is the "unbooted" hardware */
-	if ((usbdev->descriptor.idVendor == ACX100_VENDOR_ID)
-	 && (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED)) {
+	if (is_tnetw1450) {
 		/* Boot the device (i.e. upload the firmware) */
-		acxusb_boot(usbdev);
+		acxusb_boot(usbdev, is_tnetw1450, &radio_type);
 
-		/* OK, we are done with booting. Normally, the
-		** ID for the unbooted device should disappear
-		** and it will not need a driver anyway...so
-		** return a NULL
-		*/
-		log(L_INIT, "finished booting, returning from probe()\n");
-		result = OK; /* success */
-		goto end;
-	}
+		/* TNETW1450-based cards will continue right away with
+		 * the same USB ID after booting */
+	} else {
+		/* First check if this is the "unbooted" hardware */
+		if (usbdev->descriptor.idProduct == ACX100_PRODUCT_ID_UNBOOTED) {
 
-	if ((usbdev->descriptor.idVendor != ACX100_VENDOR_ID)
-	 || (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)) {
-		goto end_nodev;
+			/* Boot the device (i.e. upload the firmware) */
+			acxusb_boot(usbdev, is_tnetw1450, &radio_type);
+
+			/* DWL-120+ will first boot the firmware,
+			 * then later have a *separate* probe() run
+			 * since its USB ID will have changed after
+			 * firmware boot!
+			 * Since the first probe() run has no
+			 * other purpose than booting the firmware,
+			 * simply return immediately.
+			*/
+			log(L_INIT, "finished booting, returning from probe()\n");
+			result = OK; /* success */
+			goto end;
+		}
+		else
+		/* device not unbooted, but invalid USB ID!? */
+		if (usbdev->descriptor.idProduct != ACX100_PRODUCT_ID_BOOTED)
+			goto end_nodev;
 	}
 
 /* Ok, so it's our device and it has already booted */
@@ -656,10 +852,15 @@ acxusb_e_probe(struct usb_interface *int
 	adev->ndev = ndev;
 
 	adev->dev_type = DEVTYPE_USB;
-	adev->chip_type = CHIPTYPE_ACX100;
-
-	/* FIXME: should be read from register (via firmware) using standard ACX code */
-	adev->radio_type = RADIO_MAXIM_0D;
+	adev->radio_type = radio_type;
+	if (is_tnetw1450) {
+		/* well, actually it's a TNETW1450, but since it
+		 * seems to be sufficiently similar to TNETW1130,
+		 * I don't want to change large amounts of code now */
+		adev->chip_type = CHIPTYPE_ACX111;
+	} else {
+		adev->chip_type = CHIPTYPE_ACX100;
+	}
 
 	adev->usbdev = usbdev;
 	spin_lock_init(&adev->lock);    /* initial state: unlocked */
@@ -677,6 +878,10 @@ acxusb_e_probe(struct usb_interface *int
 	adev->softmac = ieee80211_priv(ndev);
 	adev->softmac->set_channel = acx_e_ieee80211_set_chan;
 
+	adev->ieee->sec.enabled = 0;
+	adev->ieee->sec.encrypt = 0;
+	adev->ieee->sec.auth_mode = WLAN_AUTH_OPEN;
+
 	/* Check that this is really the hardware we know about.
 	** If not sure, at least notify the user that he
 	** may be in trouble...
@@ -698,27 +903,32 @@ acxusb_e_probe(struct usb_interface *int
 	numep = ifdesc->bNumEndpoints;
 	log(L_DEBUG, "# of endpoints: %d\n", numep);
 
-	/* obtain information about the endpoint
-	** addresses, begin with some default values
-	*/
-	adev->bulkoutep = 1;
-	adev->bulkinep = 1;
-	for (i = 0; i < numep; i++) {
+	if (is_tnetw1450) {
+		adev->bulkoutep = 1;
+		adev->bulkinep = 2;
+	} else {
+		/* obtain information about the endpoint
+		** addresses, begin with some default values
+		*/
+		adev->bulkoutep = 1;
+		adev->bulkinep = 1;
+		for (i = 0; i < numep; i++) {
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11)
-		ep = usbdev->ep_in[i];
-		if (!ep)
-			continue;
-		epdesc = &ep->desc;
+			ep = usbdev->ep_in[i];
+			if (!ep)
+				continue;
+			epdesc = &ep->desc;
 #else
-		epdesc = usb_epnum_to_ep_desc(usbdev, i);
-		if (!epdesc)
-			continue;
+			epdesc = usb_epnum_to_ep_desc(usbdev, i);
+			if (!epdesc)
+				continue;
 #endif
-		if (epdesc->bmAttributes & USB_ENDPOINT_XFER_BULK) {
-			if (epdesc->bEndpointAddress & 0x80)
-				adev->bulkinep = epdesc->bEndpointAddress & 0xF;
-			else
-				adev->bulkoutep = epdesc->bEndpointAddress & 0xF;
+			if (epdesc->bmAttributes & USB_ENDPOINT_XFER_BULK) {
+				if (epdesc->bEndpointAddress & 0x80)
+					adev->bulkinep = epdesc->bEndpointAddress & 0xF;
+				else
+					adev->bulkoutep = epdesc->bEndpointAddress & 0xF;
+			}
 		}
 	}
 	log(L_DEBUG, "bulkout ep: 0x%X\n", adev->bulkoutep);
@@ -773,12 +983,13 @@ acxusb_e_probe(struct usb_interface *int
 	/* put acx out of sleep mode and initialize it */
 	acx_s_issue_cmd(adev, ACX1xx_CMD_WAKE, NULL, 0);
 
-	acxusb_s_fill_configoption(adev);
-
 	result = acx_s_init_mac(adev);
 	if (result)
 		goto end;
 
+	/* TODO: see similar code in pci.c */
+	acxusb_s_read_eeprom_version(adev);
+	acxusb_s_fill_configoption(adev);
 	acx_s_set_defaults(adev);
 	acx_s_get_firmware_version(adev);
 	acx_display_hardware_details(adev);
@@ -1622,11 +1833,13 @@ dump_device(struct usb_device *usbdev)
 	/* This saw a change after 2.6.10 */
 	printk("  ep_in wMaxPacketSize: ");
 	for (i = 0; i < 16; ++i)
-		printk("%d ", usbdev->ep_in[i]->desc.wMaxPacketSize);
+		if (usbdev->ep_in[i] != NULL)
+			printk("%d:%d ", i, usbdev->ep_in[i]->desc.wMaxPacketSize);
 	printk("\n");
 	printk("  ep_out wMaxPacketSize: ");
 	for (i = 0; i < VEC_SIZE(usbdev->ep_out); ++i)
-		printk("%d ", usbdev->ep_out[i]->desc.wMaxPacketSize);
+		if (usbdev->ep_out[i] != NULL)
+			printk("%d:%d ", i, usbdev->ep_out[i]->desc.wMaxPacketSize);
 	printk("\n");
 #else
 	printk("  epmaxpacketin: ");

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-02-08  2:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-03 12:14 [PATCH] acxsm: merge from acx 0.3.32 Denis Vlasenko
2006-02-07 15:41 ` Denis Vlasenko
2006-02-08  2:10   ` John W. Linville

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).