Staging: add w35und wifi driver

This is driver for w35und usb wifi -- also in kohjinsha
subnotebook. It should work well enough to associate and ping, but it
obviously needs to be rewritten two more times...

OTOH worst horrors (like embedded wifi stack) should have been fixed
already...

Signed-off-by: Pavel Machek <pavel@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

diff --git a/drivers/staging/winbond/linux/common.h b/drivers/staging/winbond/linux/common.h
new file mode 100644
index 0000000..6b00bad
--- /dev/null
+++ b/drivers/staging/winbond/linux/common.h
@@ -0,0 +1,143 @@
+//
+// common.h
+//
+// This file contains the OS dependant definition and function.
+// Every OS has this file individual.
+//
+
+#define DebugUsbdStatusInformation( _A )
+
+#ifndef COMMON_DEF
+#define COMMON_DEF
+
+#include <linux/version.h>
+#include <linux/usb.h>
+#include <linux/kernel.h> //need for kernel alert
+#include <linux/autoconf.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/slab.h> //memory allocate
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/init.h>//need for init and exit modules marco
+#include <linux/ctype.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/wireless.h>
+#include <linux/if_arp.h>
+#include <asm/uaccess.h>
+#include <net/iw_handler.h>
+#include <linux/skbuff.h>
+
+
+//#define DEBUG_ENABLED  1
+
+
+
+//===============================================================
+// Common type definition
+//===============================================================
+
+typedef u8*            PUCHAR;
+typedef s8*            PCHAR;
+typedef u8*            PBOOLEAN;
+typedef u16*           PUSHORT;
+typedef u32*           PULONG;
+typedef s16*   PSHORT;
+
+
+//===========================================
+#define IGNORE      2
+#define	SUCCESS     1
+#define	FAILURE     0
+
+
+#ifndef true
+#define true        1
+#endif
+
+#ifndef false
+#define false       0
+#endif
+
+// PD43 20021108
+#ifndef TRUE
+#define TRUE        1
+#endif
+
+#ifndef FALSE
+#define FALSE       0
+#endif
+
+#define STATUS_MEDIA_CONNECT 1
+#define STATUS_MEDIA_DISCONNECT 0
+
+#ifndef BIT
+#define BIT(x)                  (1 << (x))
+#endif
+
+typedef struct urb * PURB;
+
+
+
+//==================================================================================================
+// Common function definition
+//==================================================================================================
+#ifndef abs
+#define abs(_T)							((_T) < 0 ? -_T : _T)
+#endif
+#define DEBUG_ENABLED
+#define ETH_LENGTH_OF_ADDRESS	6
+#ifdef DEBUG_ENABLED
+#define WBDEBUG( _M )	printk _M
+#else
+#define WBDEBUG( _M )	0
+#endif
+
+#define OS_DISCONNECTED	0
+#define OS_CONNECTED	1
+
+
+#define OS_EVENT_INDICATE( _A, _B, _F )
+#define OS_PMKID_STATUS_EVENT( _A )
+
+
+/* Uff, no, longs are not atomic on all architectures Linux
+ * supports. This should really use atomic_t */
+
+#define OS_ATOMIC			u32
+#define OS_ATOMIC_READ( _A, _V )	_V
+#define OS_ATOMIC_INC( _A, _V )		EncapAtomicInc( _A, (void*)_V )
+#define OS_ATOMIC_DEC( _A, _V )		EncapAtomicDec( _A, (void*)_V )
+#define OS_MEMORY_CLEAR( _A, _S )	memset( (PUCHAR)_A,0,_S)
+#define OS_MEMORY_COMPARE( _A, _B, _S )	(memcmp(_A,_B,_S)? 0 : 1) // Definition is reverse with Ndis 1: the same 0: different
+
+
+#define OS_SPIN_LOCK				spinlock_t
+#define OS_SPIN_LOCK_ALLOCATE( _S )		spin_lock_init( _S );
+#define OS_SPIN_LOCK_FREE( _S )
+#define OS_SPIN_LOCK_ACQUIRED( _S )		spin_lock_irq( _S )
+#define OS_SPIN_LOCK_RELEASED( _S )		spin_unlock_irq( _S );
+
+#define OS_TIMER	struct timer_list
+#define OS_TIMER_INITIAL( _T, _F, _P )			\
+{							\
+	init_timer( _T );				\
+	(_T)->function = (void *)_F##_1a;		\
+	(_T)->data = (unsigned long)_P;			\
+}
+
+// _S : Millisecond
+// 20060420 At least 1 large than jiffies
+#define OS_TIMER_SET( _T, _S )					\
+{								\
+	(_T)->expires = jiffies + ((_S*HZ+999)/1000);\
+	add_timer( _T );					\
+}
+#define OS_TIMER_CANCEL( _T, _B )		del_timer_sync( _T )
+#define OS_TIMER_GET_SYS_TIME( _T )		(*_T=jiffies)
+
+
+#endif // COMMON_DEF
+
diff --git a/drivers/staging/winbond/linux/sysdef.h b/drivers/staging/winbond/linux/sysdef.h
new file mode 100644
index 0000000..d46d63e
--- /dev/null
+++ b/drivers/staging/winbond/linux/sysdef.h
@@ -0,0 +1,73 @@
+
+
+//
+// Winbond WLAN System Configuration defines
+//
+
+//=====================================================================
+// Current directory is Linux
+// The definition WB_LINUX is a keyword for this OS
+//=====================================================================
+#ifndef SYS_DEF_H
+#define SYS_DEF_H
+#define WB_LINUX
+#define WB_LINUX_WPA_PSK
+
+
+//#define _IBSS_BEACON_SEQ_STICK_
+#define _USE_FALLBACK_RATE_
+//#define ANTDIV_DEFAULT_ON
+
+#define _WPA2_	// 20061122 It's needed for current Linux driver
+
+
+#ifndef _WPA_PSK_DEBUG
+#undef  _WPA_PSK_DEBUG
+#endif
+
+// debug print options, mark what debug you don't need
+
+#ifdef FULL_DEBUG
+#define _PE_STATE_DUMP_
+#define _PE_TX_DUMP_
+#define _PE_RX_DUMP_
+#define _PE_OID_DUMP_
+#define _PE_DTO_DUMP_
+#define _PE_REG_DUMP_
+#define _PE_USB_INI_DUMP_
+#endif
+
+
+
+#include "common.h"	// Individual file depends on OS
+
+#include "../wb35_ver.h"
+#include "../mac_structures.h"
+#include "../ds_tkip.h"
+#include "../localpara.h"
+#include "../sme_s.h"
+#include "../scan_s.h"
+#include "../mds_s.h"
+#include "../mlme_s.h"
+#include "../bssdscpt.h"
+#include "../sme_api.h"
+#include "../gl_80211.h"
+#include "../mto.h"
+#include "../wblinux_s.h"
+#include "../wbhal_s.h"
+
+
+#include "../adapter.h"
+
+#include "../mlme_mib.h"
+#include "../mds_f.h"
+#include "../bss_f.h"
+#include "../mlmetxrx_f.h"
+#include "../mto_f.h"
+#include "../wbhal_f.h"
+#include "../wblinux_f.h"
+// Kernel Timer resolution, NDIS is 10ms, 10000us
+#define MIN_TIMEOUT_VAL	(10) //ms
+
+
+#endif
diff --git a/drivers/staging/winbond/linux/wb35reg.c b/drivers/staging/winbond/linux/wb35reg.c
new file mode 100644
index 0000000..2c0b454
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35reg.c
@@ -0,0 +1,747 @@
+#include "sysdef.h"
+
+extern void phy_calibration_winbond(hw_data_t *phw_data, u32 frequency);
+
+// TRUE  : read command process successfully
+// FALSE : register not support
+// RegisterNo : start base
+// pRegisterData : data point
+// NumberOfData : number of register data
+// Flag : AUTO_INCREMENT - RegisterNo will auto increment 4
+//		  NO_INCREMENT - Function will write data into the same register
+unsigned char
+Wb35Reg_BurstWrite(phw_data_t pHwData, u16 RegisterNo, PULONG pRegisterData, u8 NumberOfData, u8 Flag)
+{
+	PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+	PURB		pUrb = NULL;
+	PREG_QUEUE	pRegQueue = NULL;
+	u16		UrbSize;
+	struct      usb_ctrlrequest *dr;
+	u16		i, DataSize = NumberOfData*4;
+
+	// Module shutdown
+	if (pHwData->SurpriseRemove)
+		return FALSE;
+
+	// Trying to use burst write function if use new hardware
+	UrbSize = sizeof(REG_QUEUE) + DataSize + sizeof(struct usb_ctrlrequest);
+	OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
+	pUrb = wb_usb_alloc_urb(0);
+	if( pUrb && pRegQueue ) {
+		pRegQueue->DIRECT = 2;// burst write register
+		pRegQueue->INDEX = RegisterNo;
+		pRegQueue->pBuffer = (PULONG)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+		memcpy( pRegQueue->pBuffer, pRegisterData, DataSize );
+		//the function for reversing register data from little endian to big endian
+		for( i=0; i<NumberOfData ; i++ )
+			pRegQueue->pBuffer[i] = cpu_to_le32( pRegQueue->pBuffer[i] );
+
+		dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE) + DataSize);
+		dr->bRequestType = USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE;
+		dr->bRequest = 0x04; // USB or vendor-defined request code, burst mode
+		dr->wValue = cpu_to_le16( Flag ); // 0: Register number auto-increment, 1: No auto increment
+		dr->wIndex = cpu_to_le16( RegisterNo );
+		dr->wLength = cpu_to_le16( DataSize );
+		pRegQueue->Next = NULL;
+		pRegQueue->pUsbReq = dr;
+		pRegQueue->pUrb = pUrb;
+
+		OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+		if (pWb35Reg->pRegFirst == NULL)
+			pWb35Reg->pRegFirst = pRegQueue;
+		else
+			pWb35Reg->pRegLast->Next = pRegQueue;
+		pWb35Reg->pRegLast = pRegQueue;
+
+		OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+		// Start EP0VM
+		Wb35Reg_EP0VM_start(pHwData);
+
+		return TRUE;
+	} else {
+		if (pUrb)
+			usb_free_urb(pUrb);
+		if (pRegQueue)
+			kfree(pRegQueue);
+		return FALSE;
+	}
+   return FALSE;
+}
+
+void
+Wb35Reg_Update(phw_data_t pHwData,  u16 RegisterNo,  u32 RegisterValue)
+{
+	PWB35REG	pWb35Reg = &pHwData->Wb35Reg;
+	switch (RegisterNo) {
+	case 0x3b0: pWb35Reg->U1B0 = RegisterValue; break;
+	case 0x3bc: pWb35Reg->U1BC_LEDConfigure = RegisterValue; break;
+	case 0x400: pWb35Reg->D00_DmaControl = RegisterValue; break;
+	case 0x800: pWb35Reg->M00_MacControl = RegisterValue; break;
+	case 0x804: pWb35Reg->M04_MulticastAddress1 = RegisterValue; break;
+	case 0x808: pWb35Reg->M08_MulticastAddress2 = RegisterValue; break;
+	case 0x824: pWb35Reg->M24_MacControl = RegisterValue; break;
+	case 0x828: pWb35Reg->M28_MacControl = RegisterValue; break;
+	case 0x82c: pWb35Reg->M2C_MacControl = RegisterValue; break;
+	case 0x838: pWb35Reg->M38_MacControl = RegisterValue; break;
+	case 0x840: pWb35Reg->M40_MacControl = RegisterValue; break;
+	case 0x844: pWb35Reg->M44_MacControl = RegisterValue; break;
+	case 0x848: pWb35Reg->M48_MacControl = RegisterValue; break;
+	case 0x84c: pWb35Reg->M4C_MacStatus = RegisterValue; break;
+	case 0x860: pWb35Reg->M60_MacControl = RegisterValue; break;
+	case 0x868: pWb35Reg->M68_MacControl = RegisterValue; break;
+	case 0x870: pWb35Reg->M70_MacControl = RegisterValue; break;
+	case 0x874: pWb35Reg->M74_MacControl = RegisterValue; break;
+	case 0x878: pWb35Reg->M78_ERPInformation = RegisterValue; break;
+	case 0x87C: pWb35Reg->M7C_MacControl = RegisterValue; break;
+	case 0x880: pWb35Reg->M80_MacControl = RegisterValue; break;
+	case 0x884: pWb35Reg->M84_MacControl = RegisterValue; break;
+	case 0x888: pWb35Reg->M88_MacControl = RegisterValue; break;
+	case 0x898: pWb35Reg->M98_MacControl = RegisterValue; break;
+	case 0x100c: pWb35Reg->BB0C = RegisterValue; break;
+	case 0x102c: pWb35Reg->BB2C = RegisterValue; break;
+	case 0x1030: pWb35Reg->BB30 = RegisterValue; break;
+	case 0x103c: pWb35Reg->BB3C = RegisterValue; break;
+	case 0x1048: pWb35Reg->BB48 = RegisterValue; break;
+	case 0x104c: pWb35Reg->BB4C = RegisterValue; break;
+	case 0x1050: pWb35Reg->BB50 = RegisterValue; break;
+	case 0x1054: pWb35Reg->BB54 = RegisterValue; break;
+	case 0x1058: pWb35Reg->BB58 = RegisterValue; break;
+	case 0x105c: pWb35Reg->BB5C = RegisterValue; break;
+	case 0x1060: pWb35Reg->BB60 = RegisterValue; break;
+	}
+}
+
+// TRUE  : read command process successfully
+// FALSE : register not support
+unsigned char
+Wb35Reg_WriteSync(  phw_data_t pHwData,  u16 RegisterNo,  u32 RegisterValue )
+{
+	PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+	int ret = -1;
+
+	// Module shutdown
+	if (pHwData->SurpriseRemove)
+		return FALSE;
+
+	RegisterValue = cpu_to_le32(RegisterValue);
+
+	// update the register by send usb message------------------------------------
+	pWb35Reg->SyncIoPause = 1;
+
+	// 20060717.5 Wait until EP0VM stop
+	while (pWb35Reg->EP0vm_state != VM_STOP)
+		OS_SLEEP(10000);
+
+	// Sync IoCallDriver
+	pWb35Reg->EP0vm_state = VM_RUNNING;
+	ret = usb_control_msg( pHwData->WbUsb.udev,
+			       usb_sndctrlpipe( pHwData->WbUsb.udev, 0 ),
+			       0x03, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+			       0x0,RegisterNo, &RegisterValue, 4, HZ*100 );
+	pWb35Reg->EP0vm_state = VM_STOP;
+	pWb35Reg->SyncIoPause = 0;
+
+	Wb35Reg_EP0VM_start(pHwData);
+
+	if (ret < 0) {
+		#ifdef _PE_REG_DUMP_
+		WBDEBUG(("EP0 Write register usb message sending error\n"));
+		#endif
+
+		pHwData->SurpriseRemove = 1; // 20060704.2
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+// TRUE  : read command process successfully
+// FALSE : register not support
+unsigned char
+Wb35Reg_Write(  phw_data_t pHwData,  u16 RegisterNo,  u32 RegisterValue )
+{
+	PWB35REG	pWb35Reg = &pHwData->Wb35Reg;
+	struct usb_ctrlrequest *dr;
+	PURB		pUrb = NULL;
+	PREG_QUEUE	pRegQueue = NULL;
+	u16		UrbSize;
+
+
+	// Module shutdown
+	if (pHwData->SurpriseRemove)
+		return FALSE;
+
+	// update the register by send urb request------------------------------------
+	UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
+	OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
+	pUrb = wb_usb_alloc_urb(0);
+	if (pUrb && pRegQueue) {
+		pRegQueue->DIRECT = 1;// burst write register
+		pRegQueue->INDEX = RegisterNo;
+		pRegQueue->VALUE = cpu_to_le32(RegisterValue);
+		pRegQueue->RESERVED_VALID = FALSE;
+		dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+		dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
+		dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
+		dr->wValue = cpu_to_le16(0x0);
+		dr->wIndex = cpu_to_le16(RegisterNo);
+		dr->wLength = cpu_to_le16(4);
+
+		// Enter the sending queue
+		pRegQueue->Next = NULL;
+		pRegQueue->pUsbReq = dr;
+		pRegQueue->pUrb = pUrb;
+
+		OS_SPIN_LOCK_ACQUIRED(&pWb35Reg->EP0VM_spin_lock );
+		if (pWb35Reg->pRegFirst == NULL)
+			pWb35Reg->pRegFirst = pRegQueue;
+		else
+			pWb35Reg->pRegLast->Next = pRegQueue;
+		pWb35Reg->pRegLast = pRegQueue;
+
+		OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+		// Start EP0VM
+		Wb35Reg_EP0VM_start(pHwData);
+
+		return TRUE;
+	} else {
+		if (pUrb)
+			usb_free_urb(pUrb);
+		kfree(pRegQueue);
+		return FALSE;
+	}
+}
+
+//This command will be executed with a user defined value. When it completes,
+//this value is useful. For example, hal_set_current_channel will use it.
+// TRUE  : read command process successfully
+// FALSE : register not support
+unsigned char
+Wb35Reg_WriteWithCallbackValue( phw_data_t pHwData, u16 RegisterNo, u32 RegisterValue,
+				PCHAR pValue, s8 Len)
+{
+	PWB35REG	pWb35Reg = &pHwData->Wb35Reg;
+	struct usb_ctrlrequest *dr;
+	PURB		pUrb = NULL;
+	PREG_QUEUE	pRegQueue = NULL;
+	u16		UrbSize;
+
+	// Module shutdown
+	if (pHwData->SurpriseRemove)
+		return FALSE;
+
+	// update the register by send urb request------------------------------------
+	UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
+	OS_MEMORY_ALLOC((void* *) &pRegQueue, UrbSize );
+	pUrb = wb_usb_alloc_urb(0);
+	if (pUrb && pRegQueue) {
+		pRegQueue->DIRECT = 1;// burst write register
+		pRegQueue->INDEX = RegisterNo;
+		pRegQueue->VALUE = cpu_to_le32(RegisterValue);
+		//NOTE : Users must guarantee the size of value will not exceed the buffer size.
+		memcpy(pRegQueue->RESERVED, pValue, Len);
+		pRegQueue->RESERVED_VALID = TRUE;
+		dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+		dr->bRequestType = USB_TYPE_VENDOR|USB_DIR_OUT |USB_RECIP_DEVICE;
+		dr->bRequest = 0x03; // USB or vendor-defined request code, burst mode
+		dr->wValue = cpu_to_le16(0x0);
+		dr->wIndex = cpu_to_le16(RegisterNo);
+		dr->wLength = cpu_to_le16(4);
+
+		// Enter the sending queue
+		pRegQueue->Next = NULL;
+		pRegQueue->pUsbReq = dr;
+		pRegQueue->pUrb = pUrb;
+		OS_SPIN_LOCK_ACQUIRED (&pWb35Reg->EP0VM_spin_lock );
+		if( pWb35Reg->pRegFirst == NULL )
+			pWb35Reg->pRegFirst = pRegQueue;
+		else
+			pWb35Reg->pRegLast->Next = pRegQueue;
+		pWb35Reg->pRegLast = pRegQueue;
+
+		OS_SPIN_LOCK_RELEASED ( &pWb35Reg->EP0VM_spin_lock );
+
+		// Start EP0VM
+		Wb35Reg_EP0VM_start(pHwData);
+		return TRUE;
+	} else {
+		if (pUrb)
+			usb_free_urb(pUrb);
+		kfree(pRegQueue);
+		return FALSE;
+	}
+}
+
+// TRUE  : read command process successfully
+// FALSE : register not support
+// pRegisterValue : It must be a resident buffer due to asynchronous read register.
+unsigned char
+Wb35Reg_ReadSync(  phw_data_t pHwData,  u16 RegisterNo,   PULONG pRegisterValue )
+{
+	PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+	PULONG	pltmp = pRegisterValue;
+	int ret = -1;
+
+	// Module shutdown
+	if (pHwData->SurpriseRemove)
+		return FALSE;
+
+	// Read the register by send usb message------------------------------------
+
+	pWb35Reg->SyncIoPause = 1;
+
+	// 20060717.5 Wait until EP0VM stop
+	while (pWb35Reg->EP0vm_state != VM_STOP)
+		OS_SLEEP(10000);
+
+	pWb35Reg->EP0vm_state = VM_RUNNING;
+	ret = usb_control_msg( pHwData->WbUsb.udev,
+			       usb_rcvctrlpipe(pHwData->WbUsb.udev, 0),
+			       0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
+			       0x0, RegisterNo, pltmp, 4, HZ*100 );
+
+	*pRegisterValue = cpu_to_le32(*pltmp);
+
+	pWb35Reg->EP0vm_state = VM_STOP;
+
+	Wb35Reg_Update( pHwData, RegisterNo, *pRegisterValue );
+	pWb35Reg->SyncIoPause = 0;
+
+	Wb35Reg_EP0VM_start( pHwData );
+
+	if (ret < 0) {
+		#ifdef _PE_REG_DUMP_
+		WBDEBUG(("EP0 Read register usb message sending error\n"));
+		#endif
+
+		pHwData->SurpriseRemove = 1; // 20060704.2
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+// TRUE  : read command process successfully
+// FALSE : register not support
+// pRegisterValue : It must be a resident buffer due to asynchronous read register.
+unsigned char
+Wb35Reg_Read(phw_data_t pHwData, u16 RegisterNo,  PULONG pRegisterValue )
+{
+	PWB35REG	pWb35Reg = &pHwData->Wb35Reg;
+	struct usb_ctrlrequest * dr;
+	PURB		pUrb;
+	PREG_QUEUE	pRegQueue;
+	u16		UrbSize;
+
+	// Module shutdown
+	if (pHwData->SurpriseRemove)
+		return FALSE;
+
+	// update the variable by send Urb to read register ------------------------------------
+	UrbSize = sizeof(REG_QUEUE) + sizeof(struct usb_ctrlrequest);
+	OS_MEMORY_ALLOC( (void* *)&pRegQueue, UrbSize );
+	pUrb = wb_usb_alloc_urb(0);
+	if( pUrb && pRegQueue )
+	{
+		pRegQueue->DIRECT = 0;// read register
+		pRegQueue->INDEX = RegisterNo;
+		pRegQueue->pBuffer = pRegisterValue;
+		dr = (struct usb_ctrlrequest *)((PUCHAR)pRegQueue + sizeof(REG_QUEUE));
+		dr->bRequestType = USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN;
+		dr->bRequest = 0x01; // USB or vendor-defined request code, burst mode
+		dr->wValue = cpu_to_le16(0x0);
+		dr->wIndex = cpu_to_le16 (RegisterNo);
+		dr->wLength = cpu_to_le16 (4);
+
+		// Enter the sending queue
+		pRegQueue->Next = NULL;
+		pRegQueue->pUsbReq = dr;
+		pRegQueue->pUrb = pUrb;
+		OS_SPIN_LOCK_ACQUIRED ( &pWb35Reg->EP0VM_spin_lock );
+		if( pWb35Reg->pRegFirst == NULL )
+			pWb35Reg->pRegFirst = pRegQueue;
+		else
+			pWb35Reg->pRegLast->Next = pRegQueue;
+		pWb35Reg->pRegLast = pRegQueue;
+
+		OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+		// Start EP0VM
+		Wb35Reg_EP0VM_start( pHwData );
+
+		return TRUE;
+	} else {
+		if (pUrb)
+			usb_free_urb( pUrb );
+		kfree(pRegQueue);
+		return FALSE;
+	}
+}
+
+
+void
+Wb35Reg_EP0VM_start(  phw_data_t pHwData )
+{
+	PWB35REG pWb35Reg = &pHwData->Wb35Reg;
+
+	if (OS_ATOMIC_INC( pHwData->Adapter, &pWb35Reg->RegFireCount) == 1) {
+		pWb35Reg->EP0vm_state = VM_RUNNING;
+		Wb35Reg_EP0VM(pHwData);
+	} else
+		OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
+}
+
+void
+Wb35Reg_EP0VM(phw_data_t pHwData )
+{
+	PWB35REG	pWb35Reg = &pHwData->Wb35Reg;
+	PURB		pUrb;
+	struct usb_ctrlrequest *dr;
+	PULONG		pBuffer;
+	int			ret = -1;
+	PREG_QUEUE	pRegQueue;
+
+
+	if (pWb35Reg->SyncIoPause)
+		goto cleanup;
+
+	if (pHwData->SurpriseRemove)
+		goto cleanup;
+
+	// Get the register data and send to USB through Irp
+	OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+	pRegQueue = pWb35Reg->pRegFirst;
+	OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+	if (!pRegQueue)
+		goto cleanup;
+
+	// Get an Urb, send it
+	pUrb = (PURB)pRegQueue->pUrb;
+
+	dr = pRegQueue->pUsbReq;
+	pUrb = pRegQueue->pUrb;
+	pBuffer = pRegQueue->pBuffer;
+	if (pRegQueue->DIRECT == 1) // output
+		pBuffer = &pRegQueue->VALUE;
+
+	usb_fill_control_urb( pUrb, pHwData->WbUsb.udev,
+			      REG_DIRECTION(pHwData->WbUsb.udev,pRegQueue),
+			      (PUCHAR)dr,pBuffer,cpu_to_le16(dr->wLength),
+			      Wb35Reg_EP0VM_complete, (void*)pHwData);
+
+	pWb35Reg->EP0vm_state = VM_RUNNING;
+
+	ret = wb_usb_submit_urb( pUrb );
+
+	if (ret < 0) {
+#ifdef _PE_REG_DUMP_
+		WBDEBUG(("EP0 Irp sending error\n"));
+#endif
+		goto cleanup;
+	}
+
+	return;
+
+ cleanup:
+	pWb35Reg->EP0vm_state = VM_STOP;
+	OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
+}
+
+
+void
+Wb35Reg_EP0VM_complete(PURB pUrb)
+{
+	phw_data_t  pHwData = (phw_data_t)pUrb->context;
+	PWB35REG	pWb35Reg = &pHwData->Wb35Reg;
+	PREG_QUEUE	pRegQueue;
+
+
+	// Variable setting
+	pWb35Reg->EP0vm_state = VM_COMPLETED;
+	pWb35Reg->EP0VM_status = pUrb->status;
+
+	if (pHwData->SurpriseRemove) { // Let WbWlanHalt to handle surprise remove
+		pWb35Reg->EP0vm_state = VM_STOP;
+		OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Reg->RegFireCount );
+	} else {
+		// Complete to send, remove the URB from the first
+		OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+		pRegQueue = pWb35Reg->pRegFirst;
+		if (pRegQueue == pWb35Reg->pRegLast)
+			pWb35Reg->pRegLast = NULL;
+		pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
+		OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+		if (pWb35Reg->EP0VM_status) {
+#ifdef _PE_REG_DUMP_
+			WBDEBUG(("EP0 IoCompleteRoutine return error\n"));
+			DebugUsbdStatusInformation( pWb35Reg->EP0VM_status );
+#endif
+			pWb35Reg->EP0vm_state = VM_STOP;
+			pHwData->SurpriseRemove = 1;
+		} else {
+			// Success. Update the result
+
+			// Start the next send
+			Wb35Reg_EP0VM(pHwData);
+		}
+
+   		kfree(pRegQueue);
+	}
+
+	usb_free_urb(pUrb);
+}
+
+
+void
+Wb35Reg_destroy(phw_data_t pHwData)
+{
+	PWB35REG	pWb35Reg = &pHwData->Wb35Reg;
+	PURB		pUrb;
+	PREG_QUEUE	pRegQueue;
+
+
+	Uxx_power_off_procedure(pHwData);
+
+	// Wait for Reg operation completed
+	do {
+		OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
+	} while (pWb35Reg->EP0vm_state != VM_STOP);
+	OS_SLEEP(10000);  // Delay for waiting function enter 940623.1.b
+
+	// Release all the data in RegQueue
+	OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+	pRegQueue = pWb35Reg->pRegFirst;
+	while (pRegQueue) {
+		if (pRegQueue == pWb35Reg->pRegLast)
+			pWb35Reg->pRegLast = NULL;
+		pWb35Reg->pRegFirst = pWb35Reg->pRegFirst->Next;
+
+		pUrb = pRegQueue->pUrb;
+		OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+		if (pUrb) {
+			usb_free_urb(pUrb);
+			kfree(pRegQueue);
+		} else {
+			#ifdef _PE_REG_DUMP_
+			WBDEBUG(("EP0 queue release error\n"));
+			#endif
+		}
+		OS_SPIN_LOCK_ACQUIRED( &pWb35Reg->EP0VM_spin_lock );
+
+		pRegQueue = pWb35Reg->pRegFirst;
+	}
+	OS_SPIN_LOCK_RELEASED( &pWb35Reg->EP0VM_spin_lock );
+
+	// Free resource
+	OS_SPIN_LOCK_FREE(  &pWb35Reg->EP0VM_spin_lock );
+}
+
+//====================================================================================
+// The function can be run in passive-level only.
+//====================================================================================
+unsigned char Wb35Reg_initial(phw_data_t pHwData)
+{
+	PWB35REG pWb35Reg=&pHwData->Wb35Reg;
+	u32 ltmp;
+	u32 SoftwareSet, VCO_trim, TxVga, Region_ScanInterval;
+
+	// Spin lock is acquired for read and write IRP command
+	OS_SPIN_LOCK_ALLOCATE( &pWb35Reg->EP0VM_spin_lock );
+
+	// Getting RF module type from EEPROM ------------------------------------
+	Wb35Reg_WriteSync( pHwData, 0x03b4, 0x080d0000 ); // Start EEPROM access + Read + address(0x0d)
+	Wb35Reg_ReadSync( pHwData, 0x03b4, &ltmp );
+
+	//Update RF module type and determine the PHY type by inf or EEPROM
+	pWb35Reg->EEPROMPhyType = (u8)( ltmp & 0xff );
+	// 0 V MAX2825, 1 V MAX2827, 2 V MAX2828, 3 V MAX2829
+	// 16V AL2230, 17 - AL7230, 18 - AL2230S
+	// 32 Reserved
+	// 33 - W89RF242(TxVGA 0~19), 34 - W89RF242(TxVGA 0~34)
+	if (pWb35Reg->EEPROMPhyType != RF_DECIDE_BY_INF) {
+		if( (pWb35Reg->EEPROMPhyType == RF_MAXIM_2825)	||
+			(pWb35Reg->EEPROMPhyType == RF_MAXIM_2827)	||
+			(pWb35Reg->EEPROMPhyType == RF_MAXIM_2828)	||
+			(pWb35Reg->EEPROMPhyType == RF_MAXIM_2829)	||
+			(pWb35Reg->EEPROMPhyType == RF_MAXIM_V1)	||
+			(pWb35Reg->EEPROMPhyType == RF_AIROHA_2230)	||
+			(pWb35Reg->EEPROMPhyType == RF_AIROHA_2230S)    ||
+			(pWb35Reg->EEPROMPhyType == RF_AIROHA_7230)	||
+			(pWb35Reg->EEPROMPhyType == RF_WB_242)		||
+			(pWb35Reg->EEPROMPhyType == RF_WB_242_1))
+			pHwData->phy_type = pWb35Reg->EEPROMPhyType;
+	}
+
+	// Power On procedure running. The relative parameter will be set according to phy_type
+	Uxx_power_on_procedure( pHwData );
+
+	// Reading MAC address
+	Uxx_ReadEthernetAddress( pHwData );
+
+	// Read VCO trim for RF parameter
+	Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08200000 );
+	Wb35Reg_ReadSync( pHwData, 0x03b4, &VCO_trim );
+
+	// Read Antenna On/Off of software flag
+	Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08210000 );
+	Wb35Reg_ReadSync( pHwData, 0x03b4, &SoftwareSet );
+
+	// Read TXVGA
+	Wb35Reg_WriteSync( pHwData, 0x03b4, 0x08100000 );
+	Wb35Reg_ReadSync( pHwData, 0x03b4, &TxVga );
+
+	// Get Scan interval setting from EEPROM offset 0x1c
+	Wb35Reg_WriteSync( pHwData, 0x03b4, 0x081d0000 );
+	Wb35Reg_ReadSync( pHwData, 0x03b4, &Region_ScanInterval );
+
+	// Update Ethernet address
+	memcpy( pHwData->CurrentMacAddress, pHwData->PermanentMacAddress, ETH_LENGTH_OF_ADDRESS );
+
+	// Update software variable
+	pHwData->SoftwareSet = (u16)(SoftwareSet & 0xffff);
+	TxVga &= 0x000000ff;
+	pHwData->PowerIndexFromEEPROM = (u8)TxVga;
+	pHwData->VCO_trim = (u8)VCO_trim & 0xff;
+	if (pHwData->VCO_trim == 0xff)
+		pHwData->VCO_trim = 0x28;
+
+	pWb35Reg->EEPROMRegion = (u8)(Region_ScanInterval>>8); // 20060720
+	if( pWb35Reg->EEPROMRegion<1 || pWb35Reg->EEPROMRegion>6 )
+		pWb35Reg->EEPROMRegion = REGION_AUTO;
+
+	//For Get Tx VGA from EEPROM 20060315.5 move here
+	GetTxVgaFromEEPROM( pHwData );
+
+	// Set Scan Interval
+	pHwData->Scan_Interval = (u8)(Region_ScanInterval & 0xff) * 10;
+	if ((pHwData->Scan_Interval == 2550) || (pHwData->Scan_Interval < 10)) // Is default setting 0xff * 10
+		pHwData->Scan_Interval = SCAN_MAX_CHNL_TIME;
+
+	// Initial register
+	RFSynthesizer_initial(pHwData);
+
+	BBProcessor_initial(pHwData); // Async write, must wait until complete
+
+	Wb35Reg_phy_calibration(pHwData);
+
+	Mxx_initial(pHwData);
+	Dxx_initial(pHwData);
+
+	if (pHwData->SurpriseRemove)
+		return FALSE;
+	else
+		return TRUE; // Initial fail
+}
+
+//===================================================================================
+//  CardComputeCrc --
+//
+//  Description:
+//    Runs the AUTODIN II CRC algorithm on buffer Buffer of length, Length.
+//
+//  Arguments:
+//    Buffer - the input buffer
+//    Length - the length of Buffer
+//
+//  Return Value:
+//    The 32-bit CRC value.
+//
+//  Note:
+//    This is adapted from the comments in the assembly language
+//    version in _GENREQ.ASM of the DWB NE1000/2000 driver.
+//==================================================================================
+u32
+CardComputeCrc(PUCHAR Buffer, u32 Length)
+{
+    u32 Crc, Carry;
+    u32  i, j;
+    u8 CurByte;
+
+    Crc = 0xffffffff;
+
+    for (i = 0; i < Length; i++) {
+
+        CurByte = Buffer[i];
+
+        for (j = 0; j < 8; j++) {
+
+            Carry     = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
+            Crc     <<= 1;
+            CurByte >>= 1;
+
+            if (Carry) {
+                Crc =(Crc ^ 0x04c11db6) | Carry;
+            }
+        }
+    }
+
+    return Crc;
+}
+
+
+//==================================================================
+// BitReverse --
+//   Reverse the bits in the input argument, dwData, which is
+//   regarded as a string of bits with the length, DataLength.
+//
+// Arguments:
+//   dwData     :
+//   DataLength :
+//
+// Return:
+//   The converted value.
+//==================================================================
+u32 BitReverse( u32 dwData, u32 DataLength)
+{
+	u32   HalfLength, i, j;
+	u32   BitA, BitB;
+
+	if ( DataLength <= 0)       return 0;   // No conversion is done.
+	dwData = dwData & (0xffffffff >> (32 - DataLength));
+
+	HalfLength = DataLength / 2;
+	for ( i = 0, j = DataLength-1 ; i < HalfLength; i++, j--)
+	{
+		BitA = GetBit( dwData, i);
+		BitB = GetBit( dwData, j);
+		if (BitA && !BitB) {
+			dwData = ClearBit( dwData, i);
+			dwData = SetBit( dwData, j);
+		} else if (!BitA && BitB) {
+			dwData = SetBit( dwData, i);
+			dwData = ClearBit( dwData, j);
+		} else
+		{
+			// Do nothing since these two bits are of the save values.
+		}
+	}
+
+	return dwData;
+}
+
+void Wb35Reg_phy_calibration(  phw_data_t pHwData )
+{
+	u32 BB3c, BB54;
+
+	if ((pHwData->phy_type == RF_WB_242) ||
+		(pHwData->phy_type == RF_WB_242_1)) {
+		phy_calibration_winbond ( pHwData, 2412 ); // Sync operation
+		Wb35Reg_ReadSync( pHwData, 0x103c, &BB3c );
+		Wb35Reg_ReadSync( pHwData, 0x1054, &BB54 );
+
+		pHwData->BB3c_cal = BB3c;
+		pHwData->BB54_cal = BB54;
+
+		RFSynthesizer_initial(pHwData);
+		BBProcessor_initial(pHwData); // Async operation
+
+		Wb35Reg_WriteSync( pHwData, 0x103c, BB3c );
+		Wb35Reg_WriteSync( pHwData, 0x1054, BB54 );
+	}
+}
+
+
diff --git a/drivers/staging/winbond/linux/wb35reg_f.h b/drivers/staging/winbond/linux/wb35reg_f.h
new file mode 100644
index 0000000..38e2906
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35reg_f.h
@@ -0,0 +1,56 @@
+//====================================
+// Interface function declare
+//====================================
+unsigned char Wb35Reg_initial(  phw_data_t pHwData );
+void Uxx_power_on_procedure(  phw_data_t pHwData );
+void Uxx_power_off_procedure(  phw_data_t pHwData );
+void Uxx_ReadEthernetAddress(  phw_data_t pHwData );
+void Dxx_initial(  phw_data_t pHwData );
+void Mxx_initial(  phw_data_t pHwData );
+void RFSynthesizer_initial(  phw_data_t pHwData );
+//void RFSynthesizer_SwitchingChannel(  phw_data_t pHwData,  s8 Channel );
+void RFSynthesizer_SwitchingChannel(  phw_data_t pHwData,  ChanInfo Channel );
+void BBProcessor_initial(  phw_data_t pHwData );
+void BBProcessor_RateChanging(  phw_data_t pHwData,  u8 rate ); // 20060613.1
+//void RF_RateChanging(  phw_data_t pHwData,  u8 rate ); // 20060626.5.c Add
+u8 RFSynthesizer_SetPowerIndex(  phw_data_t pHwData,  u8 PowerIndex );
+u8 RFSynthesizer_SetMaxim2828_24Power(  phw_data_t,  u8 index );
+u8 RFSynthesizer_SetMaxim2828_50Power(  phw_data_t,  u8 index );
+u8 RFSynthesizer_SetMaxim2827_24Power(  phw_data_t,  u8 index );
+u8 RFSynthesizer_SetMaxim2827_50Power(  phw_data_t,  u8 index );
+u8 RFSynthesizer_SetMaxim2825Power(  phw_data_t,  u8 index );
+u8 RFSynthesizer_SetAiroha2230Power(  phw_data_t,  u8 index );
+u8 RFSynthesizer_SetAiroha7230Power(  phw_data_t,  u8 index );
+u8 RFSynthesizer_SetWinbond242Power(  phw_data_t,  u8 index );
+void GetTxVgaFromEEPROM(  phw_data_t pHwData );
+void EEPROMTxVgaAdjust(  phw_data_t pHwData ); // 20060619.5 Add
+
+#define RFWriteControlData( _A, _V ) Wb35Reg_Write( _A, 0x0864, _V )
+
+void Wb35Reg_destroy(  phw_data_t pHwData );
+
+unsigned char Wb35Reg_Read(  phw_data_t pHwData,  u16 RegisterNo,   PULONG pRegisterValue );
+unsigned char Wb35Reg_ReadSync(  phw_data_t pHwData,  u16 RegisterNo,   PULONG pRegisterValue );
+unsigned char Wb35Reg_Write(  phw_data_t pHwData,  u16 RegisterNo,  u32 RegisterValue );
+unsigned char Wb35Reg_WriteSync(  phw_data_t pHwData,  u16 RegisterNo,  u32 RegisterValue );
+unsigned char Wb35Reg_WriteWithCallbackValue(  phw_data_t pHwData,
+								 u16 RegisterNo,
+								 u32 RegisterValue,
+								 PCHAR pValue,
+								 s8	Len);
+unsigned char Wb35Reg_BurstWrite(  phw_data_t pHwData,  u16 RegisterNo,  PULONG pRegisterData,  u8 NumberOfData,  u8 Flag );
+
+void Wb35Reg_EP0VM(  phw_data_t pHwData );
+void Wb35Reg_EP0VM_start(  phw_data_t pHwData );
+void Wb35Reg_EP0VM_complete(  PURB pUrb );
+
+u32 BitReverse( u32 dwData, u32 DataLength);
+
+void CardGetMulticastBit(   u8 Address[MAC_ADDR_LENGTH],  u8 *Byte,  u8 *Value );
+u32 CardComputeCrc(  PUCHAR Buffer,  u32 Length );
+
+void Wb35Reg_phy_calibration(  phw_data_t pHwData );
+void Wb35Reg_Update(  phw_data_t pHwData,  u16 RegisterNo,  u32 RegisterValue );
+unsigned char adjust_TXVGA_for_iq_mag(  phw_data_t pHwData );
+
+
diff --git a/drivers/staging/winbond/linux/wb35reg_s.h b/drivers/staging/winbond/linux/wb35reg_s.h
new file mode 100644
index 0000000..a7595b1
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35reg_s.h
@@ -0,0 +1,170 @@
+//=======================================================================================
+/*
+				HAL setting function
+
+		========================================
+		|Uxx| 	|Dxx|	|Mxx|	|BB|	|RF|
+		========================================
+			|					|
+		Wb35Reg_Read		Wb35Reg_Write
+
+		----------------------------------------
+				WbUsb_CallUSBDASync					supplied By WbUsb module
+*/
+//=======================================================================================
+
+#define     GetBit( dwData, i)      ( dwData & (0x00000001 << i))
+#define     SetBit( dwData, i)      ( dwData | (0x00000001 << i))
+#define     ClearBit( dwData, i)    ( dwData & ~(0x00000001 << i))
+
+#define		IGNORE_INCREMENT	0
+#define		AUTO_INCREMENT		0
+#define		NO_INCREMENT		1
+#define REG_DIRECTION(_x,_y)   ((_y)->DIRECT ==0 ? usb_rcvctrlpipe(_x,0) : usb_sndctrlpipe(_x,0))
+#define REG_BUF_SIZE(_x)       ((_x)->bRequest== 0x04 ? cpu_to_le16((_x)->wLength) : 4)
+
+// 20060613.2 Add the follow definition
+#define BB48_DEFAULT_AL2230_11B		0x0033447c
+#define BB4C_DEFAULT_AL2230_11B		0x0A00FEFF
+#define BB48_DEFAULT_AL2230_11G		0x00332C1B
+#define BB4C_DEFAULT_AL2230_11G		0x0A00FEFF
+
+
+#define BB48_DEFAULT_WB242_11B		0x00292315	//backoff  2dB
+#define BB4C_DEFAULT_WB242_11B		0x0800FEFF	//backoff  2dB
+//#define BB48_DEFAULT_WB242_11B		0x00201B11	//backoff  4dB
+//#define BB4C_DEFAULT_WB242_11B		0x0600FF00	//backoff  4dB
+#define BB48_DEFAULT_WB242_11G		0x00453B24
+#define BB4C_DEFAULT_WB242_11G		0x0E00FEFF
+
+//====================================
+// Default setting for Mxx
+//====================================
+#define DEFAULT_CWMIN					31		//(M2C) CWmin. Its value is in the range 0-31.
+#define DEFAULT_CWMAX					1023	//(M2C) CWmax. Its value is in the range 0-1023.
+#define DEFAULT_AID						1		//(M34) AID. Its value is in the range 1-2007.
+
+#ifdef _USE_FALLBACK_RATE_
+#define DEFAULT_RATE_RETRY_LIMIT		2		//(M38) as named
+#else
+#define DEFAULT_RATE_RETRY_LIMIT		7		//(M38) as named
+#endif
+
+#define DEFAULT_LONG_RETRY_LIMIT		7		//(M38) LongRetryLimit. Its value is in the range 0-15.
+#define DEFAULT_SHORT_RETRY_LIMIT		7		//(M38) ShortRetryLimit. Its value is in the range 0-15.
+#define DEFAULT_PIFST					25		//(M3C) PIFS Time. Its value is in the range 0-65535.
+#define DEFAULT_EIFST					354		//(M3C) EIFS Time. Its value is in the range 0-1048575.
+#define DEFAULT_DIFST					45		//(M3C) DIFS Time. Its value is in the range 0-65535.
+#define DEFAULT_SIFST					5		//(M3C) SIFS Time. Its value is in the range 0-65535.
+#define DEFAULT_OSIFST					10		//(M3C) Original SIFS Time. Its value is in the range 0-15.
+#define DEFAULT_ATIMWD					0		//(M40) ATIM Window. Its value is in the range 0-65535.
+#define DEFAULT_SLOT_TIME				20		//(M40) ($) SlotTime. Its value is in the range 0-255.
+#define DEFAULT_MAX_TX_MSDU_LIFE_TIME	512	//(M44) MaxTxMSDULifeTime. Its value is in the range 0-4294967295.
+#define DEFAULT_BEACON_INTERVAL			500		//(M48) Beacon Interval. Its value is in the range 0-65535.
+#define DEFAULT_PROBE_DELAY_TIME		200		//(M48) Probe Delay Time. Its value is in the range 0-65535.
+#define DEFAULT_PROTOCOL_VERSION		0		//(M4C)
+#define DEFAULT_MAC_POWER_STATE			2		//(M4C) 2: MAC at power active
+#define DEFAULT_DTIM_ALERT_TIME			0
+
+
+typedef struct _REG_QUEUE
+{
+    struct  urb *pUrb;
+	void*	pUsbReq;
+	void*	Next;
+	union
+	{
+		u32	VALUE;
+		PULONG	pBuffer;
+	};
+	u8	RESERVED[4];// space reserved for communication
+
+    u16	INDEX; // For storing the register index
+    u8	RESERVED_VALID;	//Indicate whether the RESERVED space is valid at this command.
+	u8	DIRECT; // 0:In   1:Out
+
+} REG_QUEUE, *PREG_QUEUE;
+
+//====================================
+// Internal variable for module
+//====================================
+#define MAX_SQ3_FILTER_SIZE		5
+typedef struct _WB35REG
+{
+	//============================
+	// Register Bank backup
+	//============================
+	u32	U1B0;			//bit16 record the h/w radio on/off status
+	u32	U1BC_LEDConfigure;
+	u32	D00_DmaControl;
+	u32	M00_MacControl;
+	union {
+		struct {
+			u32	M04_MulticastAddress1;
+			u32	M08_MulticastAddress2;
+		};
+		u8		Multicast[8];	// contents of card multicast registers
+	};
+
+	u32	M24_MacControl;
+	u32	M28_MacControl;
+	u32	M2C_MacControl;
+	u32	M38_MacControl;
+	u32	M3C_MacControl; // 20060214 backup only
+	u32	M40_MacControl;
+	u32	M44_MacControl; // 20060214 backup only
+	u32	M48_MacControl; // 20060214 backup only
+	u32	M4C_MacStatus;
+	u32	M60_MacControl; // 20060214 backup only
+	u32	M68_MacControl; // 20060214 backup only
+	u32	M70_MacControl; // 20060214 backup only
+	u32	M74_MacControl; // 20060214 backup only
+	u32	M78_ERPInformation;//930206.2.b
+	u32	M7C_MacControl; // 20060214 backup only
+	u32	M80_MacControl; // 20060214 backup only
+	u32	M84_MacControl; // 20060214 backup only
+	u32	M88_MacControl; // 20060214 backup only
+	u32	M98_MacControl; // 20060214 backup only
+
+	//[20040722 WK]
+	//Baseband register
+	u32	BB0C;	// Used for LNA calculation
+	u32	BB2C;	//
+	u32	BB30;	//11b acquisition control register
+	u32	BB3C;
+	u32	BB48;	// 20051221.1.a 20060613.1 Fix OBW issue of 11b/11g rate
+	u32	BB4C;	// 20060613.1  Fix OBW issue of 11b/11g rate
+	u32	BB50;	//mode control register
+	u32	BB54;
+	u32 	BB58;	//IQ_ALPHA
+	u32	BB5C;	// For test
+	u32	BB60;	// for WTO read value
+
+	//-------------------
+	// VM
+	//-------------------
+	OS_SPIN_LOCK	EP0VM_spin_lock; // 4B
+	u32	        EP0VM_status;//$$
+	PREG_QUEUE	    pRegFirst;
+	PREG_QUEUE	    pRegLast;
+	OS_ATOMIC       RegFireCount;
+
+	// Hardware status
+	u8	EP0vm_state;
+	u8	mac_power_save;
+	u8	EEPROMPhyType; // 0 ~ 15 for Maxim (0 Ä„V MAX2825, 1 Ä„V MAX2827, 2 Ä„V MAX2828, 3 Ä„V MAX2829),
+						   // 16 ~ 31 for Airoha (16 Ä„V AL2230, 11 - AL7230)
+						   // 32 ~ Reserved
+						   // 33 ~ 47 For WB242 ( 33 - WB242, 34 - WB242 with new Txvga 0.5 db step)
+						   // 48 ~ 255 ARE RESERVED.
+	u8	EEPROMRegion;	//Region setting in EEPROM
+
+	u32	SyncIoPause; // If user use the Sync Io to access Hw, then pause the async access
+
+	u8	LNAValue[4]; //Table for speed up running
+	u32	SQ3_filter[MAX_SQ3_FILTER_SIZE];
+	u32	SQ3_index;
+
+} WB35REG, *PWB35REG;
+
+
diff --git a/drivers/staging/winbond/linux/wb35rx.c b/drivers/staging/winbond/linux/wb35rx.c
new file mode 100644
index 0000000..26157eb
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35rx.c
@@ -0,0 +1,337 @@
+//============================================================================
+//  Copyright (c) 1996-2002 Winbond Electronic Corporation
+//
+//  Module Name:
+//    Wb35Rx.c
+//
+//  Abstract:
+//    Processing the Rx message from down layer
+//
+//============================================================================
+#include "sysdef.h"
+
+
+void Wb35Rx_start(phw_data_t pHwData)
+{
+	PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+	// Allow only one thread to run into the Wb35Rx() function
+	if (OS_ATOMIC_INC(pHwData->Adapter, &pWb35Rx->RxFireCounter) == 1) {
+		pWb35Rx->EP3vm_state = VM_RUNNING;
+		Wb35Rx(pHwData);
+	} else
+		OS_ATOMIC_DEC(pHwData->Adapter, &pWb35Rx->RxFireCounter);
+}
+
+// This function cannot reentrain
+void Wb35Rx(  phw_data_t pHwData )
+{
+	PWB35RX	pWb35Rx = &pHwData->Wb35Rx;
+	PUCHAR	pRxBufferAddress;
+	PURB	pUrb = (PURB)pWb35Rx->RxUrb;
+	int	retv;
+	u32	RxBufferId;
+
+	//
+	// Issuing URB
+	//
+	do {
+		if (pHwData->SurpriseRemove || pHwData->HwStop)
+			break;
+
+		if (pWb35Rx->rx_halt)
+			break;
+
+		// Get RxBuffer's ID
+		RxBufferId = pWb35Rx->RxBufferId;
+		if (!pWb35Rx->RxOwner[RxBufferId]) {
+			// It's impossible to run here.
+			#ifdef _PE_RX_DUMP_
+			WBDEBUG(("Rx driver fifo unavailable\n"));
+			#endif
+			break;
+		}
+
+		// Update buffer point, then start to bulkin the data from USB
+		pWb35Rx->RxBufferId++;
+		pWb35Rx->RxBufferId %= MAX_USB_RX_BUFFER_NUMBER;
+
+		pWb35Rx->CurrentRxBufferId = RxBufferId;
+
+		if (1 != OS_MEMORY_ALLOC((void* *)&pWb35Rx->pDRx, MAX_USB_RX_BUFFER)) {
+			printk("w35und: Rx memory alloc failed\n");
+			break;
+		}
+		pRxBufferAddress = pWb35Rx->pDRx;
+
+		usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
+				  usb_rcvbulkpipe(pHwData->WbUsb.udev, 3),
+				  pRxBufferAddress, MAX_USB_RX_BUFFER,
+				  Wb35Rx_Complete, pHwData);
+
+		pWb35Rx->EP3vm_state = VM_RUNNING;
+
+		retv = wb_usb_submit_urb(pUrb);
+
+		if (retv != 0) {
+			printk("Rx URB sending error\n");
+			break;
+		}
+		return;
+	} while(FALSE);
+
+	// VM stop
+	pWb35Rx->EP3vm_state = VM_STOP;
+	OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
+}
+
+void Wb35Rx_Complete(PURB pUrb)
+{
+	phw_data_t	pHwData = pUrb->context;
+	PWB35RX		pWb35Rx = &pHwData->Wb35Rx;
+	PUCHAR		pRxBufferAddress;
+	u32		SizeCheck;
+	u16		BulkLength;
+	u32		RxBufferId;
+	R00_DESCRIPTOR 	R00;
+
+	// Variable setting
+	pWb35Rx->EP3vm_state = VM_COMPLETED;
+	pWb35Rx->EP3VM_status = pUrb->status;//Store the last result of Irp
+
+	do {
+		RxBufferId = pWb35Rx->CurrentRxBufferId;
+
+		pRxBufferAddress = pWb35Rx->pDRx;
+		BulkLength = (u16)pUrb->actual_length;
+
+		// The IRP is completed
+		pWb35Rx->EP3vm_state = VM_COMPLETED;
+
+		if (pHwData->SurpriseRemove || pHwData->HwStop) // Must be here, or RxBufferId is invalid
+			break;
+
+		if (pWb35Rx->rx_halt)
+			break;
+
+		// Start to process the data only in successful condition
+		pWb35Rx->RxOwner[ RxBufferId ] = 0; // Set the owner to driver
+		R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
+
+		// The URB is completed, check the result
+		if (pWb35Rx->EP3VM_status != 0) {
+			#ifdef _PE_USB_STATE_DUMP_
+			WBDEBUG(("EP3 IoCompleteRoutine return error\n"));
+			DebugUsbdStatusInformation( pWb35Rx->EP3VM_status );
+			#endif
+			pWb35Rx->EP3vm_state = VM_STOP;
+			break;
+		}
+
+		// 20060220 For recovering. check if operating in single USB mode
+		if (!HAL_USB_MODE_BURST(pHwData)) {
+			SizeCheck = R00.R00_receive_byte_count;  //20060926 anson's endian
+			if ((SizeCheck & 0x03) > 0)
+				SizeCheck -= 4;
+			SizeCheck = (SizeCheck + 3) & ~0x03;
+			SizeCheck += 12; // 8 + 4 badbeef
+			if ((BulkLength > 1600) ||
+				(SizeCheck > 1600) ||
+				(BulkLength != SizeCheck) ||
+				(BulkLength == 0)) { // Add for fail Urb
+				pWb35Rx->EP3vm_state = VM_STOP;
+				pWb35Rx->Ep3ErrorCount2++;
+			}
+		}
+
+		// Indicating the receiving data
+		pWb35Rx->ByteReceived += BulkLength;
+		pWb35Rx->RxBufferSize[ RxBufferId ] = BulkLength;
+
+		if (!pWb35Rx->RxOwner[ RxBufferId ])
+			Wb35Rx_indicate(pHwData);
+
+		kfree(pWb35Rx->pDRx);
+		// Do the next receive
+		Wb35Rx(pHwData);
+		return;
+
+	} while(FALSE);
+
+	pWb35Rx->RxOwner[ RxBufferId ] = 1; // Set the owner to hardware
+	OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Rx->RxFireCounter );
+	pWb35Rx->EP3vm_state = VM_STOP;
+}
+
+//=====================================================================================
+unsigned char Wb35Rx_initial(phw_data_t pHwData)
+{
+	PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+	// Initial the Buffer Queue
+	Wb35Rx_reset_descriptor( pHwData );
+
+	pWb35Rx->RxUrb = wb_usb_alloc_urb(0);
+	return (!!pWb35Rx->RxUrb);
+}
+
+void Wb35Rx_stop(phw_data_t pHwData)
+{
+	PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+	// Canceling the Irp if already sends it out.
+	if (pWb35Rx->EP3vm_state == VM_RUNNING) {
+		usb_unlink_urb( pWb35Rx->RxUrb ); // Only use unlink, let Wb35Rx_destroy to free them
+		#ifdef _PE_RX_DUMP_
+		WBDEBUG(("EP3 Rx stop\n"));
+		#endif
+	}
+}
+
+// Needs process context
+void Wb35Rx_destroy(phw_data_t pHwData)
+{
+	PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+
+	do {
+		OS_SLEEP(10000); // Delay for waiting function enter 940623.1.a
+	} while (pWb35Rx->EP3vm_state != VM_STOP);
+	OS_SLEEP(10000); // Delay for waiting function exit 940623.1.b
+
+	if (pWb35Rx->RxUrb)
+		usb_free_urb( pWb35Rx->RxUrb );
+	#ifdef _PE_RX_DUMP_
+	WBDEBUG(("Wb35Rx_destroy OK\n"));
+	#endif
+}
+
+void Wb35Rx_reset_descriptor(  phw_data_t pHwData )
+{
+	PWB35RX pWb35Rx = &pHwData->Wb35Rx;
+	u32	i;
+
+	pWb35Rx->ByteReceived = 0;
+	pWb35Rx->RxProcessIndex = 0;
+	pWb35Rx->RxBufferId = 0;
+	pWb35Rx->EP3vm_state = VM_STOP;
+	pWb35Rx->rx_halt = 0;
+
+	// Initial the Queue. The last buffer is reserved for used if the Rx resource is unavailable.
+	for( i=0; i<MAX_USB_RX_BUFFER_NUMBER; i++ )
+		pWb35Rx->RxOwner[i] = 1;
+}
+
+void Wb35Rx_adjust(PDESCRIPTOR pRxDes)
+{
+	PULONG	pRxBufferAddress;
+	u32	DecryptionMethod;
+	u32	i;
+	u16	BufferSize;
+
+	DecryptionMethod = pRxDes->R01.R01_decryption_method;
+	pRxBufferAddress = pRxDes->buffer_address[0];
+	BufferSize = pRxDes->buffer_size[0];
+
+	// Adjust the last part of data. Only data left
+	BufferSize -= 4; // For CRC-32
+	if (DecryptionMethod)
+		BufferSize -= 4;
+	if (DecryptionMethod == 3) // For CCMP
+		BufferSize -= 4;
+
+	// Adjust the IV field which after 802.11 header and ICV field.
+	if (DecryptionMethod == 1) // For WEP
+	{
+		for( i=6; i>0; i-- )
+			pRxBufferAddress[i] = pRxBufferAddress[i-1];
+		pRxDes->buffer_address[0] = pRxBufferAddress + 1;
+		BufferSize -= 4; // 4 byte for IV
+	}
+	else if( DecryptionMethod ) // For TKIP and CCMP
+	{
+		for (i=7; i>1; i--)
+			pRxBufferAddress[i] = pRxBufferAddress[i-2];
+		pRxDes->buffer_address[0] = pRxBufferAddress + 2;//Update the descriptor, shift 8 byte
+		BufferSize -= 8; // 8 byte for IV + ICV
+	}
+	pRxDes->buffer_size[0] = BufferSize;
+}
+
+extern void packet_came(char *pRxBufferAddress, int PacketSize);
+
+
+u16 Wb35Rx_indicate(phw_data_t pHwData)
+{
+	DESCRIPTOR	RxDes;
+	PWB35RX	pWb35Rx = &pHwData->Wb35Rx;
+	PUCHAR		pRxBufferAddress;
+	u16		PacketSize;
+	u16		stmp, BufferSize, stmp2 = 0;
+	u32		RxBufferId;
+
+	// Only one thread be allowed to run into the following
+	do {
+		RxBufferId = pWb35Rx->RxProcessIndex;
+		if (pWb35Rx->RxOwner[ RxBufferId ]) //Owner by VM
+			break;
+
+		pWb35Rx->RxProcessIndex++;
+		pWb35Rx->RxProcessIndex %= MAX_USB_RX_BUFFER_NUMBER;
+
+		pRxBufferAddress = pWb35Rx->pDRx;
+		BufferSize = pWb35Rx->RxBufferSize[ RxBufferId ];
+
+		// Parse the bulkin buffer
+		while (BufferSize >= 4) {
+			if ((cpu_to_le32(*(PULONG)pRxBufferAddress) & 0x0fffffff) == RX_END_TAG) //Is ending? 921002.9.a
+				break;
+
+			// Get the R00 R01 first
+			RxDes.R00.value = le32_to_cpu(*(PULONG)pRxBufferAddress);
+			PacketSize = (u16)RxDes.R00.R00_receive_byte_count;
+			RxDes.R01.value = le32_to_cpu(*((PULONG)(pRxBufferAddress+4)));
+			// For new DMA 4k
+			if ((PacketSize & 0x03) > 0)
+				PacketSize -= 4;
+
+			// Basic check for Rx length. Is length valid?
+			if (PacketSize > MAX_PACKET_SIZE) {
+				#ifdef _PE_RX_DUMP_
+				WBDEBUG(("Serious ERROR : Rx data size too long, size =%d\n", PacketSize));
+				#endif
+
+				pWb35Rx->EP3vm_state = VM_STOP;
+				pWb35Rx->Ep3ErrorCount2++;
+				break;
+			}
+
+			// Start to process Rx buffer
+//			RxDes.Descriptor_ID = RxBufferId; // Due to synchronous indicate, the field doesn't necessary to use.
+			BufferSize -= 8; //subtract 8 byte for 35's USB header length
+			pRxBufferAddress += 8;
+
+			RxDes.buffer_address[0] = pRxBufferAddress;
+			RxDes.buffer_size[0] = PacketSize;
+			RxDes.buffer_number = 1;
+			RxDes.buffer_start_index = 0;
+			RxDes.buffer_total_size = RxDes.buffer_size[0];
+			Wb35Rx_adjust(&RxDes);
+
+			packet_came(pRxBufferAddress, PacketSize);
+
+			// Move RxBuffer point to the next
+			stmp = PacketSize + 3;
+			stmp &= ~0x03; // 4n alignment
+			pRxBufferAddress += stmp;
+			BufferSize -= stmp;
+			stmp2 += stmp;
+		}
+
+		// Reclaim resource
+		pWb35Rx->RxOwner[ RxBufferId ] = 1;
+	} while(TRUE);
+
+	return stmp2;
+}
+
+
diff --git a/drivers/staging/winbond/linux/wb35rx_f.h b/drivers/staging/winbond/linux/wb35rx_f.h
new file mode 100644
index 0000000..daa3e73
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35rx_f.h
@@ -0,0 +1,17 @@
+//====================================
+// Interface function declare
+//====================================
+void		Wb35Rx_reset_descriptor(  phw_data_t pHwData );
+unsigned char		Wb35Rx_initial(  phw_data_t pHwData );
+void		Wb35Rx_destroy(  phw_data_t pHwData );
+void		Wb35Rx_stop(  phw_data_t pHwData );
+u16		Wb35Rx_indicate(  phw_data_t pHwData );
+void		Wb35Rx_adjust(  PDESCRIPTOR pRxDes );
+void		Wb35Rx_start(  phw_data_t pHwData );
+
+void		Wb35Rx(  phw_data_t pHwData );
+void		Wb35Rx_Complete(  PURB pUrb );
+
+
+
+
diff --git a/drivers/staging/winbond/linux/wb35rx_s.h b/drivers/staging/winbond/linux/wb35rx_s.h
new file mode 100644
index 0000000..53b831f
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35rx_s.h
@@ -0,0 +1,48 @@
+//============================================================================
+// wb35rx.h --
+//============================================================================
+
+// Definition for this module used
+#define MAX_USB_RX_BUFFER	4096	// This parameter must be 4096 931130.4.f
+
+#define MAX_USB_RX_BUFFER_NUMBER	ETHERNET_RX_DESCRIPTORS		// Maximum 254, 255 is RESERVED ID
+#define RX_INTERFACE				0	// Interface 1
+#define RX_PIPE						2	// Pipe 3
+#define MAX_PACKET_SIZE				1600 //1568	// 8 + 1532 + 4 + 24(IV EIV MIC ICV CRC) for check DMA data 931130.4.g
+#define RX_END_TAG					0x0badbeef
+
+
+//====================================
+// Internal variable for module
+//====================================
+typedef struct _WB35RX
+{
+	u32			ByteReceived;// For calculating throughput of BulkIn
+	OS_ATOMIC		RxFireCounter;// Does Wb35Rx module fire?
+
+	u8	RxBuffer[ MAX_USB_RX_BUFFER_NUMBER ][ ((MAX_USB_RX_BUFFER+3) & ~0x03 ) ];
+	u16	RxBufferSize[ ((MAX_USB_RX_BUFFER_NUMBER+1) & ~0x01) ];
+	u8	RxOwner[ ((MAX_USB_RX_BUFFER_NUMBER+3) & ~0x03 ) ];//Ownership of buffer  0: SW 1:HW
+
+	u32	RxProcessIndex;//The next index to process
+	u32	RxBufferId;
+	u32	EP3vm_state;
+
+	u32	rx_halt; // For VM stopping
+
+	u16	MoreDataSize;
+	u16	PacketSize;
+
+	u32	CurrentRxBufferId; // For complete routine usage
+	u32	Rx3UrbCancel;
+
+	u32	LastR1; // For RSSI reporting
+	struct urb *				RxUrb;
+	u32		Ep3ErrorCount2; // 20060625.1 Usbd for Rx DMA error count
+
+	int		EP3VM_status;
+	PUCHAR	pDRx;
+
+} WB35RX, *PWB35RX;
+
+
diff --git a/drivers/staging/winbond/linux/wb35tx.c b/drivers/staging/winbond/linux/wb35tx.c
new file mode 100644
index 0000000..cf19c3b
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35tx.c
@@ -0,0 +1,313 @@
+//============================================================================
+//  Copyright (c) 1996-2002 Winbond Electronic Corporation
+//
+//  Module Name:
+//    Wb35Tx.c
+//
+//  Abstract:
+//    Processing the Tx message and put into down layer
+//
+//============================================================================
+#include "sysdef.h"
+
+
+unsigned char
+Wb35Tx_get_tx_buffer(phw_data_t pHwData, PUCHAR *pBuffer )
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+	*pBuffer = pWb35Tx->TxBuffer[0];
+	return TRUE;
+}
+
+void Wb35Tx_start(phw_data_t pHwData)
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+	// Allow only one thread to run into function
+	if (OS_ATOMIC_INC(pHwData->Adapter, &pWb35Tx->TxFireCounter) == 1) {
+		pWb35Tx->EP4vm_state = VM_RUNNING;
+		Wb35Tx(pHwData);
+	} else
+		OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
+}
+
+
+void Wb35Tx(phw_data_t pHwData)
+{
+	PWB35TX		pWb35Tx = &pHwData->Wb35Tx;
+	PADAPTER	Adapter = pHwData->Adapter;
+	PUCHAR		pTxBufferAddress;
+	PMDS		pMds = &Adapter->Mds;
+	struct urb *	pUrb = (struct urb *)pWb35Tx->Tx4Urb;
+	int         	retv;
+	u32		SendIndex;
+
+
+	if (pHwData->SurpriseRemove || pHwData->HwStop)
+		goto cleanup;
+
+	if (pWb35Tx->tx_halt)
+		goto cleanup;
+
+	// Ownership checking
+	SendIndex = pWb35Tx->TxSendIndex;
+	if (!pMds->TxOwner[SendIndex]) //No more data need to be sent, return immediately
+		goto cleanup;
+
+	pTxBufferAddress = pWb35Tx->TxBuffer[SendIndex];
+	//
+	// Issuing URB
+	//
+	usb_fill_bulk_urb(pUrb, pHwData->WbUsb.udev,
+			  usb_sndbulkpipe(pHwData->WbUsb.udev, 4),
+			  pTxBufferAddress, pMds->TxBufferSize[ SendIndex ],
+			  Wb35Tx_complete, pHwData);
+
+	pWb35Tx->EP4vm_state = VM_RUNNING;
+	retv = wb_usb_submit_urb( pUrb );
+	if (retv<0) {
+		printk("EP4 Tx Irp sending error\n");
+		goto cleanup;
+	}
+
+	// Check if driver needs issue Irp for EP2
+	pWb35Tx->TxFillCount += pMds->TxCountInBuffer[SendIndex];
+	if (pWb35Tx->TxFillCount > 12)
+		Wb35Tx_EP2VM_start( pHwData );
+
+	pWb35Tx->ByteTransfer += pMds->TxBufferSize[SendIndex];
+	return;
+
+ cleanup:
+	pWb35Tx->EP4vm_state = VM_STOP;
+	OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
+}
+
+
+void Wb35Tx_complete(struct urb * pUrb)
+{
+	phw_data_t	pHwData = pUrb->context;
+	PADAPTER	Adapter = (PADAPTER)pHwData->Adapter;
+	PWB35TX		pWb35Tx = &pHwData->Wb35Tx;
+	PMDS		pMds = &Adapter->Mds;
+
+	printk("wb35: tx complete\n");
+	// Variable setting
+	pWb35Tx->EP4vm_state = VM_COMPLETED;
+	pWb35Tx->EP4VM_status = pUrb->status; //Store the last result of Irp
+	pMds->TxOwner[ pWb35Tx->TxSendIndex ] = 0;// Set the owner. Free the owner bit always.
+	pWb35Tx->TxSendIndex++;
+	pWb35Tx->TxSendIndex %= MAX_USB_TX_BUFFER_NUMBER;
+
+	do {
+		if (pHwData->SurpriseRemove || pHwData->HwStop) // Let WbWlanHalt to handle surprise remove
+			break;
+
+		if (pWb35Tx->tx_halt)
+			break;
+
+		// The URB is completed, check the result
+		if (pWb35Tx->EP4VM_status != 0) {
+			printk("URB submission failed\n");
+			pWb35Tx->EP4vm_state = VM_STOP;
+			break; // Exit while(FALSE);
+		}
+
+		Mds_Tx(Adapter);
+		Wb35Tx(pHwData);
+		return;
+	} while(FALSE);
+
+	OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxFireCounter );
+	pWb35Tx->EP4vm_state = VM_STOP;
+}
+
+void Wb35Tx_reset_descriptor(  phw_data_t pHwData )
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+	pWb35Tx->TxSendIndex = 0;
+	pWb35Tx->tx_halt = 0;
+}
+
+unsigned char Wb35Tx_initial(phw_data_t pHwData)
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+	pWb35Tx->Tx4Urb = wb_usb_alloc_urb(0);
+	if (!pWb35Tx->Tx4Urb)
+		return FALSE;
+
+	pWb35Tx->Tx2Urb = wb_usb_alloc_urb(0);
+	if (!pWb35Tx->Tx2Urb)
+	{
+		usb_free_urb( pWb35Tx->Tx4Urb );
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+//======================================================
+void Wb35Tx_stop(phw_data_t pHwData)
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+	// Trying to canceling the Trp of EP2
+	if (pWb35Tx->EP2vm_state == VM_RUNNING)
+		usb_unlink_urb( pWb35Tx->Tx2Urb ); // Only use unlink, let Wb35Tx_destrot to free them
+	#ifdef _PE_TX_DUMP_
+	WBDEBUG(("EP2 Tx stop\n"));
+	#endif
+
+	// Trying to canceling the Irp of EP4
+	if (pWb35Tx->EP4vm_state == VM_RUNNING)
+		usb_unlink_urb( pWb35Tx->Tx4Urb ); // Only use unlink, let Wb35Tx_destrot to free them
+	#ifdef _PE_TX_DUMP_
+	WBDEBUG(("EP4 Tx stop\n"));
+	#endif
+}
+
+//======================================================
+void Wb35Tx_destroy(phw_data_t pHwData)
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+	// Wait for VM stop
+	do {
+		OS_SLEEP(10000);  // Delay for waiting function enter 940623.1.a
+	} while( (pWb35Tx->EP2vm_state != VM_STOP) && (pWb35Tx->EP4vm_state != VM_STOP) );
+	OS_SLEEP(10000);  // Delay for waiting function enter 940623.1.b
+
+	if (pWb35Tx->Tx4Urb)
+		usb_free_urb( pWb35Tx->Tx4Urb );
+
+	if (pWb35Tx->Tx2Urb)
+		usb_free_urb( pWb35Tx->Tx2Urb );
+
+	#ifdef _PE_TX_DUMP_
+	WBDEBUG(("Wb35Tx_destroy OK\n"));
+	#endif
+}
+
+void Wb35Tx_CurrentTime(phw_data_t pHwData, u32 TimeCount)
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+	unsigned char Trigger = FALSE;
+
+	if (pWb35Tx->TxTimer > TimeCount)
+		Trigger = TRUE;
+	else if (TimeCount > (pWb35Tx->TxTimer+500))
+		Trigger = TRUE;
+
+	if (Trigger) {
+		pWb35Tx->TxTimer = TimeCount;
+		Wb35Tx_EP2VM_start( pHwData );
+	}
+}
+
+void Wb35Tx_EP2VM_start(phw_data_t pHwData)
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+
+	// Allow only one thread to run into function
+	if (OS_ATOMIC_INC( pHwData->Adapter, &pWb35Tx->TxResultCount ) == 1) {
+		pWb35Tx->EP2vm_state = VM_RUNNING;
+		Wb35Tx_EP2VM( pHwData );
+	}
+	else
+		OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
+}
+
+
+void Wb35Tx_EP2VM(phw_data_t pHwData)
+{
+	PWB35TX pWb35Tx = &pHwData->Wb35Tx;
+	struct urb *	pUrb = (struct urb *)pWb35Tx->Tx2Urb;
+	PULONG	pltmp = (PULONG)pWb35Tx->EP2_buf;
+	int		retv;
+
+	do {
+		if (pHwData->SurpriseRemove || pHwData->HwStop)
+			break;
+
+		if (pWb35Tx->tx_halt)
+			break;
+
+		//
+		// Issuing URB
+		//
+		usb_fill_int_urb( pUrb, pHwData->WbUsb.udev, usb_rcvintpipe(pHwData->WbUsb.udev,2),
+				  pltmp, MAX_INTERRUPT_LENGTH, Wb35Tx_EP2VM_complete, pHwData, 32);
+
+		pWb35Tx->EP2vm_state = VM_RUNNING;
+		retv = wb_usb_submit_urb( pUrb );
+
+		if(retv < 0) {
+			#ifdef _PE_TX_DUMP_
+			WBDEBUG(("EP2 Tx Irp sending error\n"));
+			#endif
+			break;
+		}
+
+		return;
+
+	} while(FALSE);
+
+	pWb35Tx->EP2vm_state = VM_STOP;
+	OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
+}
+
+
+void Wb35Tx_EP2VM_complete(struct urb * pUrb)
+{
+	phw_data_t	pHwData = pUrb->context;
+	T02_DESCRIPTOR	T02, TSTATUS;
+	PADAPTER	Adapter = (PADAPTER)pHwData->Adapter;
+	PWB35TX		pWb35Tx = &pHwData->Wb35Tx;
+	PULONG		pltmp = (PULONG)pWb35Tx->EP2_buf;
+	u32		i;
+	u16		InterruptInLength;
+
+
+	// Variable setting
+	pWb35Tx->EP2vm_state = VM_COMPLETED;
+	pWb35Tx->EP2VM_status = pUrb->status;
+
+	do {
+		// For Linux 2.4. Interrupt will always trigger
+		if( pHwData->SurpriseRemove || pHwData->HwStop ) // Let WbWlanHalt to handle surprise remove
+			break;
+
+		if( pWb35Tx->tx_halt )
+			break;
+
+		//The Urb is completed, check the result
+		if (pWb35Tx->EP2VM_status != 0) {
+			WBDEBUG(("EP2 IoCompleteRoutine return error\n"));
+			pWb35Tx->EP2vm_state= VM_STOP;
+			break; // Exit while(FALSE);
+		}
+
+		// Update the Tx result
+		InterruptInLength = pUrb->actual_length;
+		// Modify for minimum memory access and DWORD alignment.
+		T02.value = cpu_to_le32(pltmp[0]) >> 8; // [31:8] -> [24:0]
+		InterruptInLength -= 1;// 20051221.1.c Modify the follow for more stable
+		InterruptInLength >>= 2; // InterruptInLength/4
+		for (i=1; i<=InterruptInLength; i++) {
+			T02.value |= ((cpu_to_le32(pltmp[i]) & 0xff) << 24);
+
+			TSTATUS.value = T02.value;  //20061009 anson's endian
+			Mds_SendComplete( Adapter, &TSTATUS );
+			T02.value = cpu_to_le32(pltmp[i]) >> 8;
+		}
+
+		return;
+	} while(FALSE);
+
+	OS_ATOMIC_DEC( pHwData->Adapter, &pWb35Tx->TxResultCount );
+	pWb35Tx->EP2vm_state = VM_STOP;
+}
+
diff --git a/drivers/staging/winbond/linux/wb35tx_f.h b/drivers/staging/winbond/linux/wb35tx_f.h
new file mode 100644
index 0000000..7705a84
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35tx_f.h
@@ -0,0 +1,20 @@
+//====================================
+// Interface function declare
+//====================================
+unsigned char Wb35Tx_initial(	 phw_data_t pHwData );
+void Wb35Tx_destroy(  phw_data_t pHwData );
+unsigned char Wb35Tx_get_tx_buffer(  phw_data_t pHwData,  PUCHAR *pBuffer );
+
+void Wb35Tx_EP2VM(  phw_data_t pHwData );
+void Wb35Tx_EP2VM_start(  phw_data_t pHwData );
+void Wb35Tx_EP2VM_complete(  PURB purb );
+
+void Wb35Tx_start(  phw_data_t pHwData );
+void Wb35Tx_stop(  phw_data_t pHwData );
+void Wb35Tx(  phw_data_t pHwData );
+void Wb35Tx_complete(  PURB purb );
+void Wb35Tx_reset_descriptor(  phw_data_t pHwData );
+
+void Wb35Tx_CurrentTime(  phw_data_t pHwData,  u32 TimeCount );
+
+
diff --git a/drivers/staging/winbond/linux/wb35tx_s.h b/drivers/staging/winbond/linux/wb35tx_s.h
new file mode 100644
index 0000000..ac43257
--- /dev/null
+++ b/drivers/staging/winbond/linux/wb35tx_s.h
@@ -0,0 +1,47 @@
+//====================================
+// IS89C35 Tx related definition
+//====================================
+#define TX_INTERFACE			0	// Interface 1
+#define TX_PIPE					3	// endpoint 4
+#define TX_INTERRUPT			1	// endpoint 2
+#define MAX_INTERRUPT_LENGTH	64	// It must be 64 for EP2 hardware
+
+
+
+//====================================
+// Internal variable for module
+//====================================
+
+
+typedef struct _WB35TX
+{
+	// For Tx buffer
+	u8	TxBuffer[ MAX_USB_TX_BUFFER_NUMBER ][ MAX_USB_TX_BUFFER ];
+
+	// For Interrupt pipe
+	u8	EP2_buf[MAX_INTERRUPT_LENGTH];
+
+	OS_ATOMIC	TxResultCount;// For thread control of EP2 931130.4.m
+	OS_ATOMIC	TxFireCounter;// For thread control of EP4 931130.4.n
+	u32			ByteTransfer;
+
+	u32	    TxSendIndex;// The next index of Mds array to be sent
+	u32	    EP2vm_state; // for EP2vm state
+	u32	    EP4vm_state; // for EP4vm state
+	u32	    tx_halt; // Stopping VM
+
+	struct urb *				Tx4Urb;
+	struct urb *				Tx2Urb;
+
+	int		EP2VM_status;
+	int		EP4VM_status;
+
+	u32	TxFillCount; // 20060928
+	u32	TxTimer; // 20060928 Add if sending packet not great than 13
+
+} WB35TX, *PWB35TX;
+
+
+
+
+
diff --git a/drivers/staging/winbond/linux/wbusb.c b/drivers/staging/winbond/linux/wbusb.c
new file mode 100644
index 0000000..cbad5fb
--- /dev/null
+++ b/drivers/staging/winbond/linux/wbusb.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright 2008 Pavel Machek <pavel@suse.cz>
+ *
+ * Distribute under GPLv2.
+ */
+#include "sysdef.h"
+#include <net/mac80211.h>
+
+
+MODULE_AUTHOR( DRIVER_AUTHOR );
+MODULE_DESCRIPTION( DRIVER_DESC );
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.1");
+
+
+//============================================================
+// vendor ID and product ID can into here for others
+//============================================================
+static struct usb_device_id Id_Table[] =
+{
+  {USB_DEVICE( 0x0416, 0x0035 )},
+  {USB_DEVICE( 0x18E8, 0x6201 )},
+  {USB_DEVICE( 0x18E8, 0x6206 )},
+  {USB_DEVICE( 0x18E8, 0x6217 )},
+  {USB_DEVICE( 0x18E8, 0x6230 )},
+  {USB_DEVICE( 0x18E8, 0x6233 )},
+  {USB_DEVICE( 0x1131, 0x2035 )},
+  {  }
+};
+
+MODULE_DEVICE_TABLE(usb, Id_Table);
+
+static struct usb_driver wb35_driver = {
+	.name =		"w35und",
+	.probe =	wb35_probe,
+	.disconnect = wb35_disconnect,
+	.id_table = Id_Table,
+};
+
+static const struct ieee80211_rate wbsoft_rates[] = {
+	{ .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+};
+
+static const struct ieee80211_channel wbsoft_channels[] = {
+	{ .center_freq = 2412},
+};
+
+int wbsoft_enabled;
+struct ieee80211_hw *my_dev;
+PADAPTER my_adapter;
+
+static int wbsoft_add_interface(struct ieee80211_hw *dev,
+				 struct ieee80211_if_init_conf *conf)
+{
+	printk("wbsoft_add interface called\n");
+	return 0;
+}
+
+static void wbsoft_remove_interface(struct ieee80211_hw *dev,
+				     struct ieee80211_if_init_conf *conf)
+{
+	printk("wbsoft_remove interface called\n");
+}
+
+static int wbsoft_nop(void)
+{
+	printk("wbsoft_nop called\n");
+	return 0;
+}
+
+static void wbsoft_configure_filter(struct ieee80211_hw *dev,
+				     unsigned int changed_flags,
+				     unsigned int *total_flags,
+				     int mc_count, struct dev_mc_list *mclist)
+{
+	unsigned int bit_nr, new_flags;
+	u32 mc_filter[2];
+	int i;
+
+	new_flags = 0;
+
+	if (*total_flags & FIF_PROMISC_IN_BSS) {
+		new_flags |= FIF_PROMISC_IN_BSS;
+		mc_filter[1] = mc_filter[0] = ~0;
+	} else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) {
+		new_flags |= FIF_ALLMULTI;
+		mc_filter[1] = mc_filter[0] = ~0;
+	} else {
+		mc_filter[1] = mc_filter[0] = 0;
+		for (i = 0; i < mc_count; i++) {
+			if (!mclist)
+				break;
+			printk("Should call ether_crc here\n");
+			//bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26;
+			bit_nr = 0;
+
+			bit_nr &= 0x3F;
+			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+			mclist = mclist->next;
+		}
+	}
+
+	dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
+
+	*total_flags = new_flags;
+}
+
+static int wbsoft_tx(struct ieee80211_hw *dev, struct sk_buff *skb,
+		      struct ieee80211_tx_control *control)
+{
+	char *buffer = kmalloc(skb->len, GFP_ATOMIC);
+	printk("Sending frame %d bytes\n", skb->len);
+	memcpy(buffer, skb->data, skb->len);
+	if (1 == MLMESendFrame(my_adapter, buffer, skb->len, FRAME_TYPE_802_11_MANAGEMENT))
+		printk("frame sent ok (%d bytes)?\n", skb->len);
+	return NETDEV_TX_OK;
+}
+
+
+static int wbsoft_start(struct ieee80211_hw *dev)
+{
+	wbsoft_enabled = 1;
+	printk("wbsoft_start called\n");
+	return 0;
+}
+
+static int wbsoft_config(struct ieee80211_hw *dev, struct ieee80211_conf *conf)
+{
+	ChanInfo ch;
+	printk("wbsoft_config called\n");
+
+	ch.band = 1;
+	ch.ChanNo = 1;	/* Should use channel_num, or something, as that is already pre-translated */
+
+
+	hal_set_current_channel(&my_adapter->sHwData, ch);
+	hal_set_beacon_period(&my_adapter->sHwData, conf->beacon_int);
+//	hal_set_cap_info(&my_adapter->sHwData, ?? );
+// hal_set_ssid(phw_data_t pHwData,  PUCHAR pssid,  u8 ssid_len); ??
+	hal_set_accept_broadcast(&my_adapter->sHwData, 1);
+	hal_set_accept_promiscuous(&my_adapter->sHwData,  1);
+	hal_set_accept_multicast(&my_adapter->sHwData,  1);
+	hal_set_accept_beacon(&my_adapter->sHwData,  1);
+	hal_set_radio_mode(&my_adapter->sHwData,  0);
+	//hal_set_antenna_number(  phw_data_t pHwData, u8 number )
+	//hal_set_rf_power(phw_data_t pHwData, u8 PowerIndex)
+
+
+//	hal_start_bss(&my_adapter->sHwData, WLAN_BSSTYPE_INFRASTRUCTURE);	??
+
+//void hal_set_rates(phw_data_t pHwData, PUCHAR pbss_rates,
+//		   u8 length, unsigned char basic_rate_set)
+
+	return 0;
+}
+
+static int wbsoft_config_interface(struct ieee80211_hw *dev,
+				    struct ieee80211_vif *vif,
+				    struct ieee80211_if_conf *conf)
+{
+	printk("wbsoft_config_interface called\n");
+	return 0;
+}
+
+static u64 wbsoft_get_tsf(struct ieee80211_hw *dev)
+{
+	printk("wbsoft_get_tsf called\n");
+	return 0;
+}
+
+static const struct ieee80211_ops wbsoft_ops = {
+	.tx			= wbsoft_tx,
+	.start			= wbsoft_start,		/* Start can be pretty much empty as we do WbWLanInitialize() during probe? */
+	.stop			= wbsoft_nop,
+	.add_interface		= wbsoft_add_interface,
+	.remove_interface	= wbsoft_remove_interface,
+	.config			= wbsoft_config,
+	.config_interface	= wbsoft_config_interface,
+	.configure_filter	= wbsoft_configure_filter,
+	.get_stats		= wbsoft_nop,
+	.get_tx_stats		= wbsoft_nop,
+	.get_tsf		= wbsoft_get_tsf,
+// conf_tx: hal_set_cwmin()/hal_set_cwmax;
+};
+
+struct wbsoft_priv {
+};
+
+
+int __init wb35_init(void)
+{
+	printk("[w35und]driver init\n");
+	return usb_register(&wb35_driver);
+}
+
+void __exit wb35_exit(void)
+{
+	printk("[w35und]driver exit\n");
+	usb_deregister( &wb35_driver );
+}
+
+module_init(wb35_init);
+module_exit(wb35_exit);
+
+// Usb kernel subsystem will call this function when a new device is plugged into.
+int wb35_probe(struct usb_interface *intf, const struct usb_device_id *id_table)
+{
+	PADAPTER	Adapter;
+	PWBLINUX	pWbLinux;
+	PWBUSB		pWbUsb;
+        struct usb_host_interface *interface;
+	struct usb_endpoint_descriptor *endpoint;
+	int	i, ret = -1;
+	u32	ltmp;
+	struct usb_device *udev = interface_to_usbdev(intf);
+
+	usb_get_dev(udev);
+
+	printk("[w35und]wb35_probe ->\n");
+
+	do {
+		for (i=0; i<(sizeof(Id_Table)/sizeof(struct usb_device_id)); i++ ) {
+			if ((udev->descriptor.idVendor == Id_Table[i].idVendor) &&
+				(udev->descriptor.idProduct == Id_Table[i].idProduct)) {
+				printk("[w35und]Found supported hardware\n");
+				break;
+			}
+		}
+		if ((i == (sizeof(Id_Table)/sizeof(struct usb_device_id)))) {
+			#ifdef _PE_USB_INI_DUMP_
+			WBDEBUG(("[w35und] This is not the one we are interested about\n"));
+			#endif
+			return -ENODEV;
+		}
+
+		// 20060630.2 Check the device if it already be opened
+		ret = usb_control_msg(udev, usb_rcvctrlpipe( udev, 0 ),
+				      0x01, USB_TYPE_VENDOR|USB_RECIP_DEVICE|USB_DIR_IN,
+				      0x0, 0x400, &ltmp, 4, HZ*100 );
+		if( ret < 0 )
+			break;
+
+		ltmp = cpu_to_le32(ltmp);
+		if (ltmp)  // Is already initialized?
+			break;
+
+
+		Adapter = kzalloc(sizeof(ADAPTER), GFP_KERNEL);
+
+		my_adapter = Adapter;
+		pWbLinux = &Adapter->WbLinux;
+		pWbUsb = &Adapter->sHwData.WbUsb;
+		pWbUsb->udev = udev;
+
+	        interface = intf->cur_altsetting;
+	        endpoint = &interface->endpoint[0].desc;
+
+		if (endpoint[2].wMaxPacketSize == 512) {
+			printk("[w35und] Working on USB 2.0\n");
+			pWbUsb->IsUsb20 = 1;
+		}
+
+		if (!WbWLanInitialize(Adapter)) {
+			printk("[w35und]WbWLanInitialize fail\n");
+			break;
+		}
+
+		{
+			struct wbsoft_priv *priv;
+			struct ieee80211_hw *dev;
+			int res;
+
+			dev = ieee80211_alloc_hw(sizeof(*priv), &wbsoft_ops);
+
+			if (!dev) {
+				printk("w35und: ieee80211 alloc failed\n" );
+				BUG();
+			}
+
+			my_dev = dev;
+
+			SET_IEEE80211_DEV(dev, &udev->dev);
+			{
+				phw_data_t pHwData = &Adapter->sHwData;
+				unsigned char		dev_addr[MAX_ADDR_LEN];
+				hal_get_permanent_address(pHwData, dev_addr);
+				SET_IEEE80211_PERM_ADDR(dev, dev_addr);
+			}
+
+
+			dev->extra_tx_headroom = 12;	/* FIXME */
+			dev->flags = 0;
+
+			dev->channel_change_time = 1000;
+//			dev->max_rssi = 100;
+
+			dev->queues = 1;
+
+			static struct ieee80211_supported_band band;
+
+			band.channels = wbsoft_channels;
+			band.n_channels = ARRAY_SIZE(wbsoft_channels);
+			band.bitrates = wbsoft_rates;
+			band.n_bitrates = ARRAY_SIZE(wbsoft_rates);
+
+			dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &band;
+#if 0
+			wbsoft_modes[0].num_channels = 1;
+			wbsoft_modes[0].channels = wbsoft_channels;
+			wbsoft_modes[0].mode = MODE_IEEE80211B;
+			wbsoft_modes[0].num_rates = ARRAY_SIZE(wbsoft_rates);
+			wbsoft_modes[0].rates = wbsoft_rates;
+
+			res = ieee80211_register_hwmode(dev, &wbsoft_modes[0]);
+			BUG_ON(res);
+#endif
+
+			res = ieee80211_register_hw(dev);
+			BUG_ON(res);
+		}
+
+		usb_set_intfdata( intf, Adapter );
+
+		printk("[w35und] _probe OK\n");
+		return 0;
+
+	} while(FALSE);
+
+	return -ENOMEM;
+}
+
+void packet_came(char *pRxBufferAddress, int PacketSize)
+{
+	struct sk_buff *skb;
+	struct ieee80211_rx_status rx_status = {0};
+
+	if (!wbsoft_enabled)
+		return;
+
+	skb = dev_alloc_skb(PacketSize);
+	if (!skb) {
+		printk("Not enough memory for packet, FIXME\n");
+		return;
+	}
+
+	memcpy(skb_put(skb, PacketSize),
+	       pRxBufferAddress,
+	       PacketSize);
+
+/*
+	rx_status.rate = 10;
+	rx_status.channel = 1;
+	rx_status.freq = 12345;
+	rx_status.phymode = MODE_IEEE80211B;
+*/
+
+	ieee80211_rx_irqsafe(my_dev, skb, &rx_status);
+}
+
+unsigned char
+WbUsb_initial(phw_data_t pHwData)
+{
+	return 1;
+}
+
+
+void
+WbUsb_destroy(phw_data_t pHwData)
+{
+}
+
+int wb35_open(struct net_device *netdev)
+{
+	PADAPTER Adapter = (PADAPTER)netdev->priv;
+	phw_data_t pHwData = &Adapter->sHwData;
+
+        netif_start_queue(netdev);
+
+	//TODO : put here temporarily
+	hal_set_accept_broadcast(pHwData, 1); // open accept broadcast
+
+	return 0;
+}
+
+int wb35_close(struct net_device *netdev)
+{
+	netif_stop_queue(netdev);
+	return 0;
+}
+
+void wb35_disconnect(struct usb_interface *intf)
+{
+	PWBLINUX pWbLinux;
+	PADAPTER Adapter = usb_get_intfdata(intf);
+	usb_set_intfdata(intf, NULL);
+
+        pWbLinux = &Adapter->WbLinux;
+
+	// Card remove
+	WbWlanHalt(Adapter);
+
+}
+
+
diff --git a/drivers/staging/winbond/linux/wbusb_f.h b/drivers/staging/winbond/linux/wbusb_f.h
new file mode 100644
index 0000000..cae29e1
--- /dev/null
+++ b/drivers/staging/winbond/linux/wbusb_f.h
@@ -0,0 +1,34 @@
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Copyright (c) 1996-2004 Winbond Electronic Corporation
+//
+//  Module Name:
+//    wbusb_f.h
+//
+//  Abstract:
+//    Linux driver.
+//
+//  Author:
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+int wb35_open(struct net_device *netdev);
+int wb35_close(struct net_device *netdev);
+unsigned char WbUsb_initial(phw_data_t pHwData);
+void WbUsb_destroy(phw_data_t pHwData);
+unsigned char WbWLanInitialize(PADAPTER Adapter);
+#define	WbUsb_Stop( _A )
+
+int wb35_probe(struct usb_interface *intf,const struct usb_device_id *id_table);
+void wb35_disconnect(struct usb_interface *intf);
+
+
+#define wb_usb_submit_urb(_A) usb_submit_urb(_A, GFP_ATOMIC)
+#define wb_usb_alloc_urb(_A) usb_alloc_urb(_A, GFP_ATOMIC)
+
+#define WbUsb_CheckForHang( _P )
+#define WbUsb_DetectStart( _P, _I )
+
+
+
+
+
diff --git a/drivers/staging/winbond/linux/wbusb_s.h b/drivers/staging/winbond/linux/wbusb_s.h
new file mode 100644
index 0000000..d5c1d53
--- /dev/null
+++ b/drivers/staging/winbond/linux/wbusb_s.h
@@ -0,0 +1,42 @@
+//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+// Copyright (c) 1996-2004 Winbond Electronic Corporation
+//
+//  Module Name:
+//    wbusb_s.h
+//
+//  Abstract:
+//    Linux driver.
+//
+//  Author:
+//
+//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+#define OS_SLEEP( _MT )	{ set_current_state(TASK_INTERRUPTIBLE); \
+			  schedule_timeout( _MT*HZ/1000000 ); }
+
+
+//---------------------------------------------------------------------------
+//  RW_CONTEXT --
+//
+//  Used to track driver-generated io irps
+//---------------------------------------------------------------------------
+typedef struct _RW_CONTEXT
+{
+	void*			pHwData;
+	PURB			pUrb;
+	void*			pCallBackFunctionParameter;
+} RW_CONTEXT, *PRW_CONTEXT;
+
+
+
+
+#define DRIVER_AUTHOR "Original by: Jeff Lee<YY_Lee@issc.com.tw> Adapted to 2.6.x by Costantino Leandro (Rxart Desktop) <le_costantino@pixartargentina.com.ar>"
+#define DRIVER_DESC   "IS89C35 802.11bg WLAN USB Driver"
+
+
+
+typedef struct _WBUSB {
+	u32	IsUsb20;
+	struct usb_device *udev;
+	u32	DetectCount;
+} WBUSB, *PWBUSB;