/* $Id: callbacks.c,v 1.2 2003/12/14 14:04:40 pb Exp $ */
/***************************************************************************************
	Copyright 2000-2001 ATMEL Corporation.
	
	This file is part of atmel wireless lan drivers.

		Atmel wireless lan drivers is free software; you can redistribute it and/or modify
		it under the terms of the GNU General Public License as published by
		the Free Software Foundation; either version 2 of the License, or
		(at your option) any later version.

		Atmel wireless lan drivers is distributed in the hope that it will be useful,
		but WITHOUT ANY WARRANTY; without even the implied warranty of
		MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
		GNU General Public License for more details.

		You should have received a copy of the GNU General Public License
		along with Atmel wireless lan drivers; if not, write to the Free Software
		Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA	02111-1307	USA

**************************************************************************************/
#include "vnetusba.h"
#ifdef CONFIG_X86
#include <asm/msr.h>
#endif
#include "command.h"
#include "mib.h"
#include "rx.h"
#include "frame.h"
#ifdef RFMD
#include "internalr.h"
#include "externalr.h"
#elif defined(R505)
#include "external505.h"
#include "internal505.h"
#elif defined(R505_2958)
#include "fw5052958.h"
#endif
/****************************************************************
	Get Command Status Callback handler. This polls the
	device for the status (Adapter->CommandStatus[5])of
	the pending command. When status is somethin else
	then idle or in progress if it is Complete it calls
	the next command or if the command failed it returns,
	it wakes any waiting queue and stops any device polling.
****************************************************************/
void GetCmd_callback(purb_t purb)
{
	PVNet_ADAPTER Adapter = (PVNet_ADAPTER) purb->context;
	ULONG flags;

	if (!Adapter)
		return;

	spin_lock_irqsave(Adapter->lock, flags);

	mod_use(0, Adapter);
	if (Adapter->StationState == STATION_STATE_EXITING) {
		if (waitqueue_active(Adapter->ctrl_wait)) {
			Adapter->CmdStatus[5] = CMD_STATUS_HOST_FAILURE;
			Adapter->flags &= ~INIT_PENDING;
			wake_up_interruptible(Adapter->ctrl_wait);
		}

		if (Adapter->CallbacksPending == 0)
			wake_up_interruptible(Adapter->remove_wait);
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}
	Adapter->flags &= ~CTRL_URB_SLEEP;

	switch (purb->status) {
	case USB_ST_NOERROR:
		break;
	case USB_ST_STALL:
	case USB_ST_TIMEOUT:
	default:
		Adapter->CmdStatus[5] = CMD_STATUS_HOST_FAILURE;
		break;
	}

	if (Adapter->CmdStatus[5] == CMD_STATUS_HOST_FAILURE) {
		if (waitqueue_active(Adapter->ctrl_wait))
			wake_up_interruptible(Adapter->ctrl_wait);
		Adapter->flags &= ~INIT_PENDING;
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	if ((Adapter->CmdStatus[5] == CMD_STATUS_IDLE) ||
	    (Adapter->CmdStatus[5] == CMD_STATUS_IN_PROGRESS)) {
		spin_unlock_irqrestore(Adapter->lock, flags);
		GetCmdStatus(Adapter, Adapter->LastCommand[0]);
		return;
	}

	Adapter->flags &= ~GetCommandPedding;

	if (Adapter->CmdStatus[5] != CMD_STATUS_COMPLETE) {
		if (Adapter->LastCommand[0] == CMD_Join){
                    if((Adapter->OperatingMode == INFRASTRUCTURE_MODE) && (Adapter->CmdStatus[5] == CMD_STATUS_TIME_OUT)) {
			Adapter->StationState = STATION_STATE_SCANNING;
			UsbScan(Adapter);
			spin_unlock_irqrestore(Adapter->lock, flags);
			return;
                    }else if ((Adapter->OperatingMode == AD_HOC_MODE) && (Adapter->CmdStatus[5] == CMD_STATUS_TIME_OUT)) {
                                UsbStartIBSS(Adapter);
                                ChangeState(Adapter, STATION_STATE_READY);
                                spin_unlock_irqrestore(Adapter->lock, flags);
                                return;

                    }
		}
		Adapter->flags &= ~INIT_PENDING;
		if (waitqueue_active(Adapter->ctrl_wait))
			wake_up_interruptible(Adapter->ctrl_wait);
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	if (Adapter->flags & IOCTL_SLEEPING) {
		Adapter->flags &= ~IOCTL_SLEEPING;
		wake_up_interruptible(Adapter->ctrl_wait);
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	switch (Adapter->LastCommand[0]) {

	case CMD_Scan:

		dbgcond(DBG_CMD_CB, "last cmd: Scan\n");
		if (Adapter->flags & SITE_SURVEY_REQUEST) {
		    Adapter->flags &= ~SITE_SURVEY_REQUEST;
			ChangeState(Adapter, Adapter->TempState);
       // UsbJoin(Adapter);
		    break;
		}
                if (Adapter->IsInternationalScanEnabled){
                    GetChannelList(Adapter);
                    break;
                }else { 
                            UsbSelectBSS(Adapter);
                            dbgcond(DBG_SCAN,
                            "!Found : %d BSSID's , Desired BSSID %s\n",
                            Adapter->SiteS.BSSInList,
                            Adapter->
                            flags & BSSIDfound ? "found" : "not found");

                    if ((Adapter->SiteS.BSSInList == 0) || (!(Adapter->flags & BSSIDfound))) {	// either there isn't any wireless station near or the desired ssid isn't found.
                            if (Adapter->OperatingMode == INFRASTRUCTURE_MODE) {
                                    DropPendingTxPackets(Adapter);
                                    Adapter->StationState =
                                        STATION_STATE_SCANNING;
                                    UsbScan(Adapter);
                                    break;
                            }else if (Adapter->OperatingMode == AD_HOC_MODE){
                                    DropPendingTxPackets(Adapter);
                                    Adapter->StationState = STATION_STATE_READY;
                                    UsbStartIBSS(Adapter);
                                    printk(KERN_ALERT "EEEEEEEEEEEEEEEEEEEEE\n");
                                    printk(KERN_ALERT "EEEEEEEEEEEEEEEEEEEEE\n");
                            }
                    }

                    if (Adapter->PrivacyInvoked == 0) {
                            if (SetPreamble(Adapter) != 0) {
                                    spin_unlock_irqrestore(Adapter->lock,
                                                           flags);
                                    return;
                            }
                    } else {
                            dbgcond(DBG_SCAN, "WepIsSet is %s",
                                    Adapter->
                                    flags & WepIsSet ? "set" : "unset");
                            if (!(Adapter->flags & WepIsSet)) {
                                    if (SetWEPvalue(Adapter) != 0) {
                                            spin_unlock_irqrestore(Adapter->
                                                                   lock,
                                                                   flags);
                                            return;
                                    }
                            } else {
                                    Adapter->StationState = STATION_STATE_JOINING;
                                    UsbJoin(Adapter);
                                    spin_unlock_irqrestore(Adapter->lock,
                                                           flags);
                                    return;
                            }
                    }
		}
		break;

	case CMD_Join:
		dbgcond(DBG_CMD_CB, "last cmd: Join\n");
		if (Adapter->OperatingMode == AD_HOC_MODE) {
                            
			spin_unlock_irqrestore(Adapter->lock, flags);
			ChangeState(Adapter, STATION_STATE_READY);
			return;
		}else{
           	GetOperationalRates(Adapter);

    }
		break;
	case CMD_Startup:
		dbgcond(DBG_CMD_CB, "last cmd: Startup\n");
		Adapter->flags &= ~INIT_PENDING;
		wake_up_interruptible(Adapter->ctrl_wait);
		break;
	case CMD_SetMib:
		dbgcond(DBG_CMD_CB, "last cmd: SetMib\n");
		if (Adapter->LastCommand[1] == CMD_SetMac) {
			memcpy(Adapter->StationAddress, Adapter->tmpMAC,
			       6);
			break;
		}

		if (Adapter->LastCommand[1] == CMD_SetIRoaming) {
			UsbScan(Adapter);
			break;
		}
		
		if (Adapter->LastCommand[1] == CMD_SetPreamble) {
			SetFragThreshold(Adapter);
			break;
		}

		if (Adapter->LastCommand[1] == CMD_SetFrag) {
			SetRTSThreshold(Adapter);
			break;
		}

		if (Adapter->LastCommand[1] == CMD_SetRTS) {
			SetAutoRateFallback(Adapter);
			break;
		}

		if (Adapter->LastCommand[1] == CMD_SetARFB) {
			if ((Adapter->OperatingMode == AD_HOC_MODE) && (!(Adapter->flags & BSSIDfound))){
				UsbStartIBSS(Adapter);
      } else {
           if (Adapter->flags & BSSIDfound){
				    ChangeState(Adapter, STATION_STATE_JOINING);
				    UsbJoin(Adapter);
           }else {
				    ChangeState(Adapter, STATION_STATE_SCANNING);
            UsbScan(Adapter);
           }
			}
		}

		if (Adapter->LastCommand[1] == CMD_SetNewBSS_OK)
			break;

		if (Adapter->LastCommand[1] == CMD_WEP_SET) {
			if (Adapter->cmdhandler != NULL)
				Adapter->cmdhandler(Adapter);
			else {	//if(Adapter->LastCommand[1]=CMD_WEP_CHANGED)
				Adapter->flags |= WepIsSet;
				if (Adapter->flags & StationWasAssociated) {
					Adapter->flags &=
					    ~(StationWasAssociated |
					      StationIsAssociated);
					ChangeState(Adapter,
						    STATION_STATE_JOINING);
		dbgcond(DBG_CMD_CB, "Edw eisai 3\n");
					UsbJoin(Adapter);
				} else
					SetPreamble(Adapter);
			}
			break;
		}

		if (Adapter->LastCommand[1] == CMD_SetAssocID) {
		dbgcond(DBG_CMD_CB, "Edw eisai Mwrh 1\n");
			SetListenInterval(Adapter);
			break;
		}

		if (Adapter->LastCommand[1] == CMD_SetListenInterval) {
		dbgcond(DBG_CMD_CB, "Edw eisai Mwrh 2\n");
			SetPowerMgmtMode(Adapter);
			break;
		}
                
		if (Adapter->LastCommand[1] == CMD_SetPowerMgmtMode) {
		dbgcond(DBG_CMD_CB, "Edw eisai Mwrh 3\n");
			break;
		}

		break;
	case CMD_StartIBSS:
    memcpy(Adapter->SelectedSSID, Adapter->DesiredSSID, Adapter->DesiredSSIDsize);
    Adapter->SSID_size = Adapter->DesiredSSIDsize;

		dbgcond(DBG_CMD_CB, "last cmd: StartIBSS\n");
		GetMIBvalue(Adapter, 0x05, sizeof(MAC_MGMT_MIB));
		break;
  case CMD_SetRadioOn:
		dbgcond(DBG_CMD_CB, "Before SetIRoaming \n");
        	SetIRoaming(Adapter);
    break;
  case CMD_SetRadioOff:
        dbgcond(DBG_CMD_CB, "Radio Off Command\n");
    break;
	default:
		dbgcond(DBG_CMD_CB, "last cmd: unknown x%x\n",
			Adapter->LastCommand[0]);

		/* jal: what does this msg mean ??? */
		dbgcond(DBG_CMD_CB, "Which command?(0x%02x)",
			*((PUSHORT) ((PUCHAR) purb->setup_packet + 2)));

		if (waitqueue_active(Adapter->ctrl_wait)) {
			Adapter->flags &= ~INIT_PENDING;
			wake_up_interruptible(Adapter->ctrl_wait);
		}
		break;
	}
	spin_unlock_irqrestore(Adapter->lock, flags);
	return;
}

void ctrl_callback(purb_t purb)
{
	PVNet_ADAPTER Adapter = (PVNet_ADAPTER) purb->context;
	PUCHAR Buff = (PUCHAR) purb->transfer_buffer;
	ULONG flags;
        int i, FoundValidChannel;
	const static UCHAR ZeroArray[] = { 0, 0, 0, 0, 0, 0 };

	if (!Adapter)
		return;
	spin_lock_irqsave(Adapter->lock, flags);
	mod_use(0, Adapter);
	if (Adapter->StationState == STATION_STATE_EXITING) {
		if (waitqueue_active(Adapter->ctrl_wait)) {
			Adapter->CmdStatus[5] = CMD_STATUS_HOST_FAILURE;
			Adapter->flags &= ~INIT_PENDING;
			wake_up_interruptible(Adapter->ctrl_wait);
		}
		if (Adapter->CallbacksPending == 0)
			wake_up_interruptible(Adapter->remove_wait);
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	Adapter->flags &= ~CTRL_URB_SLEEP;
	// the only way to find out if the board is an EEPROM board
	// is if the GetOpMode command failed.
	if (Adapter->LastCommand[0] != CMD_GetOpMode) {
		switch (purb->status) {
		case USB_ST_NOERROR:
			break;
		case USB_ST_STALL:
			Adapter->flags |= NEED_CLEAR_HALT;
			spin_unlock_irqrestore(Adapter->lock, flags);
			wake_up_interruptible(Adapter->ctrl_wait);
			return;
		case USB_ST_TIMEOUT:
			Adapter->CmdStatus[5] = CMD_STATUS_HOST_FAILURE;
			break;
		default:
			dbgcond(DBG_CTRL_CB,
				"unknown status x%x, last cmd x%x\n",
				purb->status, Adapter->LastCommand[0]);
			goto LeaveError;
		}
	}

	switch (Adapter->LastCommand[0]) {
	case CMD_GetOpMode:
		dbgcond(DBG_CTRL_CB,
			"GetOpMode: ctrl_urb->status %d DevMode %d\n",
			Adapter->ctrl_urb->status, Adapter->DevMode);
		if ((Adapter->ctrl_urb->status != 0)
		    || ((Adapter->DevMode < 1)
			|| (Adapter->DevMode > 4))) {
			if (VNetAllocMem
			    ((void *) &Adapter->pDfu, sizeof(DFU)) != 0) {
				Adapter->flags &= ~INIT_PENDING;
				Adapter->CmdStatus[5] =
				    CMD_STATUS_HOST_FAILURE;
				wake_up_interruptible(Adapter->ctrl_wait);
				return;
			}

			memset(Adapter->pDfu, 0, sizeof(DFU));

#ifdef RFMD
			dbgcond(DBG_FW_DL, "Downloading RFMD");
			Adapter->pDfu->InternalFWSizeLeft = sizeof(InternalRFMD);
#elif defined(R505)                        
			dbgcond(DBG_FW_DL, "Downloading R505");
			Adapter->pDfu->InternalFWSizeLeft = sizeof(BuildInInternalFW);
#elif defined(R505_2958)                        
			dbgcond(DBG_FW_DL, "Downloading R505_2958");
			Adapter->pDfu->InternalFWSizeLeft = sizeof(BuildInInternalFW);
#endif

			if ((VNetAllocMem
			     ((void *) &Adapter->pDfu->InternalRom,
			      Adapter->pDfu->InternalFWSizeLeft) != 0)) {
				Adapter->flags &= ~INIT_PENDING;
				Adapter->CmdStatus[5] =
				    CMD_STATUS_HOST_FAILURE;
				wake_up_interruptible(Adapter->ctrl_wait);
				return;
			}

			/* jal: TODO: don't copy, set a pointer */
#ifdef RFMD
			memcpy(Adapter->pDfu->InternalRom, InternalRFMD, sizeof(InternalRFMD));
#elif defined(R505)
			memcpy(Adapter->pDfu->InternalRom, BuildInInternalFW, sizeof(BuildInInternalFW));
#elif defined(R505_2958)
			memcpy(Adapter->pDfu->InternalRom, BuildInInternalFW, sizeof(BuildInInternalFW));
#endif

			Adapter->flags |= INTERNAL_FW_DNLD;
			Adapter->StationState = STATION_STATE_FW_DOWNLOAD;
			GetDFUState(Adapter);
		} else {
			/* Adapter->ctrl_urb->status == 0 && 
			   Adapter->DevMode = 1,2,3 or 4 */

			switch (Adapter->DevMode) {
			case DeviceNetCardMode:
				if (GetHWCfg(Adapter) != 0) {
					Adapter->CmdStatus[5] =
					    STATION_STATE_INIT_FAILED;
					goto LeaveError;
				}
				break;
			case DeviceNOFlashNetCardMode:
				dbgcond(DBG_FW_DL, "sending external\n");
				if (!Adapter->pDfu) {
					if (VNetAllocMem
					    ((void *) &Adapter->pDfu,
					     sizeof(DFU)) != 0) {
						Adapter->flags &=
						    ~INIT_PENDING;
						Adapter->CmdStatus[5] =
						    CMD_STATUS_HOST_FAILURE;
						wake_up_interruptible
						    (Adapter->ctrl_wait);
						return;
					}
				}
					memset(Adapter->pDfu, 0,
					       sizeof(DFU));
#ifdef RFMD
                          Adapter->pDfu->ExternalFWSizeLeft = sizeof(ExternalRFMD);
#elif defined(R505)
                  Adapter->pDfu->ExternalFWSizeLeft = sizeof(BuildInExternalFW);
#elif defined(R505_2958)
                  Adapter->pDfu->ExternalFWSizeLeft = sizeof(BuildInExternalFW);
#endif
					if (VNetAllocMem
					    ((void *) &Adapter->pDfu->
					     ExternalRom,
					     Adapter->pDfu->
					     ExternalFWSizeLeft) != 0) {
						Adapter->flags &=
						    ~INIT_PENDING;
						Adapter->CmdStatus[5] =
						    CMD_STATUS_HOST_FAILURE;
						wake_up_interruptible
						    (Adapter->ctrl_wait);
						return;
					}
#ifdef RFMD
                  memcpy(Adapter->pDfu->ExternalRom, ExternalRFMD, sizeof(ExternalRFMD));
#elif defined(R505)
                  memcpy(Adapter->pDfu->ExternalRom, BuildInExternalFW, sizeof(BuildInExternalFW));
#elif defined(R505_2958)
                  memcpy(Adapter->pDfu->ExternalRom, BuildInExternalFW, sizeof(BuildInExternalFW));

#endif
				/* if(!Adapter->pDfu) */
				dbgcond(DBG_FW_DL,
					"start dwl ext. fw: %d byte\n",
					Adapter->pDfu->ExternalFWSizeLeft);
				DownLoadExternal(Adapter);
				break;
			case DeviceConfigurationMode:
				dbgcond(DBG_CTRL_CB,
					"Configuration Mode not"
					" supported in startup\n");
				break;
			case DeviceDFUMode:
				dbgcond(DBG_CTRL_CB,
					"DFU Mode not supported in startup\n");
				break;
			}
		}
		break;
	case CMD_GetHWCfg:	// GetHWCfg Ok
		// In the buffer's first 6 bytes the MAC waits.........
#if defined(RFMD)||defined(R505)||defined(R505_2958)
		memcpy((PUCHAR) Adapter->StationAddress,
		       (PUCHAR) Buff + 46, 6);
#else
		memcpy((PUCHAR) Adapter->StationAddress, (PUCHAR) Buff, 6);
#endif
		if ((Adapter->StationAddress[0] & 0x1) ||
		    (memcmp(Adapter->StationAddress, ZeroArray, 6) == 0)) {
			Adapter->StationAddress[0] = 0x00;
			Adapter->StationAddress[1] = 0x04;
			Adapter->StationAddress[2] = 0xac;
			Adapter->StationAddress[3] = 0x6c;
			Adapter->StationAddress[4] = 0x32;
			Adapter->StationAddress[5] = 0x70;
			dbgcond(DBG_CTRL_CB,
				"Using default MACAddress 00:04:AC:6C:32:70\n");
		}
		// Now for the F/W version
		if (GetMIBvalue(Adapter, 0x08, 4) != 0) {
			Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
			goto LeaveError;
		}
		break;
	case CMD_GetMib:	// GetMIB Ok
		// the setup packet is :
		// |byte 0|byte 1|byte 2|byte 3|byte 4|byte 5|byte 6|byte 7|
		// |-------------------------------------------------------|
		// |req.t.|req.  |              value            |              index            |       length          |
		// |-------------------------------------------------------|
		switch ((*((PUSHORT) ((PUCHAR) purb->setup_packet + 2))) >> 8)	// the last mib to usb
		{
		case 0x05:	//MAC_MIB
			if (Adapter->LastCommand[1] == CMD_NewBSS) {
				Adapter->LastCommand[1] =
				    CMD_NewBSS_NewBSSID;
				if (Adapter->ctrl_buff[54])
					GetMIBvalue(Adapter, 0x05,
						    sizeof(MAC_MGMT_MIB));
				break;
			} else {
				memcpy((PUCHAR) Adapter->CurrentBSSID,
				       (PUCHAR) & Buff[14], 6);
				dbgcond(DBG_CTRL_CB,
					"BSSID : %02x:%02x:%02x:%02x:%02x:%02x\n",
					Adapter->CurrentBSSID[0],
					Adapter->CurrentBSSID[1],
					Adapter->CurrentBSSID[2],
					Adapter->CurrentBSSID[3],
					Adapter->CurrentBSSID[4],
					Adapter->CurrentBSSID[5]);

				ChangeState(Adapter, STATION_STATE_READY);
				if (Adapter->LastCommand[1] ==
				    CMD_NewBSS_NewBSSID)
					SetMIB_NewBSSID_OK(Adapter);
			}
			break;
		case 0x07:
			// in the buffer in the byte 23 the regulatory domain exists.....
			if (Adapter->LastCommand[1] == CMD_GetRegDomain) {
				Adapter->RegDomain = (UCHAR) Buff[23];
				printk("Reg Domain\n");
				if (StartUp(Adapter) != 0) {
					Adapter->CmdStatus[5] =
					    STATION_STATE_INIT_FAILED;
					goto LeaveError;
				}
			} else if (Adapter->LastCommand[1] ==
				   CMD_GetOpRates) {
				memcpy(Adapter->OperationalRates,
				       &Buff[16], 4);
				Adapter->CurrentAuthentTransactionSeqNum =
				    0x0001;
				Adapter->AuthenticationRequestRetries = 0;
				Adapter->AssociationRequestRetries = 0;

				ChangeState(Adapter,
					    STATION_STATE_AUTHENTICATING);
				SendAuthRequest(Adapter, NULL, 0);
			}
			break;
		case 0x08:
			memcpy(Adapter->FwVersion, Buff,
			       sizeof(FW_VERSION_MIB));
			// we got the firmware version. Now we need the Regulatory Domain
			Adapter->LastCommand[1] = CMD_GetRegDomain;
			if (GetMIBvalue(Adapter, 0x07, sizeof(PHY_MIB)) !=
			    0) {
				Adapter->CmdStatus[5] =
				    STATION_STATE_INIT_FAILED;
				goto LeaveError;
			}
			break;
                case 0x09:
			if (Adapter->LastCommand[1] == CMD_GetChannelList) {
				printk("Get Channel List\n");
                                FoundValidChannel = 0;
                                for (i=0; i<14; i++){
                                    if ( Buff[14+i] == 1 ){
                                        
                                        FoundValidChannel = 1;
                                        Adapter->ChannelVector[i] = 1;
                                    }
				    dbgcond(DBG_SCAN,
					    "Channel List : %d \n", Buff[14+i]);
                                }
                                if (!FoundValidChannel){
                                    Adapter->flags &= ~FIRST_SCAN_DONE;
                                for (i=0; i<14; i++){
                                        Adapter->ChannelVector[i] = 0;
                                }

                                    UsbScan(Adapter);
                                } else{
				    UsbSelectBSS(Adapter);
				    dbgcond(DBG_SCAN,
					    "Found : %d BSSID's , Desired BSSID %s\n",
					    Adapter->SiteS.BSSInList,
					    Adapter->
					    flags & BSSIDfound ? "found" : "not found");

				    if ((Adapter->SiteS.BSSInList == 0) || (!(Adapter->flags & BSSIDfound))) {	// either there isn't any wireless station near or
					    // the desired ssid isn't found.
					    if (Adapter->OperatingMode == INFRASTRUCTURE_MODE) {
						    DropPendingTxPackets(Adapter);
						    Adapter->StationState =
							STATION_STATE_SCANNING;
						    UsbScan(Adapter);
						    break;
					    }
				    }

				    if (Adapter->PrivacyInvoked == 0) {
					    if (SetPreamble(Adapter) != 0) {
						    spin_unlock_irqrestore(Adapter->lock,
									   flags);
						    return;
					    }
				    } else {
					    dbgcond(DBG_SCAN, "WepIsSet is %s",
						    Adapter->
						    flags & WepIsSet ? "set" : "unset");
					    if (!(Adapter->flags & WepIsSet)) {
						    if (SetWEPvalue(Adapter) != 0) {
							    spin_unlock_irqrestore(Adapter->
										   lock,
										   flags);
							    return;
						    }
					    } else {
						    Adapter->StationState =
							STATION_STATE_JOINING;
						    UsbJoin(Adapter);
						    spin_unlock_irqrestore(Adapter->lock,
									   flags);
						    return;
					    }
				    }
				}
		}
		default:
			goto LeaveError;
		}
		break;
	case CMD_SetMib:
		if (GetCmdStatus(Adapter, CMD_SetMib) != 0) {
			Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
			goto LeaveError;
		}
		break;
	case CMD_Startup:
		// ok startup reached the other end (the device). Now we need to find
		// out the commandstatus for our startup......
		if (GetCmdStatus(Adapter, CMD_Startup) != 0) {
			Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
			goto LeaveError;
		}
		// Get the cmd status for StartUp. Vnet_probe wait_queue will awake in
		// GetCmd_Callback
		break;
	case CMD_Scan:		// Scan Ok
		//      Someone initiated a scan. vnet_probe, Authentication failure,e.t.c.
		dbgcond(DBG_SCAN | DBG_CTRL_CB,
			"Scan OK (rx_urb->status %d StationState %02x)\n",
			Adapter->rx_urb->status, Adapter->StationState);
		if (GetCmdStatus(Adapter, CMD_Scan) != 0) {
			Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
			goto LeaveError;
		}
		break;
	case CMD_Join:		// Join Ok
		dbgcond(DBG_JOIN | DBG_CTRL_CB,
			"Join OK (ctrl_urb->status %d flags %08lx)\n",
			Adapter->ctrl_urb->status, Adapter->flags);
		if (GetCmdStatus(Adapter, CMD_Join) != 0) {
			Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
			goto LeaveError;
		}
		break;
	case CMD_StartIBSS:	// StartIBSS Ok
		if (GetCmdStatus(Adapter, CMD_StartIBSS) != 0) {
			Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
			goto LeaveError;
		}
		break;
  case CMD_SetRadioOn:  // SetRadioOn Ok
       dbgusbnl("CMD_SetRadioOn")
       if (GetCmdStatus(Adapter, CMD_SetRadioOn) != 0) {
          dbgusbnl("CMD_SetRadioOn Failure!!!")
          Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
          goto LeaveError;
       }
       break;
  case CMD_SetRadioOff:  // SetRadioOn Ok
       dbgusbnl("CMD_SetRadioOff")
       if (GetCmdStatus(Adapter, CMD_SetRadioOn) != 0) {
          dbgusbnl("CMD_SetRadioOff Failure!!!")
          Adapter->CmdStatus[5] = STATION_STATE_INIT_FAILED;
          goto LeaveError;
       }
	default:
		break;
	}
	spin_unlock_irqrestore(Adapter->lock, flags);
	return;
      LeaveError:
	spin_unlock_irqrestore(Adapter->lock, flags);
	if (Adapter->flags & INIT_PENDING) {
		Adapter->flags &= ~INIT_PENDING;
		wake_up_interruptible(Adapter->ctrl_wait);
	}
}				/* end of ctrl_callback */

void RxCallback(purb_t purb)
{
	PVNet_ADAPTER Adapter = (PVNet_ADAPTER) purb->context;
	UCHAR FrameType, FrameSubType;
	ULONG flags, Crc;

	spin_lock_irqsave(Adapter->lock, flags);
	mod_use(0, Adapter);
	if (Adapter->StationState == STATION_STATE_EXITING) {
		if (Adapter->CallbacksPending == 0)
			wake_up_interruptible(Adapter->remove_wait);
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	if (!(Adapter->flags & VNET_RUNNING)) {
		Adapter->flags |= STOPPED_RX;
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	if (purb->status != 0) {
		if (purb->status != -EPIPE)
			goto POLL_BULK_IN;
		// if we are here we are in big trouble. The Bulk In Endpoint is
		// stalled and usb_clear_halt is not allowed in interrupt time
		// which means that we just stop the receiver.
		dbgcond(DBG_RX_CB, "bulk in endpoint stalled\n");
		Adapter->flags |= STOPPED_RX;
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	if (Adapter->RxInBuff.newbss)
		GetNewBSS(Adapter);

	memcpy(&Adapter->RxBuffUp, &Adapter->RxInBuff, sizeof(RX_BUFFER));
	if ((Adapter->RxInBuff.WLength != (purb->actual_length - 12)) ||
	    (Adapter->RxInBuff.WLength < 28)
	    || (purb->actual_length < 40)) {
		Adapter->Stats.RxDataPacketsError++;
		Adapter->netstats->rx_errors++;
		Adapter->flags &= ~RX_BUSY;
		goto POLL_BULK_IN;
	}

	if ((Adapter->PrivacyInvoked != 0) &&
	    ((Adapter->RxInBuff.WirelessPacket[1] & 0x40) != 0)) {
		Crc =
		    Calculate_CRC32(Adapter->RxInBuff.WirelessPacket + 24,
				    Adapter->RxInBuff.WLength - 24 - 4,
				    Adapter->CrcTable);
	} else {
		Crc = Calculate_CRC32(Adapter->RxInBuff.WirelessPacket,
				      Adapter->RxInBuff.WLength - 4,
				      Adapter->CrcTable);
	}

	if (Crc !=
	    *(ULONG *) (Adapter->RxInBuff.WirelessPacket +
			Adapter->RxInBuff.WLength - 4)) {
		dbgcond(DBG_CRC_CHECK | DBG_RX_CB, "Crc check failed\n");
		Adapter->Stats.RxDataPacketsError++;
		Adapter->netstats->rx_errors++;
		Adapter->flags &= ~RX_BUSY;
		goto POLL_BULK_IN;
	}
	FrameType = Adapter->RxInBuff.WirelessPacket[0] & C80211_TYPE_MASK;
	FrameSubType =
	    Adapter->RxInBuff.WirelessPacket[0] & C80211_SUBTYPE_MASK;

	Adapter->Rssi = (Adapter->Rssi + Adapter->RxInBuff.RSSI) / 2;
	Adapter->LinkQuality = (Adapter->LinkQuality + Adapter->RxInBuff.LinkQuality) / 2;

	if (FrameType == C80211_TYPE_DATA)
		RxData(Adapter);
	else if (FrameType == C80211_TYPE_MGMT)
		MgmtFrameProcessing(Adapter, FrameSubType);

      POLL_BULK_IN:
	FILL_BULK_URB(Adapter->rx_urb,
		      Adapter->usb,
		      usb_rcvbulkpipe(Adapter->usb, Adapter->BulkInAddr),
		      (PVOID) & Adapter->RxInBuff,
		      1550, RxCallback, Adapter);

	if (usb_submit_urb(Adapter->rx_urb) != 0)
		warn("Rx Failed.!");
	mod_use(1, Adapter);
	spin_unlock_irqrestore(Adapter->lock, flags);
}				/* end of RxCallback */

void TxOkCB(purb_t purb)
{
	PTX_LIST TxOk = (PTX_LIST) purb->context;
	PVNet_ADAPTER Adapter = (PVNet_ADAPTER) TxOk->Adapter;
	ULONG flags;

	dbgcond(DBG_TX_CB, "TxOk %p, length %u, skb %p, tx pending %d\n",
		TxOk, TxOk->length, TxOk->skb, Adapter->TxPacketsPending);

	spin_lock_irqsave(Adapter->lock, flags);

	mod_use(0, Adapter);	/* jal: necessary ??? */

	if (Adapter->StationState == STATION_STATE_EXITING) {
		if (Adapter->CallbacksPending == 0)
			wake_up_interruptible(Adapter->remove_wait);
		spin_unlock_irqrestore(Adapter->lock, flags);
		Adapter->flags &= ~TX_SLEEP;
		return;
	}

	if ((!TxOk) || !(Adapter->flags & VNET_RUNNING)) {
		spin_unlock_irqrestore(Adapter->lock, flags);
		Adapter->flags &= ~TX_SLEEP;
		return;
	}

	Adapter->TxPacketsPending--;
	if (TxOk->skb) {
		if (!purb->status) {
			Adapter->netstats->tx_packets++;
			Adapter->Stats.TxDataPacketsOk++;
			Adapter->netstats->tx_bytes += TxOk->length - 18 - 8;	/* magic nr ??? */
		} else {
			Adapter->netstats->tx_errors++;
			Adapter->Stats.TxDataPacketsError++;
		}
		VNetFreeSkb(TxOk->skb);
		TxOk->skb = NULL;
	}

	/* remove entry from TxList */
	list_del(&TxOk->tx_list);

	/* dealloc the buffers */
	assert(TxOk->tx_buff);
	if (TxOk->tx_buff)
		kfree(TxOk->tx_buff);
	assert(TxOk);
	if (TxOk)
		kfree(TxOk);

	Adapter->flags &= ~TX_SLEEP;
	/* try to send next packet */
	DeQueueTxPacket(Adapter, NULL);

	spin_unlock_irqrestore(Adapter->lock, flags);

}				/* end of TxOkCB */

/****************************************************************
	DFU Procedures handler. F/W download in EEPROM.
	Firmware upgrade in Parallel Flash not supported yet.
****************************************************************/
void DFUCallbacks(purb_t purb)
{
	PVNet_ADAPTER Adapter = (PVNet_ADAPTER) purb->context;
	UCHAR LoopNeeded = 0;
	ULONG flags;

	if (!Adapter)
		return;

	spin_lock_irqsave(Adapter->lock, flags);
	mod_use(0, Adapter);
	if (Adapter->StationState == STATION_STATE_EXITING) {
		if (Adapter->CallbacksPending == 0)
			wake_up_interruptible(Adapter->remove_wait);
		spin_unlock_irqrestore(Adapter->lock, flags);
		return;
	}

	Adapter->flags &= ~CTRL_URB_SLEEP;
	if (Adapter->flags & INTERNAL_FW_DNLD) {
		dbgcond(DBG_DFU_CB, "internal fw download, state %d\n",
			Adapter->pDfu->State);
		do {
			LoopNeeded = 0;
			if (Adapter->pDfu->ReSendState) {
				GetDFUState(Adapter);
				spin_unlock_irqrestore(Adapter->lock,
						       flags);
				return;
			}
			switch (Adapter->pDfu->State) {
			case STATE_appIDLE:
				Adapter->CmdStatus[5] =
				    CMD_STATUS_HOST_FAILURE;
				Adapter->flags &= ~INIT_PENDING;
				wake_up_interruptible(Adapter->ctrl_wait);
				break;
			case STATE_appDETACH:
				break;
			case STATE_dfuDNLOAD_IDLE:
			case STATE_dfuIDLE:
				DownLoadInternal(Adapter);
				Adapter->pDfu->ReSendState = 1;
				break;
			case STATE_dfuDNLOAD_SYNC:
				if (Adapter->LastCommand[0] !=
				    CMD_DFUStatus) {
					GetDFUStatus(Adapter);
					break;
				}
				Adapter->pDfu->State =
				    Adapter->pDfu->StatusBuf[4];
				Adapter->pDfu->TimeOut = 0;
				Adapter->pDfu->TimeOut |=
				    (ULONG) (Adapter->pDfu->
					     StatusBuf[3] << 16);
				Adapter->pDfu->TimeOut |=
				    (ULONG) (Adapter->pDfu->
					     StatusBuf[2] << 8);
				Adapter->pDfu->TimeOut |=
				    (ULONG) Adapter->pDfu->StatusBuf[1];
				Adapter->pDfu->ReSendState = 0;
				LoopNeeded = 1;
				break;
			case STATE_dfuDNBUSY:
				Adapter->pDfu->ReSendState = 1;
				mdelay(Adapter->pDfu->TimeOut);
				break;
			case STATE_dfuMANIFEST_SYNC:
				if (Adapter->LastCommand[0] !=
				    CMD_DFUStatus) {
					GetDFUStatus(Adapter);
					break;
				}
				Adapter->pDfu->State =
				    Adapter->pDfu->StatusBuf[4];
				Adapter->pDfu->TimeOut = 0;
				Adapter->pDfu->TimeOut |=
				    (ULONG) (Adapter->pDfu->
					     StatusBuf[3] << 16);
				Adapter->pDfu->TimeOut |=
				    (ULONG) (Adapter->pDfu->
					     StatusBuf[2] << 8);
				Adapter->pDfu->TimeOut |=
				    (ULONG) Adapter->pDfu->StatusBuf[1];
				Adapter->pDfu->ReSendState = 0;
				LoopNeeded = 1;
				mdelay(Adapter->pDfu->TimeOut);
				break;
			case STATE_dfuMANIFEST:	// Internal Rom Download Finished.
				Adapter->pDfu->ReSendState = 0;
				Adapter->flags &= ~INTERNAL_FW_DNLD;
				VNetFree(Adapter->pDfu->InternalRom);
				Remap(Adapter);
				break;
			case STATE_dfuMANIFEST_WAIT_RESET:
				LoopNeeded = 1;
				break;
			case STATE_dfuUPLOAD_IDLE:
				break;
			case STATE_dfuERROR:
				break;
			}
		} while (LoopNeeded);
		spin_unlock_irqrestore(Adapter->lock, flags);
	} else {
		dbgcond(DBG_DFU_CB, "external fw dwld, last cmd %d\n",
			Adapter->LastCommand[0]);

		switch (Adapter->LastCommand[0]) {
		case CMD_REMAP:
			// We must sleep for 2 seconds. schedule_timeout cannot be called in
			// interrupt time. (the same applies in sleep_on_timeout and
			// interruptible_sleep_on_timeout. So the only solution (as it seems)
			// is to add a timer for 1 sec and wait for its completion.
			dbgcond(DBG_DFU_CB, "To Remap\n");
			VnetTimer(Adapter, 20);
			dbgcond(DBG_DFU_CB, "timer set\n");
			break;
		case CMD_FWExternal:
			if (!Adapter->pDfu->BlockCnt) {	//external FW downloaded
				VNetFree(Adapter->pDfu->ExternalRom);
				VNetFree(Adapter->pDfu);
				Adapter->pDfu = NULL;
				GetHWCfg(Adapter);
				break;
			}
			DownLoadExternal(Adapter);
			break;
		}
		spin_unlock_irqrestore(Adapter->lock, flags);
	}
}				/* end of DFUCallbacks */
