From: Stephen Hemminger Date: Wed, 8 Sep 2010 21:46:36 +0000 (-0700) Subject: staging: Beeceem USB Wimax driver X-Git-Tag: v2.6.37-rc1~60^2~3^2~650 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f8942e07a3db9d82e8fb11d3d494876b8bae9ff9;p=profile%2Fivi%2Fkernel-x86-ivi.git staging: Beeceem USB Wimax driver The Sprint 4G network uses a Wimax dongle with Beecem chipset. The driver is typical of out of tree drivers, but maybe useful for people, and the hardware is readily available. Here is a staging ready version (i.e warts and all) 0. Started with Rel_5.2.7.3P1_USB from Sprint4GDeveloperPack-1.1 1. Consolidated files in staging 2. Remove Dos cr/lf 3. Remove unnecessary ioctl from usbbcm_fops Applied patches that were in the developer pack, surprising there were ones for 2.6.35 already. This is compile tested only, see TODO for what still needs to be done. Signed-off-by: Stephen Hemminger Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 35ad939..af9b8e4 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -161,5 +161,7 @@ source "drivers/staging/ath6kl/Kconfig" source "drivers/staging/keucr/Kconfig" +source "drivers/staging/bcm/Kconfig" + endif # !STAGING_EXCLUDE_BUILD endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index a33209b..cad2574 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -61,3 +61,4 @@ obj-$(CONFIG_WESTBRIDGE_ASTORIA) += westbridge/astoria/ obj-$(CONFIG_SBE_2T3E3) += sbe-2t3e3/ obj-$(CONFIG_ATH6K_LEGACY) += ath6kl/ obj-$(CONFIG_USB_ENESTORAGE) += keucr/ +obj-$(CONFIG_BCM_WIMAX) += bcm/ diff --git a/drivers/staging/bcm/Adapter.h b/drivers/staging/bcm/Adapter.h new file mode 100644 index 0000000..a7c0ce9 --- /dev/null +++ b/drivers/staging/bcm/Adapter.h @@ -0,0 +1,714 @@ +/*********************************** +* Adapter.h +************************************/ +#ifndef __ADAPTER_H__ +#define __ADAPTER_H__ + +#define MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES 256 +#include "Debug.h" + +typedef struct _LIST_ENTRY{ + struct _LIST_ENTRY *next; + struct _LIST_ENTRY *prev; +} LIST_ENTRY, *PLIST_ENTRY; + +typedef struct _BCM_LIST_ENTRY { + + LIST_ENTRY Link; + +} BCM_LIST_ENTRY, *PBCM_LIST_ENTRY; + +typedef enum _RCB_STATUS +{ + DRIVER_PROCESSED=1, + APPLICATION_PROCESSED +} RCB_STATUS, *PRCB_STATUS; + +#define fFILLED 1 +#define fEMPTY 0 + +struct _BCM_CB +{ + // The network packet that this RCB is receiving + PVOID pv_packet; + // Describes the length of the packet . + UINT ui_packet_length; + // Pointer to the first buffer in the packet (only one buffer for Rx) + PUCHAR buffer; + atomic_t status; + UINT filled; +} __attribute__((packed)); +typedef struct _BCM_CB BCM_CB,*PBCM_CB; + +typedef BCM_CB BCM_RCB, *PBCM_RCB; +typedef BCM_CB BCM_TCB, *PBCM_TCB; + +/* This is to be stored in the "pvOsDepData" of ADAPTER */ +typedef struct LINUX_DEP_DATA +{ + struct net_device *virtualdev; /* Our Interface (veth0) */ + struct net_device *actualdev; /* True Interface (eth0) */ + struct net_device_stats netstats; /* Net statistics */ + struct fasync_struct *async_queue; /* For asynchronus notification */ + +} LINUX_DEP_DATA, *PLINUX_DEP_DATA; + + +struct _LEADER +{ + USHORT Vcid; + USHORT PLength; + UCHAR Status; + UCHAR Unused[3]; +}__attribute__((packed)); +typedef struct _LEADER LEADER,*PLEADER; + +struct _PACKETTOSEND +{ + LEADER Leader; + UCHAR ucPayload; +}__attribute__((packed)); +typedef struct _PACKETTOSEND PACKETTOSEND, *PPACKETTOSEND; + + +struct _CONTROL_PACKET +{ + PVOID ControlBuff; + UINT ControlBuffLen; + struct _CONTROL_PACKET* next; +}__attribute__((packed)); +typedef struct _CONTROL_PACKET CONTROL_PACKET,*PCONTROL_PACKET; + + +struct link_request +{ + LEADER Leader; + UCHAR szData[4]; +}__attribute__((packed)); +typedef struct link_request LINK_REQUEST, *PLINK_REQUEST; + + +//classification extension is added +typedef struct _ADD_CONNECTION +{ + ULONG SrcIpAddressCount; + ULONG SrcIpAddress[MAX_CONNECTIONS]; + ULONG SrcIpMask[MAX_CONNECTIONS]; + + ULONG DestIpAddressCount; + ULONG DestIpAddress[MAX_CONNECTIONS]; + ULONG DestIpMask[MAX_CONNECTIONS]; + + USHORT SrcPortBegin; + USHORT SrcPortEnd; + + USHORT DestPortBegin; + USHORT DestPortEnd; + + UCHAR SrcTOS; + UCHAR SrcProtocol; +} ADD_CONNECTION,*PADD_CONNECTION; + + +typedef struct _CLASSIFICATION_RULE +{ + UCHAR ucIPSrcAddrLen; + UCHAR ucIPSrcAddr[32]; + UCHAR ucIPDestAddrLen; + UCHAR ucIPDestAddr[32]; + UCHAR ucSrcPortRangeLen; + UCHAR ucSrcPortRange[4]; + UCHAR ucDestPortRangeLen; + UCHAR ucDestPortRange[4]; + USHORT usVcid; +} CLASSIFICATION_RULE,*PCLASSIFICATION_RULE; + +typedef struct _CLASSIFICATION_ONLY +{ + USHORT usVcid; + ULONG DestIpAddress; + ULONG DestIpMask; + USHORT usPortLo; + USHORT usPortHi; + BOOLEAN bIpVersion; + UCHAR ucDestinationAddress[16]; +} CLASSIFICATION_ONLY, *PCLASSIFICATION_ONLY; + + +#define MAX_IP_RANGE_LENGTH 4 +#define MAX_PORT_RANGE 4 +#define MAX_PROTOCOL_LENGTH 32 +#define IPV6_ADDRESS_SIZEINBYTES 0x10 + +typedef union _U_IP_ADDRESS +{ + struct + { + ULONG ulIpv4Addr[MAX_IP_RANGE_LENGTH];//Source Ip Address Range + ULONG ulIpv4Mask[MAX_IP_RANGE_LENGTH];//Source Ip Mask Address Range + }; + struct + { + ULONG ulIpv6Addr[MAX_IP_RANGE_LENGTH * 4];//Source Ip Address Range + ULONG ulIpv6Mask[MAX_IP_RANGE_LENGTH * 4];//Source Ip Mask Address Range + + }; + struct + { + UCHAR ucIpv4Address[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS]; + UCHAR ucIpv4Mask[MAX_IP_RANGE_LENGTH * IP_LENGTH_OF_ADDRESS]; + }; + struct + { + UCHAR ucIpv6Address[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES]; + UCHAR ucIpv6Mask[MAX_IP_RANGE_LENGTH * IPV6_ADDRESS_SIZEINBYTES]; + }; +}U_IP_ADDRESS; +struct _packet_info; + +typedef struct _S_HDR_SUPRESSION_CONTEXTINFO +{ + + UCHAR ucaHdrSupressionInBuf[MAX_PHS_LENGTHS]; //Intermediate buffer to accumulate pkt Header for PHS + UCHAR ucaHdrSupressionOutBuf[MAX_PHS_LENGTHS + PHSI_LEN]; //Intermediate buffer containing pkt Header after PHS + +}S_HDR_SUPRESSION_CONTEXTINFO; + + +typedef struct _S_CLASSIFIER_RULE +{ + ULONG ulSFID; + UCHAR ucReserved[2]; + B_UINT16 uiClassifierRuleIndex; + BOOLEAN bUsed; + USHORT usVCID_Value; + B_UINT8 u8ClassifierRulePriority; //This field detemines the Classifier Priority + U_IP_ADDRESS stSrcIpAddress; + UCHAR ucIPSourceAddressLength;//Ip Source Address Length + + U_IP_ADDRESS stDestIpAddress; + UCHAR ucIPDestinationAddressLength;//Ip Destination Address Length + UCHAR ucIPTypeOfServiceLength;//Type of service Length + UCHAR ucTosLow;//Tos Low + UCHAR ucTosHigh;//Tos High + UCHAR ucTosMask;//Tos Mask + + UCHAR ucProtocolLength;//protocol Length + UCHAR ucProtocol[MAX_PROTOCOL_LENGTH];//protocol Length + USHORT usSrcPortRangeLo[MAX_PORT_RANGE]; + USHORT usSrcPortRangeHi[MAX_PORT_RANGE]; + UCHAR ucSrcPortRangeLength; + + USHORT usDestPortRangeLo[MAX_PORT_RANGE]; + USHORT usDestPortRangeHi[MAX_PORT_RANGE]; + UCHAR ucDestPortRangeLength; + + BOOLEAN bProtocolValid; + BOOLEAN bTOSValid; + BOOLEAN bDestIpValid; + BOOLEAN bSrcIpValid; + + //For IPv6 Addressing + UCHAR ucDirection; + BOOLEAN bIpv6Protocol; + UINT32 u32PHSRuleID; + S_PHS_RULE sPhsRule; + UCHAR u8AssociatedPHSI; + + //Classification fields for ETH CS + UCHAR ucEthCSSrcMACLen; + UCHAR au8EThCSSrcMAC[MAC_ADDRESS_SIZE]; + UCHAR au8EThCSSrcMACMask[MAC_ADDRESS_SIZE]; + UCHAR ucEthCSDestMACLen; + UCHAR au8EThCSDestMAC[MAC_ADDRESS_SIZE]; + UCHAR au8EThCSDestMACMask[MAC_ADDRESS_SIZE]; + UCHAR ucEtherTypeLen; + UCHAR au8EthCSEtherType[NUM_ETHERTYPE_BYTES]; + UCHAR usUserPriority[2]; + USHORT usVLANID; + USHORT usValidityBitMap; +}S_CLASSIFIER_RULE; +//typedef struct _S_CLASSIFIER_RULE S_CLASSIFIER_RULE; + +typedef struct _S_FRAGMENTED_PACKET_INFO +{ + BOOLEAN bUsed; + ULONG ulSrcIpAddress; + USHORT usIpIdentification; + S_CLASSIFIER_RULE *pstMatchedClassifierEntry; + BOOLEAN bOutOfOrderFragment; +}S_FRAGMENTED_PACKET_INFO,*PS_FRAGMENTED_PACKET_INFO; + +struct _packet_info +{ + //classification extension Rule + ULONG ulSFID; + USHORT usVCID_Value; + UINT uiThreshold; + // This field determines the priority of the SF Queues + B_UINT8 u8TrafficPriority; + + BOOLEAN bValid; + BOOLEAN bActive; + BOOLEAN bActivateRequestSent; + + B_UINT8 u8QueueType;//BE or rtPS + + UINT uiMaxBucketSize;//maximum size of the bucket for the queue + UINT uiCurrentQueueDepthOnTarget; + UINT uiCurrentBytesOnHost; + UINT uiCurrentPacketsOnHost; + UINT uiDroppedCountBytes; + UINT uiDroppedCountPackets; + UINT uiSentBytes; + UINT uiSentPackets; + UINT uiCurrentDrainRate; + UINT uiThisPeriodSentBytes; + LARGE_INTEGER liDrainCalculated; + UINT uiCurrentTokenCount; + LARGE_INTEGER liLastUpdateTokenAt; + UINT uiMaxAllowedRate; + UINT NumOfPacketsSent; + UCHAR ucDirection; + USHORT usCID; + S_MIBS_EXTSERVICEFLOW_PARAMETERS stMibsExtServiceFlowTable; + UINT uiCurrentRxRate; + UINT uiThisPeriodRxBytes; + UINT uiTotalRxBytes; + UINT uiTotalTxBytes; + UINT uiPendedLast; + UCHAR ucIpVersion; + + union + { + struct + { + struct sk_buff* FirstTxQueue; + struct sk_buff* LastTxQueue; + }; + struct + { + struct sk_buff* ControlHead; + struct sk_buff* ControlTail; + }; + }; + BOOLEAN bProtocolValid; + BOOLEAN bTOSValid; + BOOLEAN bDestIpValid; + BOOLEAN bSrcIpValid; + + BOOLEAN bActiveSet; + BOOLEAN bAdmittedSet; + BOOLEAN bAuthorizedSet; + BOOLEAN bClassifierPriority; + UCHAR ucServiceClassName[MAX_CLASS_NAME_LENGTH]; + BOOLEAN bHeaderSuppressionEnabled; + spinlock_t SFQueueLock; + void *pstSFIndication; + struct timeval stLastUpdateTokenAt; + atomic_t uiPerSFTxResourceCount; + UINT uiMaxLatency; + UCHAR bIPCSSupport; + UCHAR bEthCSSupport; +}; +typedef struct _packet_info PacketInfo; + + +typedef struct _PER_TARANG_DATA +{ + struct _PER_TARANG_DATA * next; + struct _MINI_ADAPTER * Adapter; + struct sk_buff* RxAppControlHead; + struct sk_buff* RxAppControlTail; + volatile INT AppCtrlQueueLen; + BOOLEAN MacTracingEnabled; + BOOLEAN bApplicationToExit; + S_MIBS_DROPPED_APP_CNTRL_MESSAGES stDroppedAppCntrlMsgs; + ULONG RxCntrlMsgBitMask; +} PER_TARANG_DATA, *PPER_TARANG_DATA; + + +#ifdef REL_4_1 +typedef struct _TARGET_PARAMS +{ + B_UINT32 m_u32CfgVersion; + + // Scanning Related Params + B_UINT32 m_u32CenterFrequency; + B_UINT32 m_u32BandAScan; + B_UINT32 m_u32BandBScan; + B_UINT32 m_u32BandCScan; + + // QoS Params + B_UINT32 m_u32minGrantsize; // size of minimum grant is 0 or 6 + B_UINT32 m_u32PHSEnable; + + // HO Params + B_UINT32 m_u32HoEnable; + B_UINT32 m_u32HoReserved1; + B_UINT32 m_u32HoReserved2; + + // Power Control Params + B_UINT32 m_u32MimoEnable; + B_UINT32 m_u32SecurityEnable; + /* + * bit 1: 1 Idlemode enable; + * bit 2: 1 Sleepmode Enable + */ + B_UINT32 m_u32PowerSavingModesEnable; + /* PowerSaving Mode Options: + bit 0 = 1: CPE mode - to keep pcmcia if alive; + bit 1 = 1: CINR reporing in Idlemode Msg + bit 2 = 1: Default PSC Enable in sleepmode*/ + B_UINT32 m_u32PowerSavingModeOptions; + + B_UINT32 m_u32ArqEnable; + + // From Version #3, the HARQ section renamed as general + B_UINT32 m_u32HarqEnable; + // EEPROM Param Location + B_UINT32 m_u32EEPROMFlag; + /* BINARY TYPE - 4th MSByte: + * Interface Type - 3rd MSByte: + * Vendor Type - 2nd MSByte + */ + // Unused - LSByte + B_UINT32 m_u32Customize; + B_UINT32 m_u32ConfigBW; /* In Hz */ + B_UINT32 m_u32ShutDownTimer; + + + B_UINT32 m_u32RadioParameter; + B_UINT32 m_u32PhyParameter1; + B_UINT32 m_u32PhyParameter2; + B_UINT32 m_u32PhyParameter3; + + /* in eval mode only; + * lower 16bits = basic cid for testing; + * then bit 16 is test cqich, + * bit 17 test init rang; + * bit 18 test periodic rang + * bit 19 is test harq ack/nack + */ + B_UINT32 m_u32TestOptions; + + B_UINT32 m_u32MaxMACDataperDLFrame; + B_UINT32 m_u32MaxMACDataperULFrame; + + B_UINT32 m_u32Corr2MacFlags; + + //adding driver params. + B_UINT32 HostDrvrConfig1; + B_UINT32 HostDrvrConfig2; + B_UINT32 HostDrvrConfig3; + B_UINT32 HostDrvrConfig4; + B_UINT32 HostDrvrConfig5; + B_UINT32 HostDrvrConfig6; + B_UINT32 m_u32SegmentedPUSCenable; + + // BAMC enable - but 4.x does not support this feature + // This is added just to sync 4.x and 5.x CFGs + B_UINT32 m_u32BandAMCEnable; +} STARGETPARAMS, *PSTARGETPARAMS; +#endif + +typedef struct _STTARGETDSXBUFFER +{ + ULONG ulTargetDsxBuffer; + B_UINT16 tid; + BOOLEAN valid; +}STTARGETDSXBUFFER, *PSTTARGETDSXBUFFER; + +typedef INT (*FP_FLASH_WRITE)(struct _MINI_ADAPTER*,UINT,PVOID); + +typedef INT (*FP_FLASH_WRITE_STATUS)(struct _MINI_ADAPTER*,UINT,PVOID); + +/** +Driver adapter data structure +*/ +struct _MINI_ADAPTER +{ + struct _MINI_ADAPTER *next; + PVOID pvOsDepData; + CHAR *caDsxReqResp; + atomic_t ApplicationRunning; + volatile INT CtrlQueueLen; + atomic_t AppCtrlQueueLen; + BOOLEAN AppCtrlQueueOverFlow; + atomic_t CurrentApplicationCount; + atomic_t RegisteredApplicationCount; + BOOLEAN TimerActive; + ULONG StatisticsPointer; + struct sk_buff *RxControlHead; + struct sk_buff *RxControlTail; +// spinlock_t RxControlQueuelock; + struct semaphore RxAppControlQueuelock; + struct semaphore fw_download_sema; + + PPER_TARANG_DATA pTarangs; + spinlock_t control_queue_lock; + wait_queue_head_t process_read_wait_queue; + ULONG bcm_jiffies; /* Store Jiffies value */ + + // the pointer to the first packet we have queued in send + // deserialized miniport support variables + atomic_t TotalPacketCount; + atomic_t TxPktAvail; + + // this to keep track of the Tx and Rx MailBox Registers. + atomic_t CurrNumFreeTxDesc; + // to keep track the no of byte recieved + atomic_t RxRollOverCount; + USHORT PrevNumRecvDescs; + USHORT CurrNumRecvDescs; + atomic_t GoodRxByteCount; + atomic_t GoodRxPktCount; + atomic_t BadRxByteCount; + atomic_t RxPacketDroppedCount; + atomic_t GoodTxByteCount; + atomic_t TxTotalPacketCount; + atomic_t TxDroppedPacketCount; + ULONG LinkUpStatus; + BOOLEAN TransferMode; + UINT u32TotalDSD; + PacketInfo PackInfo[NO_OF_QUEUES]; + S_CLASSIFIER_RULE astClassifierTable[MAX_CLASSIFIERS]; + + /*************** qos ******************/ + UINT bETHCSEnabled; + + ULONG BEBucketSize; + ULONG rtPSBucketSize; + UCHAR LinkStatus; + BOOLEAN AutoLinkUp; + BOOLEAN AutoSyncup; + + struct net_device *dev; + UINT major; + UINT minor; + wait_queue_head_t tx_packet_wait_queue; + wait_queue_head_t process_rx_cntrlpkt; + atomic_t process_waiting; + BOOLEAN fw_download_done; + + unsigned int ctrlpkt_present; + BOOLEAN packets_given_to_all; + char *txctlpacket[MAX_CNTRL_PKTS]; + atomic_t cntrlpktCnt ; + atomic_t index_app_read_cntrlpkt; + atomic_t index_wr_txcntrlpkt; + atomic_t index_rd_txcntrlpkt; + UINT index_datpkt; + struct semaphore rdmwrmsync; + + STTARGETDSXBUFFER astTargetDsxBuffer[MAX_TARGET_DSX_BUFFERS]; + ULONG ulFreeTargetBufferCnt; + ULONG ulCurrentTargetBuffer; + ULONG ulTotalTargetBuffersAvailable; + unsigned int timeout; + int irq; + unsigned long chip_id; + unsigned int bFlashBoot; + unsigned int if_up; +// spinlock_t sleeper_lock; + atomic_t rdm_wrm_access; + atomic_t tx_rx_access; + wait_queue_head_t lowpower_mode_wait_queue; + atomic_t bAbortedByHost; + BOOLEAN bBinDownloaded; + BOOLEAN bCfgDownloaded; + USHORT usBestEffortQueueIndex; + BOOLEAN bSyncUpRequestSent; +// struct semaphore data_packet_queue_lock; + wait_queue_head_t ioctl_fw_dnld_wait_queue; + BOOLEAN waiting_to_fw_download_done; + pid_t fw_download_process_pid; + PSTARGETPARAMS pstargetparams; + BOOLEAN device_removed; + BOOLEAN DeviceAccess; + INT DDRSetting; + BOOLEAN bDDRInitDone; + ULONG ulPowerSaveMode; + BOOLEAN bIsAutoCorrectEnabled; + spinlock_t txtransmitlock; + B_UINT8 txtransmit_running; + /* Thread for control packet handling */ + struct task_struct *control_packet_handler; + /* thread for transmitting packets. */ + struct task_struct *transmit_packet_thread; + + /* LED Related Structures */ + LED_INFO_STRUCT LEDInfo; + + /* Driver State for LED Blinking */ + LedEventInfo_t DriverState; + /* Interface Specific */ + PVOID pvInterfaceAdapter; + int (*bcm_file_download)( PVOID, + struct file *, + unsigned int); + int (*bcm_file_readback_from_chip)( PVOID, + struct file *, + unsigned int); + INT (*interface_rdm)(PVOID, + UINT , + PVOID , + INT); + INT (*interface_wrm)(PVOID, + UINT , + PVOID , + INT); + int (*interface_transmit)(PVOID, PVOID , UINT); + BOOLEAN IdleMode; + BOOLEAN bDregRequestSentInIdleMode; + BOOLEAN bTriedToWakeUpFromlowPowerMode; + BOOLEAN bShutStatus; + BOOLEAN bWakeUpDevice; + unsigned int usIdleModePattern; + //BOOLEAN bTriedToWakeUpFromShutdown; + BOOLEAN bLinkDownRequested; + unsigned int check_for_hang; + int downloadDDR; + PHS_DEVICE_EXTENSION stBCMPhsContext; + S_HDR_SUPRESSION_CONTEXTINFO stPhsTxContextInfo; + uint8_t ucaPHSPktRestoreBuf[2048]; + uint8_t bPHSEnabled; + int AutoFirmDld; + BOOLEAN bMipsConfig; + BOOLEAN bDPLLConfig; + UINT32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; + UINT32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; + S_FRAGMENTED_PACKET_INFO astFragmentedPktClassifierTable[MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES]; + atomic_t uiMBupdate; + UINT32 PmuMode; + NVM_TYPE eNVMType; + UINT uiSectorSize; + UINT uiSectorSizeInCFG; + BOOLEAN bSectorSizeOverride; + BOOLEAN bStatusWrite; + UINT uiNVMDSDSize; + UINT uiVendorExtnFlag; + //it will always represent choosed DSD at any point of time. + // Generally it is Active DSD but in case of NVM RD/WR it might be different. + UINT ulFlashCalStart; + ULONG ulFlashControlSectionStart; + ULONG ulFlashWriteSize; + ULONG ulFlashID; + FP_FLASH_WRITE fpFlashWrite; + FP_FLASH_WRITE_STATUS fpFlashWriteWithStatusCheck; + + + struct semaphore NVMRdmWrmLock; + BOOLEAN bNetworkInterfaceRegistered; + BOOLEAN bNetdeviceNotifierRegistered; + struct device *pstCreatedClassDevice; + BOOLEAN bUsbClassDriverRegistered; +// BOOLEAN InterfaceUpStatus; + PFLASH2X_CS_INFO psFlash2xCSInfo; + PFLASH_CS_INFO psFlashCSInfo ; + PFLASH2X_VENDORSPECIFIC_INFO psFlash2xVendorInfo; + UINT uiFlashBaseAdd; //Flash start address + UINT uiActiveISOOffset; //Active ISO offset choosen before f/w download + FLASH2X_SECTION_VAL eActiveISO; //Active ISO section val + FLASH2X_SECTION_VAL eActiveDSD; //Active DSD val choosen before f/w download + UINT uiActiveDSDOffsetAtFwDld; //For accessing Active DSD choosen before f/w download + UINT uiFlashLayoutMajorVersion ; + UINT uiFlashLayoutMinorVersion; + BOOLEAN bAllDSDWriteAllow ; + BOOLEAN bSigCorrupted ; + //this should be set who so ever want to change the Headers. after Wrtie it should be reset immediately. + BOOLEAN bHeaderChangeAllowed ; + INT SelectedChip ; + BOOLEAN bEndPointHalted; + //while bFlashRawRead will be true, Driver ignore map lay out and consider flash as of without any map. + BOOLEAN bFlashRawRead; + BOOLEAN bPreparingForLowPowerMode ; + BOOLEAN bDoSuspend ; + UINT syscfgBefFwDld ; + BOOLEAN StopAllXaction ; + UINT32 liTimeSinceLastNetEntry; //Used to Support extended CAPI requirements from + struct semaphore LowPowerModeSync; + ULONG liDrainCalculated; + UINT gpioBitMap; + S_BCM_DEBUG_STATE stDebugState; + +}; +typedef struct _MINI_ADAPTER MINI_ADAPTER, *PMINI_ADAPTER; + + +typedef struct _DEVICE_EXTENSION +{ + PMINI_ADAPTER pAdapt; +}DEVICE_EXTENSION,*PDEVICE_EXTENSION; + + +struct _ETH_HEADER_STRUC { + UCHAR au8DestinationAddress[6]; + UCHAR au8SourceAddress[6]; + USHORT u16Etype; +}__attribute__((packed)); +typedef struct _ETH_HEADER_STRUC ETH_HEADER_STRUC, *PETH_HEADER_STRUC; + + +typedef struct FirmwareInfo +{ + PVOID pvMappedFirmwareAddress; + ULONG u32FirmwareLength; + ULONG u32StartingAddress; +}__attribute__((packed)) FIRMWARE_INFO, *PFIRMWARE_INFO; + +// holds the value of net_device structure.. +extern struct net_device *gblpnetdev; +typedef struct _cntl_pkt{ + PMINI_ADAPTER Adapter; + PLEADER PLeader; +}cntl_pkt; +typedef LINK_REQUEST CONTROL_MESSAGE; + +typedef struct _DDR_SETTING +{ + ULONG ulRegAddress; + ULONG ulRegValue; +}DDR_SETTING, *PDDR_SETTING; +typedef DDR_SETTING DDR_SET_NODE, *PDDR_SET_NODE; +INT +InitAdapter(PMINI_ADAPTER psAdapter); + +// ===================================================================== +// Beceem vendor request codes for EP0 +// ===================================================================== + +#define BCM_REQUEST_READ 0x2 +#define BCM_REQUEST_WRITE 0x1 +#define EP2_MPS_REG 0x0F0110A0 +#define EP2_MPS 0x40 + +#define EP2_CFG_REG 0x0F0110A8 +#define EP2_CFG_INT 0x27 +#define EP2_CFG_BULK 0x25 + +#define EP4_MPS_REG 0x0F0110F0 +#define EP4_MPS 0x8C + +#define EP4_CFG_REG 0x0F0110F8 + +#define ISO_MPS_REG 0x0F0110C8 +#define ISO_MPS 0x00000000 + + +#define EP1 0 +#define EP2 1 +#define EP3 2 +#define EP4 3 +#define EP5 4 +#define EP6 5 + + +typedef enum eInterface_setting +{ + DEFAULT_SETTING_0 = 0, + ALTERNATE_SETTING_1 = 1, +}INTERFACE_SETTING; + +#endif //__ADAPTER_H__ + diff --git a/drivers/staging/bcm/Arp.c b/drivers/staging/bcm/Arp.c new file mode 100644 index 0000000..d60d859 --- /dev/null +++ b/drivers/staging/bcm/Arp.c @@ -0,0 +1,94 @@ + +/* + * File Name: Arp.c + * Abstract: This file contains the routines for handling ARP PACKETS + */ +#include "headers.h" +#define ARP_PKT_SIZE 60 + +/* ========================================================================= + * Function - reply_to_arp_request() + * + * Description - When this host tries to broadcast ARP request packet through + * the virtual interface (veth0), reply directly to upper layer. + * This function allocates a new skb for ARP reply packet, + * fills in the fields of the packet and then sends it to + * upper layer. + * + * Parameters - skb: Pointer to sk_buff structure of the ARP request pkt. + * + * Returns - None + * =========================================================================*/ + +VOID +reply_to_arp_request(struct sk_buff *skb) +{ + PMINI_ADAPTER Adapter; + struct ArpHeader *pArpHdr = NULL; + struct ethhdr *pethhdr = NULL; + UCHAR uiIPHdr[4]; + /* Check for valid skb */ + if(skb == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid skb: Cannot reply to ARP request\n"); + return; + } + + + Adapter = GET_BCM_ADAPTER(skb->dev); + /* Print the ARP Request Packet */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP Packet Dump :"); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); + + /* + * Extract the Ethernet Header and Arp Payload including Header + */ + pethhdr = (struct ethhdr *)skb->data; + pArpHdr = (struct ArpHeader *)(skb->data+ETH_HLEN); + + if(Adapter->bETHCSEnabled) + { + if(memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) + { + bcm_kfree_skb(skb); + return; + } + } + + // Set the Ethernet Header First. + memcpy(pethhdr->h_dest, pethhdr->h_source, ETH_ALEN); + if(!memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) + { + pethhdr->h_source[5]++; + } + + /* Set the reply to ARP Reply */ + pArpHdr->arp.ar_op = ntohs(ARPOP_REPLY); + + /* Set the HW Address properly */ + memcpy(pArpHdr->ar_sha, pethhdr->h_source, ETH_ALEN); + memcpy(pArpHdr->ar_tha, pethhdr->h_dest, ETH_ALEN); + + // Swapping the IP Adddress + memcpy(uiIPHdr,pArpHdr->ar_sip,4); + memcpy(pArpHdr->ar_sip,pArpHdr->ar_tip,4); + memcpy(pArpHdr->ar_tip,uiIPHdr,4); + + /* Print the ARP Reply Packet */ + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP REPLY PACKET: "); + + /* Send the Packet to upper layer */ + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); + + skb->protocol = eth_type_trans(skb,skb->dev); + skb->pkt_type = PACKET_HOST; + +// skb->mac.raw=skb->data+LEADER_SIZE; + skb_set_mac_header (skb, LEADER_SIZE); + netif_rx(skb); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "<=============\n"); + return; +} + + diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c new file mode 100644 index 0000000..489487a --- /dev/null +++ b/drivers/staging/bcm/Bcmchar.c @@ -0,0 +1,2420 @@ +#include "headers.h" +/*************************************************************** +* Function - bcm_char_open() +* +* Description - This is the "open" entry point for the character +* driver. +* +* Parameters - inode: Pointer to the Inode structure of char device +* filp : File pointer of the char device +* +* Returns - Zero(Success) +****************************************************************/ +static struct class *bcm_class = NULL; +static int bcm_char_open(struct inode *inode, struct file * filp) +{ + PMINI_ADAPTER Adapter = NULL; + PPER_TARANG_DATA pTarang = NULL; + + Adapter = GET_BCM_ADAPTER(gblpnetdev); + pTarang = (PPER_TARANG_DATA)kmalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL); + if (!pTarang) + return -ENOMEM; + + memset (pTarang, 0, sizeof(PER_TARANG_DATA)); + pTarang->Adapter = Adapter; + pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB) ; + + down(&Adapter->RxAppControlQueuelock); + pTarang->next = Adapter->pTarangs; + Adapter->pTarangs = pTarang; + up(&Adapter->RxAppControlQueuelock); + + /* Store the Adapter structure */ + filp->private_data = pTarang; + + /*Start Queuing the control response Packets*/ + atomic_inc(&Adapter->ApplicationRunning); + return 0; +} +static int bcm_char_release(struct inode *inode, struct file *filp) +{ + PPER_TARANG_DATA pTarang, tmp, ptmp; + PMINI_ADAPTER Adapter=NULL; + struct sk_buff * pkt, * npkt; + + pTarang = (PPER_TARANG_DATA)filp->private_data; + + if(pTarang == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ptarang is null\n"); + return 0; + } + + Adapter = pTarang->Adapter; + + down( &Adapter->RxAppControlQueuelock); + + tmp = Adapter->pTarangs; + for ( ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next ) + { + if ( tmp == pTarang ) + break; + } + + if ( tmp ) + { + if ( !ptmp ) + Adapter->pTarangs = tmp->next; + else + ptmp->next = tmp->next; + } + + else + { + up( &Adapter->RxAppControlQueuelock); + return 0; + } + + pkt = pTarang->RxAppControlHead; + while ( pkt ) + { + npkt = pkt->next; + kfree_skb(pkt); + pkt = npkt; + } + + up( &Adapter->RxAppControlQueuelock); + + /*Stop Queuing the control response Packets*/ + atomic_dec(&Adapter->ApplicationRunning); + + bcm_kfree(pTarang); + + /* remove this filp from the asynchronously notified filp's */ + filp->private_data = NULL; + return 0; +} + +static int bcm_char_read(struct file *filp, PCHAR buf, size_t size, loff_t *f_pos) +{ + PPER_TARANG_DATA pTarang = (PPER_TARANG_DATA)filp->private_data; + PMINI_ADAPTER Adapter = pTarang->Adapter; + struct sk_buff* Packet = NULL; + UINT PktLen = 0; + int wait_ret_val=0; + + wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue, + (pTarang->RxAppControlHead || Adapter->device_removed)); + if((wait_ret_val == -ERESTARTSYS)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Exiting as i've been asked to exit!!!\n"); + return wait_ret_val; + } + + if(Adapter->device_removed) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device Removed... Killing the Apps...\n"); + return -ENODEV; + } + + if(FALSE == Adapter->fw_download_done) + return -EACCES; + + down( &Adapter->RxAppControlQueuelock); + + if(pTarang->RxAppControlHead) + { + Packet = pTarang->RxAppControlHead; + DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail); + pTarang->AppCtrlQueueLen--; + } + + up(&Adapter->RxAppControlQueuelock); + + if(Packet) + { + PktLen = Packet->len; + if(copy_to_user(buf, Packet->data, PktLen)) + { + bcm_kfree_skb(Packet); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nReturning from copy to user failure \n"); + return -EFAULT; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Read %d Bytes From Adapter packet = 0x%p by process %d!\n", PktLen, Packet, current->pid); + bcm_kfree_skb(Packet); + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<====\n"); + return PktLen; +} + +static INT bcm_char_ioctl(struct inode *inode, struct file *filp, + UINT cmd, ULONG arg) +{ + PPER_TARANG_DATA pTarang = (PPER_TARANG_DATA)filp->private_data; + PMINI_ADAPTER Adapter = pTarang->Adapter; + INT Status = STATUS_FAILURE; + IOCTL_BUFFER IoBuffer={0}; +#ifndef BCM_SHM_INTERFACE + int timeout = 0; +#endif + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Parameters Passed to control IOCTL cmd=0x%X arg=0x%lX", cmd, arg); + + if(_IOC_TYPE(cmd) != BCM_IOCTL) + return -EFAULT; + if(_IOC_DIR(cmd) & _IOC_READ) + Status = !access_ok(VERIFY_WRITE, (PVOID)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + Status = !access_ok(VERIFY_READ, (PVOID)arg, _IOC_SIZE(cmd)); + else if (_IOC_NONE == (_IOC_DIR(cmd) & _IOC_NONE)) + Status = STATUS_SUCCESS; + + if(Status) + return -EFAULT; + + if(Adapter->device_removed) + { + return -EFAULT; + } + + if(FALSE == Adapter->fw_download_done) + { + switch (cmd) + { + case IOCTL_MAC_ADDR_REQ: + case IOCTL_LINK_REQ: + case IOCTL_CM_REQUEST: + case IOCTL_SS_INFO_REQ: + case IOCTL_SEND_CONTROL_MESSAGE: + case IOCTL_IDLE_REQ: + case IOCTL_BCM_GPIO_SET_REQUEST: + case IOCTL_BCM_GPIO_STATUS_REQUEST: + return -EACCES; + default: + break; + } + } + + Status = vendorextnIoctl(Adapter, cmd, arg); + if(Status != CONTINUE_COMMON_PATH ) + { + return Status; + } + + switch(cmd){ + // Rdms for Swin Idle... + case IOCTL_BCM_REGISTER_READ_PRIVATE: + { + RDM_BUFFER sRdmBuffer = {0}; + PCHAR temp_buff = NULL; + UINT Bufflen = 0; + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, + sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + + Bufflen = IoBuffer.OutputLength + (4 - IoBuffer.OutputLength%4)%4; + temp_buff = (PCHAR)kmalloc(Bufflen, GFP_KERNEL); + if(!temp_buff) + { + return STATUS_FAILURE; + } + if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, + IoBuffer.InputLength)) + { + Status = -EFAULT; + break; + } + Status = rdmalt(Adapter, (UINT)sRdmBuffer.Register, + (PUINT)temp_buff, Bufflen); + if(Status != STATUS_SUCCESS) + { + bcm_kfree(temp_buff); + return Status; + } + if(copy_to_user((PCHAR)IoBuffer.OutputBuffer, + (PCHAR)temp_buff, (UINT)IoBuffer.OutputLength)) + { + Status = -EFAULT; + } + bcm_kfree(temp_buff); + break; + } + case IOCTL_BCM_REGISTER_WRITE_PRIVATE: + { + WRM_BUFFER sWrmBuffer = {0}; + UINT uiTempVar=0; + /* Copy Ioctl Buffer structure */ + + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, + sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + /* Get WrmBuffer structure */ + if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, + IoBuffer.InputLength)) + { + Status = -EFAULT; + break; + } + uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; + if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && + ((uiTempVar == EEPROM_REJECT_REG_1)|| + (uiTempVar == EEPROM_REJECT_REG_2) || + (uiTempVar == EEPROM_REJECT_REG_3) || + (uiTempVar == EEPROM_REJECT_REG_4))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); + Status = -EFAULT; + break; + } + Status = wrmalt(Adapter, (UINT)sWrmBuffer.Register, + (PUINT)sWrmBuffer.Data, sizeof(ULONG)); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"WRM Done\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); + Status = -EFAULT; + } + break; + } + + case IOCTL_BCM_REGISTER_READ: + case IOCTL_BCM_EEPROM_REGISTER_READ: + { + RDM_BUFFER sRdmBuffer = {0}; + PCHAR temp_buff = NULL; + UINT uiTempVar = 0; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Rdms\n"); + Status = -EACCES; + break; + } + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, + sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + + temp_buff = (PCHAR)kmalloc(IoBuffer.OutputLength, GFP_KERNEL); + if(!temp_buff) + { + return STATUS_FAILURE; + } + if(copy_from_user(&sRdmBuffer, IoBuffer.InputBuffer, + IoBuffer.InputLength)) + { + Status = -EFAULT; + break; + } + + if( +#if !defined(BCM_SHM_INTERFACE) + (((ULONG)sRdmBuffer.Register & 0x0F000000) != 0x0F000000) || +#endif + ((ULONG)sRdmBuffer.Register & 0x3) + ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Done On invalid Address : %x Access Denied.\n", + (int)sRdmBuffer.Register); + Status = -EINVAL; + break; + } + + uiTempVar = sRdmBuffer.Register & EEPROM_REJECT_MASK; + Status = rdmaltWithLock(Adapter, (UINT)sRdmBuffer.Register, + (PUINT)temp_buff, IoBuffer.OutputLength); + if(Status != STATUS_SUCCESS) + { + bcm_kfree(temp_buff); + return Status; + } + if(copy_to_user((PCHAR)IoBuffer.OutputBuffer, + (PCHAR)temp_buff, (UINT)IoBuffer.OutputLength)) + { + Status = -EFAULT; + } + bcm_kfree(temp_buff); + break; + } + case IOCTL_BCM_REGISTER_WRITE: + case IOCTL_BCM_EEPROM_REGISTER_WRITE: + { + WRM_BUFFER sWrmBuffer = {0}; + UINT uiTempVar=0; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device in Idle Mode, Blocking Wrms\n"); + Status = -EACCES; + break; + } + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, + sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + /* Get WrmBuffer structure */ + if(copy_from_user(&sWrmBuffer, IoBuffer.InputBuffer, + IoBuffer.InputLength)) + { + Status = -EFAULT; + break; + } + if( +#if !defined(BCM_SHM_INTERFACE) + + (((ULONG)sWrmBuffer.Register & 0x0F000000) != 0x0F000000) || +#endif + ((ULONG)sWrmBuffer.Register & 0x3) + ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Done On invalid Address : %x Access Denied.\n", + (int)sWrmBuffer.Register); + Status = -EINVAL; + break; + } + uiTempVar = sWrmBuffer.Register & EEPROM_REJECT_MASK; + if(!((Adapter->pstargetparams->m_u32Customize) & VSG_MODE) && + ((uiTempVar == EEPROM_REJECT_REG_1)|| + (uiTempVar == EEPROM_REJECT_REG_2) || + (uiTempVar == EEPROM_REJECT_REG_3) || + (uiTempVar == EEPROM_REJECT_REG_4)) && + (cmd == IOCTL_BCM_REGISTER_WRITE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM Access Denied, not in VSG Mode\n"); + Status = -EFAULT; + break; + } + + Status = wrmaltWithLock(Adapter, (UINT)sWrmBuffer.Register, + (PUINT)sWrmBuffer.Data, sWrmBuffer.Length); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "WRM Done\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM Failed\n"); + Status = -EFAULT; + } + break; + } + case IOCTL_BCM_GPIO_SET_REQUEST: + { + UCHAR ucResetValue[4]; + UINT value =0; + UINT uiBit = 0; + UINT uiOperation = 0; + + GPIO_INFO gpio_info = {0}; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode"); + Status = -EACCES; + break; + } + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) + { + Status = -EFAULT; + break; + } + uiBit = gpio_info.uiGpioNumber; + uiOperation = gpio_info.uiGpioValue; + + value= (1< is not correspond to LED !!!",value); + Status = -EINVAL; + break; + } + + + if(uiOperation)//Set - setting 1 + { + //Set the gpio output register + Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG , + (PUINT)(&value), sizeof(UINT)); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Set the GPIO bit\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to set the %dth GPIO \n",uiBit); + break; + } + } + else//Unset - setting 0 + { + //Set the gpio output register + Status = wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG , + (PUINT)(&value), sizeof(UINT)); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Set the GPIO bit\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Failed to clear the %dth GPIO \n",uiBit); + break; + } + } + + Status = rdmaltWithLock(Adapter, (UINT)GPIO_MODE_REGISTER, + (PUINT)ucResetValue, sizeof(UINT)); + if (STATUS_SUCCESS != Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO_MODE_REGISTER read failed"); + break; + } + //Set the gpio mode register to output + *(UINT*)ucResetValue |= (1<IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"GPIO Can't be set/clear in Low power Mode"); + Status = -EACCES; + break; + } + Status =copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status); + break; + } + + Status= copy_from_user(&threadReq, IoBuffer.InputBuffer, IoBuffer.InputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the InputBuffer from user space err:%d",Status); + break; + } + //if LED thread is running(Actively or Inactively) set it state to make inactive + if(Adapter->LEDInfo.led_thread_running) + { + if(threadReq.ThreadState == LED_THREAD_ACTIVATION_REQ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Activating thread req"); + Adapter->DriverState = LED_THREAD_ACTIVE; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DeActivating Thread req....."); + Adapter->DriverState = LED_THREAD_INACTIVE; + } + + //signal thread. + wake_up(&Adapter->LEDInfo.notify_led_event); + + } + } + break; + case IOCTL_BCM_GPIO_STATUS_REQUEST: + { + ULONG uiBit = 0; + UCHAR ucRead[4]; + GPIO_INFO gpio_info = {0}; + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + Status = -EACCES; + break; + } + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + if(copy_from_user(&gpio_info, IoBuffer.InputBuffer, IoBuffer.InputLength)) + { + Status = -EFAULT; + break; + } + uiBit = gpio_info.uiGpioNumber; + //Set the gpio output register + Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, + (PUINT)ucRead, sizeof(UINT)); + if(Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "RDM Failed\n"); + return Status; + } + + } + break; + case IOCTL_BCM_GPIO_MULTI_REQUEST: + { + UCHAR ucResetValue[4]; + GPIO_MULTI_INFO gpio_multi_info[MAX_IDX]; + PGPIO_MULTI_INFO pgpio_multi_info = (PGPIO_MULTI_INFO)gpio_multi_info; + + memset( pgpio_multi_info, 0, MAX_IDX * sizeof( GPIO_MULTI_INFO)); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + Status = -EINVAL; + break; + } + Status = copy_from_user( (PCHAR)&IoBuffer, ( PCHAR)arg, sizeof( IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status); + break; + } + + Status = copy_from_user( &gpio_multi_info, IoBuffer.InputBuffer, IoBuffer.InputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer Contents from user space err:%d",Status); + break; + } + if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_info[WIMAX_IDX].uiGPIOMask)== FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_info[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap); + Status = -EINVAL; + break; + } + + /* Set the gpio output register */ + + if( ( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) & + ( pgpio_multi_info[WIMAX_IDX].uiGPIOCommand)) + { + /* Set 1's in GPIO OUTPUT REGISTER */ + *(UINT*) ucResetValue = pgpio_multi_info[WIMAX_IDX].uiGPIOMask & + pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & + pgpio_multi_info[WIMAX_IDX].uiGPIOValue; + + if( *(UINT*) ucResetValue) + Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_SET_REG , (PUINT) ucResetValue, sizeof(ULONG)); + + if( Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_SET_REG Failed."); + return Status; + } + + /* Clear to 0's in GPIO OUTPUT REGISTER */ + *(UINT*) ucResetValue = (pgpio_multi_info[WIMAX_IDX].uiGPIOMask & + pgpio_multi_info[WIMAX_IDX].uiGPIOCommand & + ( ~( pgpio_multi_info[WIMAX_IDX].uiGPIOValue))); + + if( *(UINT*) ucResetValue) + Status = wrmaltWithLock( Adapter, BCM_GPIO_OUTPUT_CLR_REG , (PUINT) ucResetValue, sizeof(ULONG)); + + if( Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to BCM_GPIO_OUTPUT_CLR_REG Failed." ); + return Status; + } + } + + if( pgpio_multi_info[WIMAX_IDX].uiGPIOMask) + { + Status = rdmaltWithLock(Adapter, (UINT)GPIO_PIN_STATE_REGISTER, (PUINT)ucResetValue, sizeof(UINT)); + + if(Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM to GPIO_PIN_STATE_REGISTER Failed."); + return Status; + } + + pgpio_multi_info[WIMAX_IDX].uiGPIOValue = ( *(UINT*)ucResetValue & + pgpio_multi_info[WIMAX_IDX].uiGPIOMask); + } + + Status = copy_to_user( (PCHAR)IoBuffer.OutputBuffer, &gpio_multi_info, IoBuffer.OutputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); + break; + } + } + break; + case IOCTL_BCM_GPIO_MODE_REQUEST: + { + UCHAR ucResetValue[4]; + GPIO_MULTI_MODE gpio_multi_mode[MAX_IDX]; + PGPIO_MULTI_MODE pgpio_multi_mode = ( PGPIO_MULTI_MODE) gpio_multi_mode; + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + Status = -EINVAL; + break; + } + Status = copy_from_user( (PCHAR)&IoBuffer, ( PCHAR)arg, sizeof( IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer from user space err:%d",Status); + break; + } + + Status = copy_from_user( &gpio_multi_mode, IoBuffer.InputBuffer, IoBuffer.InputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying the IOBufer Contents from user space err:%d",Status); + break; + } + + Status = rdmaltWithLock( Adapter, ( UINT) GPIO_MODE_REGISTER, ( PUINT) ucResetValue, sizeof( UINT)); + if( STATUS_SUCCESS != Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Read of GPIO_MODE_REGISTER failed"); + return Status; + } + + //Validating the request + if(IsReqGpioIsLedInNVM(Adapter,pgpio_multi_mode[WIMAX_IDX].uiGPIOMask)== FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Sorry, Requested GPIO<0x%X> is not correspond to NVM LED bit map<0x%X>!!!",pgpio_multi_mode[WIMAX_IDX].uiGPIOMask,Adapter->gpioBitMap); + Status = -EINVAL; + break; + } + + if( pgpio_multi_mode[WIMAX_IDX].uiGPIOMask) + { + /* write all OUT's (1's) */ + *( UINT*) ucResetValue |= ( pgpio_multi_mode[WIMAX_IDX].uiGPIOMode & + pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); + /* write all IN's (0's) */ + *( UINT*) ucResetValue &= ~( ( ~pgpio_multi_mode[WIMAX_IDX].uiGPIOMode) & + pgpio_multi_mode[WIMAX_IDX].uiGPIOMask); + + /* Currently implemented return the modes of all GPIO's + * else needs to bit AND with mask + * */ + pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *(UINT*)ucResetValue; + + Status = wrmaltWithLock( Adapter, GPIO_MODE_REGISTER , ( PUINT) ucResetValue, sizeof( ULONG)); + if( Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "WRM to GPIO_MODE_REGISTER Done"); + } + else + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to GPIO_MODE_REGISTER Failed"); + Status = -EFAULT; + break; + } + } + else /* if uiGPIOMask is 0 then return mode register configuration */ + { + pgpio_multi_mode[WIMAX_IDX].uiGPIOMode = *( UINT*) ucResetValue; + } + Status = copy_to_user( (PCHAR)IoBuffer.OutputBuffer, &gpio_multi_mode, IoBuffer.OutputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed while copying Content to IOBufer for user space err:%d",Status); + break; + } + } + break; + + case IOCTL_MAC_ADDR_REQ: + case IOCTL_LINK_REQ: + case IOCTL_CM_REQUEST: + case IOCTL_SS_INFO_REQ: + case IOCTL_SEND_CONTROL_MESSAGE: + case IOCTL_IDLE_REQ: + { + PVOID pvBuffer=NULL; + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, + sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + pvBuffer=kmalloc(IoBuffer.InputLength, GFP_KERNEL); + if(!pvBuffer) + { + return -ENOMEM; + } + + if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, + IoBuffer.InputLength)) + { + Status = -EFAULT; + bcm_kfree(pvBuffer); + break; + } + + down(&Adapter->LowPowerModeSync); + Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, + !Adapter->bPreparingForLowPowerMode, + (1 * HZ)); + if(Status == -ERESTARTSYS) + goto cntrlEnd; + + if(Adapter->bPreparingForLowPowerMode) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Preparing Idle Mode is still True - Hence Rejecting control message\n"); + Status = STATUS_FAILURE ; + goto cntrlEnd ; + } + Status = CopyBufferToControlPacket(Adapter, (PVOID)pvBuffer); + cntrlEnd: + up(&Adapter->LowPowerModeSync); + bcm_kfree(pvBuffer); + break; + } +#ifndef BCM_SHM_INTERFACE + case IOCTL_BCM_BUFFER_DOWNLOAD_START: + { + INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock) ; + if(NVMAccess) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); + return -EACCES; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); + if(!down_trylock(&Adapter->fw_download_sema)) + { + Adapter->bBinDownloaded=FALSE; + Adapter->fw_download_process_pid=current->pid; + Adapter->bCfgDownloaded=FALSE; + Adapter->fw_download_done=FALSE; + netif_carrier_off(Adapter->dev); + netif_stop_queue(Adapter->dev); + Status = reset_card_proc(Adapter); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "reset_card_proc Failed!\n"); + up(&Adapter->fw_download_sema); + up(&Adapter->NVMRdmWrmLock); + break; + } + mdelay(10); + } + else + { + + Status = -EBUSY; + + } + up(&Adapter->NVMRdmWrmLock); + break; + } + case IOCTL_BCM_BUFFER_DOWNLOAD: + { + FIRMWARE_INFO *psFwInfo=NULL; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Starting the firmware download PID =0x%x!!!!\n", current->pid); + do{ + if(!down_trylock(&Adapter->fw_download_sema)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid way to download buffer. Use Start and then call this!!!\n"); + Status=-EINVAL; + break; + } + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, + sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); + Status = -EFAULT; + break; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length for FW DLD is : %lx\n", + IoBuffer.InputLength); + psFwInfo=kmalloc(sizeof(*psFwInfo), GFP_KERNEL); + if(!psFwInfo) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Failed to allocate buffer!!!!\n"); + Status = -ENOMEM; + break; + } + if(copy_from_user(psFwInfo, IoBuffer.InputBuffer, + IoBuffer.InputLength)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_from_user 2 failed\n"); + Status = -EFAULT; + break; + } + + if(!psFwInfo->pvMappedFirmwareAddress || + (psFwInfo->u32FirmwareLength == 0)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Something else is wrong %lu\n", + psFwInfo->u32FirmwareLength); + Status = -EINVAL; + break; + } + Status = bcm_ioctl_fw_download(Adapter, psFwInfo); + if(Status != STATUS_SUCCESS) + { + if(psFwInfo->u32StartingAddress==CONFIG_BEGIN_ADDR) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Configuration File Upload Failed\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "IOCTL: Firmware File Upload Failed\n"); + } + //up(&Adapter->fw_download_sema); + + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = DRIVER_INIT; + Adapter->LEDInfo.bLedInitDone = FALSE; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + } + break ; + }while(0); + + if(Status != STATUS_SUCCESS) + up(&Adapter->fw_download_sema); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, OSAL_DBG, DBG_LVL_ALL, "IOCTL: Firmware File Uploaded\n"); + bcm_kfree(psFwInfo); + break; + } + case IOCTL_BCM_BUFFER_DOWNLOAD_STOP: + { + INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); + if(NVMAccess) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " FW download blocked as EEPROM Read/Write is in progress\n"); + up(&Adapter->fw_download_sema); + return -EACCES; + } + if(down_trylock(&Adapter->fw_download_sema)) + { + Adapter->bBinDownloaded=TRUE; + Adapter->bCfgDownloaded=TRUE; + atomic_set(&Adapter->CurrNumFreeTxDesc, 0); + atomic_set(&Adapter->RxRollOverCount, 0); + Adapter->CurrNumRecvDescs=0; + Adapter->downloadDDR = 0; + + //setting the Mips to Run + Status = run_card_proc(Adapter); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Firm Download Failed\n"); + up(&Adapter->fw_download_sema); + up(&Adapter->NVMRdmWrmLock); + break; + } + else + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Firm Download Over...\n"); + mdelay(10); + /* Wait for MailBox Interrupt */ + if(StartInterruptUrb((PS_INTERFACE_ADAPTER)Adapter->pvInterfaceAdapter)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to send interrupt...\n"); + } + timeout = 5*HZ; + Adapter->waiting_to_fw_download_done = FALSE; + wait_event_timeout(Adapter->ioctl_fw_dnld_wait_queue, + Adapter->waiting_to_fw_download_done, timeout); + Adapter->fw_download_process_pid=INVALID_PID; + Adapter->fw_download_done=TRUE; + atomic_set(&Adapter->CurrNumFreeTxDesc, 0); + Adapter->CurrNumRecvDescs = 0; + Adapter->PrevNumRecvDescs = 0; + atomic_set(&Adapter->cntrlpktCnt,0); + Adapter->LinkUpStatus = 0; + Adapter->LinkStatus = 0; + + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = FW_DOWNLOAD_DONE; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + + if(!timeout) + { + Status = -ENODEV; + } + } + else + { + Status = -EINVAL; + } + up(&Adapter->fw_download_sema); + up(&Adapter->NVMRdmWrmLock); + break; + } +#endif + case IOCTL_BE_BUCKET_SIZE: + Adapter->BEBucketSize = *(PULONG)arg; + Status = STATUS_SUCCESS; + break; + + case IOCTL_RTPS_BUCKET_SIZE: + Adapter->rtPSBucketSize = *(PULONG)arg; + Status = STATUS_SUCCESS; + break; + case IOCTL_CHIP_RESET: + { + INT NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); + if(NVMAccess) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " IOCTL_BCM_CHIP_RESET not allowed as EEPROM Read/Write is in progress\n"); + return -EACCES; + } + down(&Adapter->RxAppControlQueuelock); + Status = reset_card_proc(Adapter); + flushAllAppQ(); + up(&Adapter->RxAppControlQueuelock); + up(&Adapter->NVMRdmWrmLock); + ResetCounters(Adapter); + break; + } + case IOCTL_QOS_THRESHOLD: + { + USHORT uiLoopIndex; + for(uiLoopIndex = 0 ; uiLoopIndex < NO_OF_QUEUES ; uiLoopIndex++) + { + Adapter->PackInfo[uiLoopIndex].uiThreshold = *(PULONG)arg; + } + Status = STATUS_SUCCESS; + break; + } + + case IOCTL_DUMP_PACKET_INFO: + + DumpPackInfo(Adapter); + DumpPhsRules(&Adapter->stBCMPhsContext); + Status = STATUS_SUCCESS; + break; + + case IOCTL_GET_PACK_INFO: + if(copy_to_user((PCHAR)arg, &Adapter->PackInfo, + sizeof(PacketInfo)*NO_OF_QUEUES)) + { + Status = -EFAULT; + break; + } + Status = STATUS_SUCCESS; + break; + case IOCTL_BCM_SWITCH_TRANSFER_MODE: + { + UINT uiData = 0; + if(copy_from_user(&uiData, (PUINT)arg, sizeof(UINT))) + { + Status = -EFAULT; + break; + } + if(uiData) /* Allow All Packets */ + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: ETH_PACKET_TUNNELING_MODE\n"); + Adapter->TransferMode = ETH_PACKET_TUNNELING_MODE; + } + else /* Allow IP only Packets */ + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SWITCH_TRANSFER_MODE: IP_PACKET_ONLY_MODE\n"); + Adapter->TransferMode = IP_PACKET_ONLY_MODE; + } + Status = STATUS_SUCCESS; + break; + } + + case IOCTL_BCM_GET_DRIVER_VERSION: + { + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, + (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + if(copy_to_user((PUCHAR)IoBuffer.OutputBuffer, + VER_FILEVERSION_STR, (UINT)IoBuffer.OutputLength)) + { + Status = -EFAULT; + break; + } + Status = STATUS_SUCCESS; + break; + } + case IOCTL_BCM_GET_CURRENT_STATUS: + { + LINK_STATE *plink_state = NULL; + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, + (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user failed..\n"); + Status = -EFAULT; + break; + } + plink_state = (LINK_STATE*)arg; + plink_state->bIdleMode = (UCHAR)Adapter->IdleMode; + plink_state->bShutdownMode = Adapter->bShutStatus; + plink_state->ucLinkStatus = (UCHAR)Adapter->LinkStatus; + if(copy_to_user((PUCHAR)IoBuffer.OutputBuffer, + (PUCHAR)plink_state, (UINT)IoBuffer.OutputLength)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_to_user Failed..\n"); + Status = -EFAULT; + break; + } + Status = STATUS_SUCCESS; + break; + } + case IOCTL_BCM_SET_MAC_TRACING: + { + UINT tracing_flag; + /* copy ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, + (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + if(copy_from_user((PCHAR)&tracing_flag, + (PCHAR)IoBuffer.InputBuffer,sizeof(UINT))) + { + Status = -EFAULT; + break; + } + if (tracing_flag) + Adapter->pTarangs->MacTracingEnabled = TRUE; + else + Adapter->pTarangs->MacTracingEnabled = FALSE; + break; + } + case IOCTL_BCM_GET_DSX_INDICATION: + { + ULONG ulSFId=0; + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, + sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid IO buffer!!!" ); + Status = -EFAULT; + break; + } + if(IoBuffer.OutputLength < sizeof(stLocalSFAddIndicationAlt)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Mismatch req: %lx needed is =0x%x!!!", + IoBuffer.OutputLength, sizeof(stLocalSFAddIndicationAlt)); + return -EINVAL; + } + if(copy_from_user((PCHAR)&ulSFId, (PCHAR)IoBuffer.InputBuffer, + sizeof(ulSFId))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Invalid SFID!!! %lu", ulSFId ); + Status = -EFAULT; + break; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Get DSX Data SF ID is =%lx\n", ulSFId ); + get_dsx_sf_data_to_application(Adapter, ulSFId, + IoBuffer.OutputBuffer); + Status=STATUS_SUCCESS; + } + break; + case IOCTL_BCM_GET_HOST_MIBS: + { + PCHAR temp_buff; + + if(copy_from_user((PCHAR)&IoBuffer, + (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy_from user for IoBuff failed\n"); + Status = -EFAULT; + break; + } + + if(IoBuffer.OutputLength != sizeof(S_MIBS_HOST_STATS_MIBS)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Length Check failed %lu %d\n", IoBuffer.OutputLength, + sizeof(S_MIBS_HOST_STATS_MIBS)); + return -EINVAL; + } + + temp_buff = (PCHAR)kmalloc(IoBuffer.OutputLength, GFP_KERNEL); + + if(!temp_buff) + { + return STATUS_FAILURE; + } + + Status = ProcessGetHostMibs(Adapter, + (PUCHAR)temp_buff, IoBuffer.OutputLength); + + Status = GetDroppedAppCntrlPktMibs((PVOID)temp_buff, + (PPER_TARANG_DATA)filp->private_data); + + if(copy_to_user((PCHAR)IoBuffer.OutputBuffer,(PCHAR)temp_buff, + sizeof(S_MIBS_HOST_STATS_MIBS))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy to user failed\n"); + bcm_kfree(temp_buff); + return -EFAULT; + } + + bcm_kfree(temp_buff); + break; + } + + case IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE: + if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && (TRUE==Adapter->IdleMode)) + { + Adapter->usIdleModePattern = ABORT_IDLE_MODE; + Adapter->bWakeUpDevice = TRUE; + wake_up(&Adapter->process_rx_cntrlpkt); + #if 0 + Adapter->bTriedToWakeUpFromlowPowerMode = TRUE; + InterfaceAbortIdlemode (Adapter, Adapter->usIdleModePattern); + #endif + } + Status = STATUS_SUCCESS; + break; + + case IOCTL_BCM_BULK_WRM: + { + PBULKWRM_BUFFER pBulkBuffer; + UINT uiTempVar=0; + PCHAR pvBuffer = NULL; + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Device in Idle/Shutdown Mode, Blocking Wrms\n"); + Status = -EACCES; + break; + } + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + Status = -EFAULT; + break; + } + + pvBuffer=kmalloc(IoBuffer.InputLength, GFP_KERNEL); + if(!pvBuffer) + { + return -ENOMEM; + break; + } + + /* Get WrmBuffer structure */ + if(copy_from_user(pvBuffer, IoBuffer.InputBuffer, IoBuffer.InputLength)) + { + bcm_kfree(pvBuffer); + Status = -EFAULT; + break; + } + + pBulkBuffer = (PBULKWRM_BUFFER)pvBuffer; + + if(((ULONG)pBulkBuffer->Register & 0x0F000000) != 0x0F000000 || + ((ULONG)pBulkBuffer->Register & 0x3)) + { + bcm_kfree(pvBuffer); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"WRM Done On invalid Address : %x Access Denied.\n",(int)pBulkBuffer->Register); + Status = -EINVAL; + break; + } + + + uiTempVar = pBulkBuffer->Register & EEPROM_REJECT_MASK; + if(!((Adapter->pstargetparams->m_u32Customize)&VSG_MODE) + && ((uiTempVar == EEPROM_REJECT_REG_1)|| + (uiTempVar == EEPROM_REJECT_REG_2) || + (uiTempVar == EEPROM_REJECT_REG_3) || + (uiTempVar == EEPROM_REJECT_REG_4)) && + (cmd == IOCTL_BCM_REGISTER_WRITE)) + { + bcm_kfree(pvBuffer); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0,"EEPROM Access Denied, not in VSG Mode\n"); + Status = -EFAULT; + break; + } + + if(pBulkBuffer->SwapEndian == FALSE) + Status = wrmWithLock(Adapter, (UINT)pBulkBuffer->Register, (PCHAR)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); + else + Status = wrmaltWithLock(Adapter, (UINT)pBulkBuffer->Register, (PUINT)pBulkBuffer->Values, IoBuffer.InputLength - 2*sizeof(ULONG)); + + if(Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed\n"); + } + + bcm_kfree(pvBuffer); + break; + } + + case IOCTL_BCM_GET_NVM_SIZE: + { + + if(copy_from_user((unsigned char *)&IoBuffer, + (unsigned char *)arg, sizeof(IOCTL_BUFFER))) + { + //IOLog("failed NVM first"); + Status = -EFAULT; + break; + } + if(Adapter->eNVMType == NVM_EEPROM || Adapter->eNVMType == NVM_FLASH ) { + if(copy_to_user(IoBuffer.OutputBuffer, + (unsigned char *)&Adapter->uiNVMDSDSize, (UINT)sizeof(UINT))) + { + Status = -EFAULT; + return Status; + } + } + + Status = STATUS_SUCCESS ; + } + break; + + case IOCTL_BCM_CAL_INIT : + + { + UINT uiSectorSize = 0 ; + if(Adapter->eNVMType == NVM_FLASH) + { + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy From User space failed. status :%d", Status); + return Status; + } + uiSectorSize = *((PUINT)(IoBuffer.InputBuffer)); + if((uiSectorSize < MIN_SECTOR_SIZE) || (uiSectorSize > MAX_SECTOR_SIZE)) + { + + Status = copy_to_user(IoBuffer.OutputBuffer, + (unsigned char *)&Adapter->uiSectorSize , + (UINT)sizeof(UINT)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Coping the sector size to use space failed. status:%d",Status); + return Status; + } + } + else + { + if(IsFlash2x(Adapter)) + { + Status = copy_to_user(IoBuffer.OutputBuffer, + (unsigned char *)&Adapter->uiSectorSize , + (UINT)sizeof(UINT)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Coping the sector size to use space failed. status:%d",Status); + return Status; + } + + } + else + { + if((TRUE == Adapter->bShutStatus) || + (TRUE == Adapter->IdleMode)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle/Shutdown Mode\n"); + return -EACCES; + } + + Adapter->uiSectorSize = uiSectorSize ; + BcmUpdateSectorSize(Adapter,Adapter->uiSectorSize); + } + } + Status = STATUS_SUCCESS ; + } + else + { + Status = STATUS_FAILURE; + } + } + break; + case IOCTL_BCM_SET_DEBUG : + { + USER_BCM_DBG_STATE sUserDebugState; + +// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Entered the ioctl %x \n", IOCTL_BCM_SET_DEBUG ); + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In SET_DEBUG ioctl\n"); + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy from user failed\n"); + break; + } + Status = copy_from_user(&sUserDebugState,(USER_BCM_DBG_STATE *)IoBuffer.InputBuffer, sizeof(USER_BCM_DBG_STATE)); + if(Status) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "Copy of IoBuffer.InputBuffer failed"); + return Status; + } + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "IOCTL_BCM_SET_DEBUG: OnOff=%d Type = 0x%x ", + sUserDebugState.OnOff, sUserDebugState.Type); + //sUserDebugState.Subtype <<= 1; + sUserDebugState.Subtype = 1 << sUserDebugState.Subtype; + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "actual Subtype=0x%x\n", sUserDebugState.Subtype); + + // Update new 'DebugState' in the Adapter + Adapter->stDebugState.type |= sUserDebugState.Type; + /* Subtype: A bitmap of 32 bits for Subtype per Type. + * Valid indexes in 'subtype' array: 1,2,4,8 + * corresponding to valid Type values. Hence we can use the 'Type' field + * as the index value, ignoring the array entries 0,3,5,6,7 ! + */ + if (sUserDebugState.OnOff) + Adapter->stDebugState.subtype[sUserDebugState.Type] |= sUserDebugState.Subtype; + else + Adapter->stDebugState.subtype[sUserDebugState.Type] &= ~sUserDebugState.Subtype; + + BCM_SHOW_DEBUG_BITMAP(Adapter); + + } + break; + case IOCTL_BCM_NVM_READ: + case IOCTL_BCM_NVM_WRITE: + { + + NVM_READWRITE stNVMReadWrite = {0}; + PUCHAR pReadData = NULL; + PUCHAR pBuffertobeCopied = NULL; + ULONG ulDSDMagicNumInUsrBuff = 0 ; + struct timeval tv0, tv1; + memset(&tv0,0,sizeof(struct timeval)); + memset(&tv1,0,sizeof(struct timeval)); + if((Adapter->eNVMType == NVM_FLASH) && (Adapter->uiFlashLayoutMajorVersion == 0)) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,"The Flash Control Section is Corrupted. Hence Rejection on NVM Read/Write\n"); + Status = -EFAULT; + break; + } + + if(IsFlash2x(Adapter)) + { + if((Adapter->eActiveDSD != DSD0) && + (Adapter->eActiveDSD != DSD1) && + (Adapter->eActiveDSD != DSD2)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"No DSD is active..hence NVM Command is blocked"); + return STATUS_FAILURE ; + } + } + + /* Copy Ioctl Buffer structure */ + + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copy_from_user failed\n"); + Status = -EFAULT; + break; + } + if(IOCTL_BCM_NVM_READ == cmd) + pBuffertobeCopied = IoBuffer.OutputBuffer; + else + pBuffertobeCopied = IoBuffer.InputBuffer; + + if(copy_from_user(&stNVMReadWrite, pBuffertobeCopied,sizeof(NVM_READWRITE))) + { + Status = -EFAULT; + break; + } + + // + // Deny the access if the offset crosses the cal area limit. + // + if((stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) > Adapter->uiNVMDSDSize) + { + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allow access beyond NVM Size: 0x%x 0x%x\n", stNVMReadWrite.uiOffset , +// stNVMReadWrite.uiNumBytes); + Status = STATUS_FAILURE; + break; + } + + pReadData =(PCHAR)kmalloc(stNVMReadWrite.uiNumBytes, GFP_KERNEL); + + if(!pReadData) + return -ENOMEM; + + memset(pReadData,0,stNVMReadWrite.uiNumBytes); + + if(copy_from_user(pReadData, stNVMReadWrite.pBuffer, + stNVMReadWrite.uiNumBytes)) + { + Status = -EFAULT; + bcm_kfree(pReadData); + break; + } + + do_gettimeofday(&tv0); + if(IOCTL_BCM_NVM_READ == cmd) + { + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pReadData); + return -EACCES; + } + + Status = BeceemNVMRead(Adapter, (PUINT)pReadData, + stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes); + + up(&Adapter->NVMRdmWrmLock); + + if(Status != STATUS_SUCCESS) + { + bcm_kfree(pReadData); + return Status; + } + if(copy_to_user((PCHAR)stNVMReadWrite.pBuffer, + (PCHAR)pReadData, (UINT)stNVMReadWrite.uiNumBytes)) + { + bcm_kfree(pReadData); + Status = -EFAULT; + } + } + else + { + + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pReadData); + return -EACCES; + } + + Adapter->bHeaderChangeAllowed = TRUE ; + if(IsFlash2x(Adapter)) + { + /* + New Requirement:- + DSD section updation will be allowed in two case:- + 1. if DSD sig is present in DSD header means dongle is ok and updation is fruitfull + 2. if point 1 failes then user buff should have DSD sig. this point ensures that if dongle is + corrupted then user space program first modify the DSD header with valid DSD sig so + that this as well as further write may be worthwhile. + + This restriction has been put assuming that if DSD sig is corrupted, DSD + data won't be considered valid. + + + */ + Status = BcmFlash2xCorruptSig(Adapter,Adapter->eActiveDSD); + if(Status != STATUS_SUCCESS) + { + if(( (stNVMReadWrite.uiOffset + stNVMReadWrite.uiNumBytes) != Adapter->uiNVMDSDSize ) || + (stNVMReadWrite.uiNumBytes < SIGNATURE_SIZE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pReadData); + return Status; + } + + ulDSDMagicNumInUsrBuff = ntohl(*(PUINT)(pReadData + stNVMReadWrite.uiNumBytes - SIGNATURE_SIZE)); + if(ulDSDMagicNumInUsrBuff != DSD_IMAGE_MAGIC_NUMBER) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"DSD Sig is present neither in Flash nor User provided Input.."); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pReadData); + return Status; + } + } + } + Status = BeceemNVMWrite(Adapter, (PUINT )pReadData, + stNVMReadWrite.uiOffset, stNVMReadWrite.uiNumBytes, stNVMReadWrite.bVerify); + if(IsFlash2x(Adapter)) + BcmFlash2xWriteSig(Adapter,Adapter->eActiveDSD); + + Adapter->bHeaderChangeAllowed = FALSE ; + + up(&Adapter->NVMRdmWrmLock); + + + if(Status != STATUS_SUCCESS) + { + bcm_kfree(pReadData); + return Status; + } + } + do_gettimeofday(&tv1); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " timetaken by Write/read :%ld msec\n",(tv1.tv_sec - tv0.tv_sec)*1000 +(tv1.tv_usec - tv0.tv_usec)/1000); + + + bcm_kfree(pReadData); + Status = STATUS_SUCCESS; + } + break; + case IOCTL_BCM_FLASH2X_SECTION_READ : + { + + FLASH2X_READWRITE sFlash2xRead = {0}; + PUCHAR pReadBuff = NULL ; + UINT NOB = 0; + UINT BuffSize = 0; + UINT ReadBytes = 0; + UINT ReadOffset = 0; + PUCHAR OutPutBuff = NULL; + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_FLASH2X_SECTION_READ Called"); + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + return Status ; + } + + //Reading FLASH 2.x READ structure + Status = copy_from_user((PUCHAR)&sFlash2xRead, (PUCHAR)IoBuffer.InputBuffer,sizeof(FLASH2X_READWRITE)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Input Buffer failed"); + return Status ; + } + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xRead.Section); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%x" ,sFlash2xRead.offset); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xRead.numOfBytes); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xRead.bVerify); + + //This was internal to driver for raw read. now it has ben exposed to user space app. + if(validateFlash2xReadWrite(Adapter,&sFlash2xRead) == FALSE) + return STATUS_FAILURE ; + + NOB = sFlash2xRead.numOfBytes; + if(NOB > Adapter->uiSectorSize ) + BuffSize = Adapter->uiSectorSize; + else + BuffSize = NOB ; + + ReadOffset = sFlash2xRead.offset ; + OutPutBuff = (PUCHAR)(IoBuffer.OutputBuffer) ; + + + pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); + if(pReadBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); + return -ENOMEM; + } + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pReadBuff); + return -EACCES; + } + + while(NOB) + { + + if(NOB > Adapter->uiSectorSize ) + ReadBytes = Adapter->uiSectorSize; + else + ReadBytes = NOB; + + + //Reading the data from Flash 2.x + + Status = BcmFlash2xBulkRead(Adapter,(PUINT)pReadBuff,sFlash2xRead.Section,ReadOffset,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Flash 2x read err with Status :%d", Status); + break ; + } + + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes); + + Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Copy to use failed with status :%d", Status); + break; + } + NOB = NOB - ReadBytes; + if(NOB) + { + ReadOffset = ReadOffset + ReadBytes ; + OutPutBuff = OutPutBuff + ReadBytes ; + } + + } + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pReadBuff); + + } + break ; + case IOCTL_BCM_FLASH2X_SECTION_WRITE : + { + FLASH2X_READWRITE sFlash2xWrite = {0}; + PUCHAR pWriteBuff = NULL; + PUCHAR InputAddr = NULL; + UINT NOB = 0; + UINT BuffSize = 0; + UINT WriteOffset = 0; + UINT WriteBytes = 0; + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } + + //First make this False so that we can enable the Sector Permission Check in BeceemFlashBulkWrite + Adapter->bAllDSDWriteAllow = FALSE; + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_FLASH2X_SECTION_WRITE Called"); + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + return Status; + } + + //Reading FLASH 2.x READ structure + Status = copy_from_user((PCHAR)&sFlash2xWrite, (PCHAR)IoBuffer.InputBuffer, sizeof(FLASH2X_READWRITE)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reading of output Buffer from IOCTL buffer fails"); + return Status; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.Section :%x" ,sFlash2xWrite.Section); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.offset :%d" ,sFlash2xWrite.offset); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.numOfBytes :%x" ,sFlash2xWrite.numOfBytes); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\nsFlash2xRead.bVerify :%x\n" ,sFlash2xWrite.bVerify); + #if 0 + if((sFlash2xWrite.Section == ISO_IMAGE1) ||(sFlash2xWrite.Section == ISO_IMAGE2) || + (sFlash2xWrite.Section == DSD0) || (sFlash2xWrite.Section == DSD1) || (sFlash2xWrite.Section == DSD2)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"ISO/DSD Image write is not allowed.... "); + return STATUS_FAILURE ; + } + #endif + if((sFlash2xWrite.Section != VSA0) && (sFlash2xWrite.Section != VSA1) && + (sFlash2xWrite.Section != VSA2) ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Only VSA write is allowed"); + return -EINVAL; + } + + if(validateFlash2xReadWrite(Adapter,&sFlash2xWrite) == FALSE) + return STATUS_FAILURE ; + + InputAddr = (PCHAR)(sFlash2xWrite.pDataBuff) ; + WriteOffset = sFlash2xWrite.offset ; + NOB = sFlash2xWrite.numOfBytes; + + if(NOB > Adapter->uiSectorSize ) + BuffSize = Adapter->uiSectorSize; + else + BuffSize = NOB ; + + pWriteBuff = (PCHAR)kmalloc(BuffSize, GFP_KERNEL); + if(pWriteBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); + return -ENOMEM; + } + + //extracting the remainder of the given offset. + WriteBytes = Adapter->uiSectorSize ; + if(WriteOffset % Adapter->uiSectorSize) + WriteBytes =Adapter->uiSectorSize - (WriteOffset % Adapter->uiSectorSize); + if(NOB < WriteBytes) + WriteBytes = NOB; + + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pWriteBuff); + return -EACCES; + } + + BcmFlash2xCorruptSig(Adapter,sFlash2xWrite.Section); + do + { + Status = copy_from_user(pWriteBuff,InputAddr,WriteBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to user failed with status :%d", Status); + break ; + } + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pWriteBuff,WriteBytes); + //Writing the data from Flash 2.x + Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pWriteBuff,sFlash2xWrite.Section,WriteOffset,WriteBytes,sFlash2xWrite.bVerify); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status); + break ; + } + + NOB = NOB - WriteBytes; + if(NOB) + { + WriteOffset = WriteOffset + WriteBytes ; + InputAddr = InputAddr + WriteBytes ; + if(NOB > Adapter->uiSectorSize ) + WriteBytes = Adapter->uiSectorSize; + else + WriteBytes = NOB; + } + + + } while(NOB > 0); + BcmFlash2xWriteSig(Adapter,sFlash2xWrite.Section); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pWriteBuff); + } + break ; + case IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP : + { + + PFLASH2X_BITMAP psFlash2xBitMap = NULL ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP Called"); + + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + return Status; + } + if(IoBuffer.OutputLength != sizeof(FLASH2X_BITMAP)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Structure size mismatch Lib :0x%lx Driver :0x%x ",IoBuffer.OutputLength, sizeof(FLASH2X_BITMAP)); + break; + } + + psFlash2xBitMap = (PFLASH2X_BITMAP)kzalloc(sizeof(FLASH2X_BITMAP), GFP_KERNEL); + if(psFlash2xBitMap == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory is not available"); + return -ENOMEM ; + } + //Reading the Flash Sectio Bit map + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(psFlash2xBitMap); + return -EACCES; + } + + BcmGetFlash2xSectionalBitMap(Adapter, psFlash2xBitMap); + up(&Adapter->NVMRdmWrmLock); + Status = copy_to_user((PCHAR)IoBuffer.OutputBuffer, (PCHAR)psFlash2xBitMap, sizeof(FLASH2X_BITMAP)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash2x bitMap failed"); + bcm_kfree(psFlash2xBitMap); + return Status; + } + bcm_kfree(psFlash2xBitMap); + } + break ; + case IOCTL_BCM_SET_ACTIVE_SECTION : + { + FLASH2X_SECTION_VAL eFlash2xSectionVal = 0; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_SET_ACTIVE_SECTION Called"); + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } + + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + return Status; + } + + Status = copy_from_user((PCHAR)&eFlash2xSectionVal,(PCHAR)IoBuffer.InputBuffer, sizeof(INT)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); + return Status; + } + + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + return -EACCES; + } + + Status = BcmSetActiveSection(Adapter,eFlash2xSectionVal); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Failed to make it's priority Highest. Status %d", Status); + } + up(&Adapter->NVMRdmWrmLock); + } + break ; + case IOCTL_BCM_IDENTIFY_ACTIVE_SECTION : + { + //Right Now we are taking care of only DSD + Adapter->bAllDSDWriteAllow = FALSE ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_IDENTIFY_ACTIVE_SECTION called"); + + #if 0 + SECTION_TYPE section = 0 ; + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_IDENTIFY_ACTIVE_SECTION Called"); + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy of IOCTL BUFFER failed"); + return Status; + } + Status = copy_from_user((PCHAR)section,(PCHAR)&IoBuffer, sizeof(INT)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Copy of section type failed failed"); + return Status; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", section); + if(section == DSD) + Adapter->ulFlashCalStart = Adapter->uiActiveDSDOffsetAtFwDld ; + else + Status = STATUS_FAILURE ; + #endif + Status = STATUS_SUCCESS ; + } + break ; + case IOCTL_BCM_COPY_SECTION : + { + FLASH2X_COPY_SECTION sCopySectStrut = {0}; + Status = STATUS_SUCCESS; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "IOCTL_BCM_COPY_SECTION Called"); + + Adapter->bAllDSDWriteAllow = FALSE ; + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } + + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed Status :%d", Status); + return Status; + } + + Status = copy_from_user((PCHAR)&sCopySectStrut,(PCHAR)IoBuffer.InputBuffer, sizeof(FLASH2X_COPY_SECTION)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of Copy_Section_Struct failed with Status :%d", Status); + return Status; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Source SEction :%x", sCopySectStrut.SrcSection); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Destination SEction :%x", sCopySectStrut.DstSection); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "offset :%x", sCopySectStrut.offset); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "NOB :%x", sCopySectStrut.numOfBytes); + + + if(IsSectionExistInFlash(Adapter,sCopySectStrut.SrcSection) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source Section<%x> does not exixt in Flash ", sCopySectStrut.SrcSection); + return -EINVAL; + } + + if(IsSectionExistInFlash(Adapter,sCopySectStrut.DstSection) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destinatio Section<%x> does not exixt in Flash ", sCopySectStrut.DstSection); + return -EINVAL; + } + + if(sCopySectStrut.SrcSection == sCopySectStrut.DstSection) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Source and Destination section should be different"); + return -EINVAL; + } + + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + up(&Adapter->NVMRdmWrmLock); + return -EACCES; + } + + if(sCopySectStrut.SrcSection == ISO_IMAGE1 || sCopySectStrut.SrcSection == ISO_IMAGE2) + { + if(IsNonCDLessDevice(Adapter)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is Non-CDLess hence won't have ISO !!"); + Status = -EINVAL ; + } + else if(sCopySectStrut.numOfBytes == 0) + { + Status = BcmCopyISO(Adapter,sCopySectStrut); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Partial Copy of ISO section is not Allowed.."); + Status = STATUS_FAILURE ; + } + up(&Adapter->NVMRdmWrmLock); + return Status; + } + + Status = BcmCopySection(Adapter, sCopySectStrut.SrcSection, + sCopySectStrut.DstSection,sCopySectStrut.offset,sCopySectStrut.numOfBytes); + up(&Adapter->NVMRdmWrmLock); + } + break ; + case IOCTL_BCM_GET_FLASH_CS_INFO : + { + Status = STATUS_SUCCESS; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_GET_FLASH_CS_INFO Called"); + + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + break; + } + if(Adapter->eNVMType != NVM_FLASH) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Connected device does not have flash"); + Status = -EINVAL; + break; + } + if(IsFlash2x(Adapter) == TRUE) + { + + if(IoBuffer.OutputLength < sizeof(FLASH2X_CS_INFO)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Passed buffer size:0x%lX is insufficient for the CS structure.. \nRequired size :0x%x ",IoBuffer.OutputLength, sizeof(FLASH2X_CS_INFO)); + Status = -EINVAL; + break; + } + + Status = copy_to_user((PCHAR)IoBuffer.OutputBuffer, (PCHAR)Adapter->psFlash2xCSInfo, sizeof(FLASH2X_CS_INFO)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash2x cs info failed"); + break; + } + } + else + { + if(IoBuffer.OutputLength < sizeof(FLASH_CS_INFO)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Passed buffer size:0x%lX is insufficient for the CS structure.. Required size :0x%u ",IoBuffer.OutputLength, sizeof(FLASH_CS_INFO)); + Status = -EINVAL; + break; + } + Status = copy_to_user((PCHAR)IoBuffer.OutputBuffer, (PCHAR)Adapter->psFlashCSInfo, sizeof(FLASH_CS_INFO)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copying Flash CS info failed"); + break; + } + + } + } + break ; + case IOCTL_BCM_SELECT_DSD : + { + UINT SectOfset = 0; + FLASH2X_SECTION_VAL eFlash2xSectionVal; + eFlash2xSectionVal = NO_SECTION_VAL ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, " IOCTL_BCM_SELECT_DSD Called"); + + if(IsFlash2x(Adapter) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Does not have 2.x map"); + return -EINVAL; + } + + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + return Status; + } + Status = copy_from_user((PCHAR)&eFlash2xSectionVal,(PCHAR)IoBuffer.InputBuffer, sizeof(INT)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of flash section val failed"); + return Status; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Read Section :%d", eFlash2xSectionVal); + if((eFlash2xSectionVal != DSD0) && + (eFlash2xSectionVal != DSD1) && + (eFlash2xSectionVal != DSD2) ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Passed section<%x> is not DSD section", eFlash2xSectionVal); + return STATUS_FAILURE ; + } + + SectOfset= BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal); + if(SectOfset == INVALID_OFFSET) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section val <%d> does not exixt in Flash 2.x", eFlash2xSectionVal); + return -EINVAL; + } + + Adapter->bAllDSDWriteAllow = TRUE ; + + Adapter->ulFlashCalStart = SectOfset ; + Adapter->eActiveDSD = eFlash2xSectionVal; + } + Status = STATUS_SUCCESS ; + break; + + case IOCTL_BCM_NVM_RAW_READ : + { + + NVM_READWRITE stNVMRead = {0}; + INT NOB ; + INT BuffSize ; + INT ReadOffset = 0; + UINT ReadBytes = 0 ; + PUCHAR pReadBuff = NULL ; + PUCHAR OutPutBuff = NULL ; + + if(Adapter->eNVMType != NVM_FLASH) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"NVM TYPE is not Flash "); + return -EINVAL ; + } + + /* Copy Ioctl Buffer structure */ + if(copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy_from_user 1 failed\n"); + Status = -EFAULT; + break; + } + + if(copy_from_user(&stNVMRead, (PUCHAR)IoBuffer.OutputBuffer,sizeof(NVM_READWRITE))) + { + Status = -EFAULT; + break; + } + + NOB = stNVMRead.uiNumBytes; + //In Raw-Read max Buff size : 64MB + + if(NOB > DEFAULT_BUFF_SIZE) + BuffSize = DEFAULT_BUFF_SIZE; + else + BuffSize = NOB ; + + ReadOffset = stNVMRead.uiOffset ; + OutPutBuff = (PUCHAR)(stNVMRead.pBuffer) ; + + + pReadBuff = (PCHAR)kzalloc(BuffSize , GFP_KERNEL); + if(pReadBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for Flash 2.x Read Structure"); + Status = -ENOMEM; + break; + } + down(&Adapter->NVMRdmWrmLock); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Device is in Idle/Shutdown Mode\n"); + bcm_kfree(pReadBuff); + up(&Adapter->NVMRdmWrmLock); + return -EACCES; + } + + Adapter->bFlashRawRead = TRUE ; + while(NOB) + { + if(NOB > DEFAULT_BUFF_SIZE ) + ReadBytes = DEFAULT_BUFF_SIZE; + else + ReadBytes = NOB; + + //Reading the data from Flash 2.x + Status = BeceemNVMRead(Adapter,(PUINT)pReadBuff,ReadOffset,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash 2x read err with Status :%d", Status); + break; + } + + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,pReadBuff, ReadBytes); + + Status = copy_to_user(OutPutBuff, pReadBuff,ReadBytes); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Copy to use failed with status :%d", Status); + break; + } + NOB = NOB - ReadBytes; + if(NOB) + { + ReadOffset = ReadOffset + ReadBytes ; + OutPutBuff = OutPutBuff + ReadBytes ; + } + + } + Adapter->bFlashRawRead = FALSE ; + up(&Adapter->NVMRdmWrmLock); + bcm_kfree(pReadBuff); + break ; + } + + case IOCTL_BCM_CNTRLMSG_MASK: + { + ULONG RxCntrlMsgBitMask = 0 ; + + /* Copy Ioctl Buffer structure */ + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space"); + break; + } + + Status = copy_from_user(&RxCntrlMsgBitMask, IoBuffer.InputBuffer, IoBuffer.InputLength); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space"); + break; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask); + pTarang->RxCntrlMsgBitMask = RxCntrlMsgBitMask ; + } + break; + case IOCTL_BCM_GET_DEVICE_DRIVER_INFO: + { + DEVICE_DRIVER_INFO DevInfo; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); + + DevInfo.MaxRDMBufferSize = BUFFER_4K; + DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START; + DevInfo.u32RxAlignmentCorrection = 0; + DevInfo.u32NVMType = Adapter->eNVMType; + DevInfo.u32InterfaceType = BCM_USB; + + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + break; + } + if(IoBuffer.OutputLength < sizeof(DevInfo)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"User Passed buffer length is less than actural buffer size"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"user passed buffer size :0x%lX, expected size :0x%x",IoBuffer.OutputLength, sizeof(DevInfo)); + Status = -EINVAL; + break; + } + Status = copy_to_user((PCHAR)IoBuffer.OutputBuffer, (PCHAR)&DevInfo, sizeof(DevInfo)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copying Dev info structure to user space buffer failed"); + break; + } + } + break ; + + case IOCTL_BCM_TIME_SINCE_NET_ENTRY: + { + ST_TIME_ELAPSED stTimeElapsedSinceNetEntry = {0}; + struct timeval tv = {0} ; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"IOCTL_BCM_TIME_SINCE_NET_ENTRY called"); + + Status = copy_from_user((PCHAR)&IoBuffer, (PCHAR)arg, sizeof(IOCTL_BUFFER)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Copy of IOCTL BUFFER failed"); + break; + } + if(IoBuffer.OutputLength < sizeof(ST_TIME_ELAPSED)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"User Passed buffer length:0x%lx is less than expected buff size :0x%X",IoBuffer.OutputLength,sizeof(ST_TIME_ELAPSED)); + Status = -EINVAL; + break; + } + + //stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = Adapter->liTimeSinceLastNetEntry; + do_gettimeofday(&tv); + stTimeElapsedSinceNetEntry.ul64TimeElapsedSinceNetEntry = tv.tv_sec - Adapter->liTimeSinceLastNetEntry; + + Status = copy_to_user((PCHAR)IoBuffer.OutputBuffer, (PCHAR)&stTimeElapsedSinceNetEntry, sizeof(ST_TIME_ELAPSED)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"copying ST_TIME_ELAPSED structure to user space buffer failed"); + break; + } + + } + break; + + default: + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "wrong input %x",cmd); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "In default ioctl %d\n", cmd); + Status = STATUS_FAILURE; + + break; + } + return Status; +} + + +static struct file_operations bcm_fops = { + .owner = THIS_MODULE, + .open = bcm_char_open, + .release = bcm_char_release, + .read = bcm_char_read, + .unlocked_ioctl = bcm_char_ioctl, +}; + + +int register_control_device_interface(PMINI_ADAPTER Adapter) +{ + if(Adapter->major>0) + return Adapter->major; + Adapter->major = register_chrdev(0, "tarang", &bcm_fops); + if(Adapter->major < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "register_chrdev:Failed to registering WiMax control char device!"); + return Adapter->major; + } + + bcm_class = NULL; + bcm_class = class_create (THIS_MODULE, "tarang"); + if(IS_ERR (bcm_class)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unable to create class\n"); + unregister_chrdev(Adapter->major, "tarang"); + Adapter->major = 0; + return -ENODEV; + } + Adapter->pstCreatedClassDevice = device_create (bcm_class, NULL, + MKDEV(Adapter->major, 0), +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26) + NULL , +#endif + "tarang"); + + if(IS_ERR(Adapter->pstCreatedClassDevice)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "class device did not get created : %ld", PTR_ERR(Adapter->pstCreatedClassDevice) ); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Got Major No: %d", Adapter->major); + return 0; +} + +void unregister_control_device_interface(PMINI_ADAPTER Adapter) +{ + if(Adapter->major > 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "destroying class device"); + device_destroy (bcm_class, MKDEV(Adapter->major, 0)); + } + if(!IS_ERR(bcm_class)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "destroying created class "); + class_destroy (bcm_class); + bcm_class = NULL; + } + if(Adapter->major > 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"unregistering character interface"); + unregister_chrdev(Adapter->major, "tarang"); + } + +} diff --git a/drivers/staging/bcm/Bcmnet.c b/drivers/staging/bcm/Bcmnet.c new file mode 100644 index 0000000..d4f4800 --- /dev/null +++ b/drivers/staging/bcm/Bcmnet.c @@ -0,0 +1,266 @@ +#include "headers.h" + +static INT bcm_notify_event(struct notifier_block *nb, ULONG event, PVOID dev) +{ + struct net_device *ndev = (struct net_device*)dev; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + //PMINI_ADAPTER Adapter = (PMINI_ADAPTER)ndev->priv; + if(strncmp(ndev->name,gblpnetdev->name,5)==0) + { + switch(event) + { + case NETDEV_CHANGEADDR: + case NETDEV_GOING_DOWN: + /*ignore this */ + break; + case NETDEV_DOWN: + break; + + case NETDEV_UP: + break; + + case NETDEV_REGISTER: + /* Increment the Reference Count for "veth0" */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register RefCount: %x\n", + atomic_read(&ndev->refcnt)); + atomic_inc(&ndev->refcnt); + break; + + case NETDEV_UNREGISTER: + /* Decrement the Reference Count for "veth0" */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregister RefCnt: %x\n", + atomic_read(&ndev->refcnt)); + atomic_dec(&ndev->refcnt); + if((int)atomic_read(&ndev->refcnt) < 0) + atomic_set(&ndev->refcnt, 0); + break; + }; + } + return NOTIFY_DONE; +} + +/* Notifier block to receive netdevice events */ +static struct notifier_block bcm_notifier_block = +{ + .notifier_call = bcm_notify_event, +}; + +struct net_device *gblpnetdev; +/***************************************************************************************/ +/* proto-type of lower function */ +#ifdef BCM_SHM_INTERFACE +const char *bcmVirtDeviceName="bcmeth"; +#endif + +static INT bcm_open(struct net_device *dev) +{ + PMINI_ADAPTER Adapter = NULL ; //(PMINI_ADAPTER)dev->priv; + Adapter = GET_BCM_ADAPTER(dev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "======>"); + if(Adapter->fw_download_done==FALSE) + return -EINVAL; + Adapter->if_up=1; + if(Adapter->LinkUpStatus == 1){ + if(netif_queue_stopped(Adapter->dev)){ + netif_carrier_on(Adapter->dev); + netif_start_queue(Adapter->dev); + } + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "<======"); + return 0; +} + +static INT bcm_close(struct net_device *dev) +{ + PMINI_ADAPTER Adapter = NULL ;//gpadapter ; + Adapter = GET_BCM_ADAPTER(dev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=====>"); + Adapter->if_up=0; + if(!netif_queue_stopped(dev)) { + netif_carrier_off(dev); + netif_stop_queue(dev); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"<====="); + return 0; +} + +static struct net_device_stats *bcm_get_stats(struct net_device *dev) +{ + PLINUX_DEP_DATA pLinuxData=NULL; + PMINI_ADAPTER Adapter = NULL ;// gpadapter ; + Adapter = GET_BCM_ADAPTER(dev); + pLinuxData = (PLINUX_DEP_DATA)(Adapter->pvOsDepData); + + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Dev = %p, pLinuxData = %p", dev, pLinuxData); + pLinuxData->netstats.rx_packets=atomic_read(&Adapter->RxRollOverCount)*64*1024+Adapter->PrevNumRecvDescs; + pLinuxData->netstats.rx_bytes=atomic_read(&Adapter->GoodRxByteCount)+atomic_read(&Adapter->BadRxByteCount); + pLinuxData->netstats.rx_dropped=atomic_read(&Adapter->RxPacketDroppedCount); + pLinuxData->netstats.rx_errors=atomic_read(&Adapter->RxPacketDroppedCount); + pLinuxData->netstats.rx_length_errors=0; + pLinuxData->netstats.rx_frame_errors=0; + pLinuxData->netstats.rx_crc_errors=0; + pLinuxData->netstats.tx_bytes=atomic_read(&Adapter->GoodTxByteCount); + pLinuxData->netstats.tx_packets=atomic_read(&Adapter->TxTotalPacketCount); + pLinuxData->netstats.tx_dropped=atomic_read(&Adapter->TxDroppedPacketCount); + + return &(pLinuxData->netstats); +} +/** +@ingroup init_functions +Register other driver entry points with the kernel +*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) +struct net_device_ops bcmNetDevOps = { + .ndo_open = bcm_open, + .ndo_stop = bcm_close, + .ndo_get_stats = bcm_get_stats, + .ndo_start_xmit = bcm_transmit, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; +#endif + +int register_networkdev(PMINI_ADAPTER Adapter) +{ + int result=0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) + int *temp = NULL ; +#endif + Adapter->dev = alloc_etherdev(sizeof(PMINI_ADAPTER)); + if(!Adapter->dev) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "ERR: No Dev"); + return -ENOMEM; + } + gblpnetdev = Adapter->dev; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + Adapter->dev->priv = Adapter; +#else + temp = netdev_priv(Adapter->dev); + *temp = (UINT)Adapter; +#endif + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "init adapterptr: %x %x\n", (UINT)Adapter, temp); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) + Adapter->dev->netdev_ops = &bcmNetDevOps; +#else + Adapter->dev->open = bcm_open; + Adapter->dev->stop = bcm_close; + Adapter->dev->get_stats = bcm_get_stats; + Adapter->dev->hard_start_xmit = bcm_transmit; + Adapter->dev->hard_header_len = ETH_HLEN + LEADER_SIZE; +#endif + +#ifndef BCM_SHM_INTERFACE + Adapter->dev->mtu = MTU_SIZE; /* 1400 Bytes */ + /* Read the MAC Address from EEPROM */ + ReadMacAddressFromNVM(Adapter); + + + /* Register the notifier block for getting netdevice events */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Registering netdevice notifier\n"); + result = register_netdevice_notifier(&bcm_notifier_block); + if(result) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM Notifier Block did not get registered"); + Adapter->bNetdeviceNotifierRegistered = FALSE; + return result; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM Notifier got Registered"); + Adapter->bNetdeviceNotifierRegistered = TRUE; + } + +#else + + Adapter->dev->mtu = CPE_MTU_SIZE; + +#if 0 + //for CPE - harcode the virtual mac address + Adapter->dev->dev_addr[0] = MII_WIMAX_MACADDRESS[0]; + Adapter->dev->dev_addr[1] = MII_WIMAX_MACADDRESS[1]; + Adapter->dev->dev_addr[2] = MII_WIMAX_MACADDRESS[2]; + Adapter->dev->dev_addr[3] = MII_WIMAX_MACADDRESS[3]; + Adapter->dev->dev_addr[4] = MII_WIMAX_MACADDRESS[4]; + Adapter->dev->dev_addr[5] = MII_WIMAX_MACADDRESS[5]; +#else + ReadMacAddressFromNVM(Adapter); +#endif + strcpy(Adapter->dev->name, bcmVirtDeviceName); //Copy the device name + +#endif + + result = register_netdev(Adapter->dev); + if (!result) + { + Adapter->bNetworkInterfaceRegistered = TRUE ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Beceem Network device name is %s!", Adapter->dev->name); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Network device can not be registered!"); + Adapter->bNetworkInterfaceRegistered = FALSE ; + return result; + } + +#if 0 + Adapter->stDebugState.debug_level = DBG_LVL_CURR; + Adapter->stDebugState.type =(UINT)0xffffffff; + Adapter->stDebugState.subtype[DBG_TYPE_OTHERS] = 0xffffffff; + Adapter->stDebugState.subtype[DBG_TYPE_RX] = 0xffffffff; + Adapter->stDebugState.subtype[DBG_TYPE_TX] = 0xffffffff; + Adapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xffffffff; + + printk("-------ps_adapter->stDebugState.type=%x\n",Adapter->stDebugState.type); + printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_OTHERS]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_OTHERS]); + printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_RX]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_RX]); + printk("-------ps_adapter->stDebugState.subtype[DBG_TYPE_TX]=%x\n",Adapter->stDebugState.subtype[DBG_TYPE_TX]); +#endif + + return 0; +} + +void bcm_unregister_networkdev(PMINI_ADAPTER Adapter) +{ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregistering the Net Dev...\n"); + if(Adapter->dev && !IS_ERR(Adapter->dev) && Adapter->bNetworkInterfaceRegistered) + unregister_netdev(Adapter->dev); + /* Unregister the notifier block */ + if(Adapter->bNetdeviceNotifierRegistered == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Unregistering netdevice notifier\n"); + unregister_netdevice_notifier(&bcm_notifier_block); + } +} + +static int bcm_init(void) +{ + int result; + result = InterfaceInitialize(); + if(result) + { + printk("Initialisation failed for usbbcm"); + } + else + { + printk("Initialised usbbcm"); + } + return result; +} + + +static void bcm_exit(void) +{ + printk("%s %s Calling InterfaceExit\n",__FILE__, __FUNCTION__); + InterfaceExit(); + printk("%s %s InterfaceExit returned\n",__FILE__, __FUNCTION__); +} + +module_init(bcm_init); +module_exit(bcm_exit); +MODULE_LICENSE ("GPL"); + + diff --git a/drivers/staging/bcm/CmHost.c b/drivers/staging/bcm/CmHost.c new file mode 100644 index 0000000..d1a6683 --- /dev/null +++ b/drivers/staging/bcm/CmHost.c @@ -0,0 +1,2443 @@ +/************************************************************ +* CMHOST.C +* This file contains the routines for handling Connnection +* Management. +************************************************************/ + +//#define CONN_MSG +#include "headers.h" + +typedef enum _E_CLASSIFIER_ACTION +{ + eInvalidClassifierAction, + eAddClassifier, + eReplaceClassifier, + eDeleteClassifier +}E_CLASSIFIER_ACTION; + + +/************************************************************ +* Function - SearchSfid +* +* Description - This routinue would search QOS queues having +* specified SFID as input parameter. +* +* Parameters - Adapter: Pointer to the Adapter structure +* uiSfid : Given SFID for matching +* +* Returns - Queue index for this SFID(If matched) + Else Invalid Queue Index(If Not matched) +************************************************************/ +__inline INT SearchSfid(PMINI_ADAPTER Adapter,UINT uiSfid) +{ + INT iIndex=0; + for(iIndex=(NO_OF_QUEUES-1); iIndex>=0; iIndex--) + if(Adapter->PackInfo[iIndex].ulSFID==uiSfid) + return iIndex; + return NO_OF_QUEUES+1; +} + +/*************************************************************** +* Function - SearchFreeSfid +* +* Description - This routinue would search Free available SFID. +* +* Parameter - Adapter: Pointer to the Adapter structure +* +* Returns - Queue index for the free SFID +* Else returns Invalid Index. +****************************************************************/ +__inline INT SearchFreeSfid(PMINI_ADAPTER Adapter) +{ + UINT uiIndex=0; + for(uiIndex=0; uiIndex < (NO_OF_QUEUES-1); uiIndex++) + if(Adapter->PackInfo[uiIndex].ulSFID==0) + return uiIndex; + return NO_OF_QUEUES+1; +} + +__inline int SearchVcid(PMINI_ADAPTER Adapter,unsigned short usVcid) +{ + int iIndex=0; + for(iIndex=(NO_OF_QUEUES-1);iIndex>=0;iIndex--) + if(Adapter->PackInfo[iIndex].usVCID_Value == usVcid) + return iIndex; + return NO_OF_QUEUES+1; + +} + + +/* +Function: SearchClsid +Description: This routinue would search Classifier having specified ClassifierID as input parameter +Input parameters: PMINI_ADAPTER Adapter - Adapter Context + unsigned int uiSfid - The SF in which the classifier is to searched + B_UINT16 uiClassifierID - The classifier ID to be searched +Return: int :Classifier table index of matching entry +*/ + +__inline int SearchClsid(PMINI_ADAPTER Adapter,ULONG ulSFID,B_UINT16 uiClassifierID) +{ + unsigned int uiClassifierIndex = 0; + for(uiClassifierIndex=0;uiClassifierIndexastClassifierTable[uiClassifierIndex].bUsed) && + (Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex == uiClassifierID)&& + (Adapter->astClassifierTable[uiClassifierIndex].ulSFID == ulSFID)) + return uiClassifierIndex; + } + return MAX_CLASSIFIERS+1; +} + +/** +@ingroup ctrl_pkt_functions +This routinue would search Free available Classifier entry in classifier table. +@return free Classifier Entry index in classifier table for specified SF +*/ +static __inline int SearchFreeClsid(PMINI_ADAPTER Adapter /**Adapter Context*/ + ) +{ + unsigned int uiClassifierIndex = 0; + for(uiClassifierIndex=0;uiClassifierIndexastClassifierTable[uiClassifierIndex].bUsed) + return uiClassifierIndex; + } + return MAX_CLASSIFIERS+1; +} + +VOID deleteSFBySfid(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex) +{ + //deleting all the packet held in the SF + flush_queue(Adapter,uiSearchRuleIndex); + + //Deleting the all classifiers for this SF + DeleteAllClassifiersForSF(Adapter,uiSearchRuleIndex); + + //Resetting only MIBS related entries in the SF + memset((PVOID)&Adapter->PackInfo[uiSearchRuleIndex], 0, sizeof(S_MIBS_SERVICEFLOW_TABLE)); +} + +static inline VOID +CopyIpAddrToClassifier(S_CLASSIFIER_RULE *pstClassifierEntry , + B_UINT8 u8IpAddressLen , B_UINT8 *pu8IpAddressMaskSrc , + BOOLEAN bIpVersion6 , E_IPADDR_CONTEXT eIpAddrContext) +{ + UINT ucLoopIndex=0; + UINT nSizeOfIPAddressInBytes = IP_LENGTH_OF_ADDRESS; + UCHAR *ptrClassifierIpAddress = NULL; + UCHAR *ptrClassifierIpMask = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + if(bIpVersion6) + { + nSizeOfIPAddressInBytes = IPV6_ADDRESS_SIZEINBYTES; + } + //Destination Ip Address + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Ip Address Range Length:0x%X ", + u8IpAddressLen); + if((bIpVersion6?(IPV6_ADDRESS_SIZEINBYTES * MAX_IP_RANGE_LENGTH * 2): + (TOTAL_MASKED_ADDRESS_IN_BYTES)) >= u8IpAddressLen) + { + /* + //checking both the mask and address togethor in Classification. + //So length will be : TotalLengthInBytes/nSizeOfIPAddressInBytes * 2 + //(nSizeOfIPAddressInBytes for address and nSizeOfIPAddressInBytes for mask) + */ + if(eIpAddrContext == eDestIpAddress) + { + pstClassifierEntry->ucIPDestinationAddressLength = + u8IpAddressLen/(nSizeOfIPAddressInBytes * 2); + if(bIpVersion6) + { + ptrClassifierIpAddress = + pstClassifierEntry->stDestIpAddress.ucIpv6Address; + ptrClassifierIpMask = + pstClassifierEntry->stDestIpAddress.ucIpv6Mask; + } + else + { + ptrClassifierIpAddress = + pstClassifierEntry->stDestIpAddress.ucIpv4Address; + ptrClassifierIpMask = + pstClassifierEntry->stDestIpAddress.ucIpv4Mask; + } + } + else if(eIpAddrContext == eSrcIpAddress) + { + pstClassifierEntry->ucIPSourceAddressLength = + u8IpAddressLen/(nSizeOfIPAddressInBytes * 2); + if(bIpVersion6) + { + ptrClassifierIpAddress = + pstClassifierEntry->stSrcIpAddress.ucIpv6Address; + ptrClassifierIpMask = + pstClassifierEntry->stSrcIpAddress.ucIpv6Mask; + } + else + { + ptrClassifierIpAddress = + pstClassifierEntry->stSrcIpAddress.ucIpv4Address; + ptrClassifierIpMask = + pstClassifierEntry->stSrcIpAddress.ucIpv4Mask; + } + } + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Address Length:0x%X \n", + pstClassifierEntry->ucIPDestinationAddressLength); + while((u8IpAddressLen>= nSizeOfIPAddressInBytes) && + (ucLoopIndex < MAX_IP_RANGE_LENGTH)) + { + memcpy(ptrClassifierIpAddress + + (ucLoopIndex * nSizeOfIPAddressInBytes), + (pu8IpAddressMaskSrc+(ucLoopIndex*nSizeOfIPAddressInBytes*2)), + nSizeOfIPAddressInBytes); + if(!bIpVersion6) + { + if(eIpAddrContext == eSrcIpAddress) + { + pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]= + ntohl(pstClassifierEntry->stSrcIpAddress. + ulIpv4Addr[ucLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Src Ip Address:0x%luX ",pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[ucLoopIndex]); + } + else if(eIpAddrContext == eDestIpAddress) + { + pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]= ntohl(pstClassifierEntry->stDestIpAddress. + ulIpv4Addr[ucLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Dest Ip Address:0x%luX ",pstClassifierEntry->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); + } + } + u8IpAddressLen-=nSizeOfIPAddressInBytes; + if(u8IpAddressLen >= nSizeOfIPAddressInBytes) + { + memcpy(ptrClassifierIpMask + + (ucLoopIndex * nSizeOfIPAddressInBytes), + (pu8IpAddressMaskSrc+nSizeOfIPAddressInBytes + + (ucLoopIndex*nSizeOfIPAddressInBytes*2)), + nSizeOfIPAddressInBytes); + if(!bIpVersion6) + { + if(eIpAddrContext == eSrcIpAddress) + { + pstClassifierEntry->stSrcIpAddress. + ulIpv4Mask[ucLoopIndex]= + ntohl(pstClassifierEntry->stSrcIpAddress. + ulIpv4Mask[ucLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Src Ip Mask Address:0x%luX ",pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[ucLoopIndex]); + } + else if(eIpAddrContext == eDestIpAddress) + { + pstClassifierEntry->stDestIpAddress. + ulIpv4Mask[ucLoopIndex] = + ntohl(pstClassifierEntry->stDestIpAddress. + ulIpv4Mask[ucLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Dest Ip Mask Address:0x%luX ",pstClassifierEntry->stDestIpAddress.ulIpv4Mask[ucLoopIndex]); + } + } + u8IpAddressLen-=nSizeOfIPAddressInBytes; + } + if(0==u8IpAddressLen) + { + pstClassifierEntry->bDestIpValid=TRUE; + } + ucLoopIndex++; + } + if(bIpVersion6) + { + //Restore EndianNess of Struct + for(ucLoopIndex =0 ; ucLoopIndex < MAX_IP_RANGE_LENGTH * 4 ; + ucLoopIndex++) + { + if(eIpAddrContext == eSrcIpAddress) + { + pstClassifierEntry->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]= + ntohl(pstClassifierEntry->stSrcIpAddress. + ulIpv6Addr[ucLoopIndex]); + pstClassifierEntry->stSrcIpAddress.ulIpv6Mask[ucLoopIndex]= ntohl(pstClassifierEntry->stSrcIpAddress. + ulIpv6Mask[ucLoopIndex]); + } + else if(eIpAddrContext == eDestIpAddress) + { + pstClassifierEntry->stDestIpAddress.ulIpv6Addr[ucLoopIndex]= ntohl(pstClassifierEntry->stDestIpAddress. + ulIpv6Addr[ucLoopIndex]); + pstClassifierEntry->stDestIpAddress.ulIpv6Mask[ucLoopIndex]= ntohl(pstClassifierEntry->stDestIpAddress. + ulIpv6Mask[ucLoopIndex]); + } + } + } + } +} + + +void ClearTargetDSXBuffer(PMINI_ADAPTER Adapter,B_UINT16 TID,BOOLEAN bFreeAll) +{ + ULONG ulIndex; + for(ulIndex=0; ulIndex < Adapter->ulTotalTargetBuffersAvailable; ulIndex++) + { + if(Adapter->astTargetDsxBuffer[ulIndex].valid) + continue; + if ((bFreeAll) || (Adapter->astTargetDsxBuffer[ulIndex].tid == TID)){ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ClearTargetDSXBuffer: found tid %d buffer cleared %lx\n", + TID, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); + Adapter->astTargetDsxBuffer[ulIndex].valid=1; + Adapter->astTargetDsxBuffer[ulIndex].tid=0; + Adapter->ulFreeTargetBufferCnt++; + } + } +} + +/** +@ingroup ctrl_pkt_functions +copy classifier rule into the specified SF index +*/ +static inline VOID CopyClassifierRuleToSF(PMINI_ADAPTER Adapter,stConvergenceSLTypes *psfCSType,UINT uiSearchRuleIndex,UINT nClassifierIndex) +{ + S_CLASSIFIER_RULE *pstClassifierEntry = NULL; + //VOID *pvPhsContext = NULL; + UINT ucLoopIndex=0; + //UCHAR ucProtocolLength=0; + //ULONG ulPhsStatus; + + + if(Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value == 0 || + nClassifierIndex > (MAX_CLASSIFIERS-1)) + return; + + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Storing Classifier Rule Index : %X",ntohs(psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex)); + + if(nClassifierIndex > MAX_CLASSIFIERS-1) + return; + + pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex]; + if(pstClassifierEntry) + { + //Store if Ipv6 + pstClassifierEntry->bIpv6Protocol = + (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6)?TRUE:FALSE; + + //Destinaiton Port + pstClassifierEntry->ucDestPortRangeLength=psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength/4; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Destination Port Range Length:0x%X ",pstClassifierEntry->ucDestPortRangeLength); + if( MAX_PORT_RANGE >= psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength) + { + for(ucLoopIndex=0;ucLoopIndex<(pstClassifierEntry->ucDestPortRangeLength);ucLoopIndex++) + { + pstClassifierEntry->usDestPortRangeLo[ucLoopIndex] = + *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+ucLoopIndex)); + pstClassifierEntry->usDestPortRangeHi[ucLoopIndex] = + *((PUSHORT)(psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange+2+ucLoopIndex)); + pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]=ntohs(pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Destination Port Range Lo:0x%X ",pstClassifierEntry->usDestPortRangeLo[ucLoopIndex]); + pstClassifierEntry->usDestPortRangeHi[ucLoopIndex]=ntohs(pstClassifierEntry->usDestPortRangeHi[ucLoopIndex]); + } + } + else + { + pstClassifierEntry->ucDestPortRangeLength=0; + } + //Source Port + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Source Port Range Length:0x%X ",psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + if(MAX_PORT_RANGE >= + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength) + { + pstClassifierEntry->ucSrcPortRangeLength = + psfCSType->cCPacketClassificationRule. + u8ProtocolSourcePortRangeLength/4; + for(ucLoopIndex = 0; ucLoopIndex < + (pstClassifierEntry->ucSrcPortRangeLength); ucLoopIndex++) + { + pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex] = + *((PUSHORT)(psfCSType->cCPacketClassificationRule. + u8ProtocolSourcePortRange+ucLoopIndex)); + pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex] = + *((PUSHORT)(psfCSType->cCPacketClassificationRule. + u8ProtocolSourcePortRange+2+ucLoopIndex)); + pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex] = + ntohs(pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Source Port Range Lo:0x%X ",pstClassifierEntry->usSrcPortRangeLo[ucLoopIndex]); + pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex]=ntohs(pstClassifierEntry->usSrcPortRangeHi[ucLoopIndex]); + } + } + //Destination Ip Address and Mask + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Ip Destination Parameters : "); + + CopyIpAddrToClassifier(pstClassifierEntry, + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength, + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress, + (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6)? + TRUE:FALSE, eDestIpAddress); + + //Source Ip Address and Mask + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Ip Source Parameters : "); + + CopyIpAddrToClassifier(pstClassifierEntry, + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength, + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress, + (Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion == IPV6)?TRUE:FALSE, + eSrcIpAddress); + + //TOS + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"TOS Length:0x%X ",psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + if(3 == psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength) + { + pstClassifierEntry->ucIPTypeOfServiceLength = + psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength; + pstClassifierEntry->ucTosLow = + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0]; + pstClassifierEntry->ucTosHigh = + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1]; + pstClassifierEntry->ucTosMask = + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]; + pstClassifierEntry->bTOSValid = TRUE; + } + if(psfCSType->cCPacketClassificationRule.u8Protocol == 0) + { + //we didnt get protocol field filled in by the BS + pstClassifierEntry->ucProtocolLength=0; + } + else + { + pstClassifierEntry->ucProtocolLength=1;// 1 valid protocol + } + + pstClassifierEntry->ucProtocol[0] = + psfCSType->cCPacketClassificationRule.u8Protocol; + + pstClassifierEntry->u8ClassifierRulePriority = + psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority; + + //store the classifier rule ID and set this classifier entry as valid + pstClassifierEntry->ucDirection = + Adapter->PackInfo[uiSearchRuleIndex].ucDirection; + pstClassifierEntry->uiClassifierRuleIndex = ntohs(psfCSType-> + cCPacketClassificationRule.u16PacketClassificationRuleIndex); + pstClassifierEntry->usVCID_Value = + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value; + pstClassifierEntry->ulSFID = + Adapter->PackInfo[uiSearchRuleIndex].ulSFID; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Search Index %d Dir: %d, Index: %d, Vcid: %d\n", + uiSearchRuleIndex, pstClassifierEntry->ucDirection, + pstClassifierEntry->uiClassifierRuleIndex, + pstClassifierEntry->usVCID_Value); + + if(psfCSType->cCPacketClassificationRule.u8AssociatedPHSI) + { + pstClassifierEntry->u8AssociatedPHSI = psfCSType->cCPacketClassificationRule.u8AssociatedPHSI; + } + + //Copy ETH CS Parameters + pstClassifierEntry->ucEthCSSrcMACLen = (psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddressLength); + memcpy(pstClassifierEntry->au8EThCSSrcMAC,psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress,MAC_ADDRESS_SIZE); + memcpy(pstClassifierEntry->au8EThCSSrcMACMask,psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress+MAC_ADDRESS_SIZE,MAC_ADDRESS_SIZE); + pstClassifierEntry->ucEthCSDestMACLen = (psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + memcpy(pstClassifierEntry->au8EThCSDestMAC,psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress,MAC_ADDRESS_SIZE); + memcpy(pstClassifierEntry->au8EThCSDestMACMask,psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress+MAC_ADDRESS_SIZE,MAC_ADDRESS_SIZE); + pstClassifierEntry->ucEtherTypeLen = (psfCSType->cCPacketClassificationRule.u8EthertypeLength); + memcpy(pstClassifierEntry->au8EthCSEtherType,psfCSType->cCPacketClassificationRule.u8Ethertype,NUM_ETHERTYPE_BYTES); + memcpy(pstClassifierEntry->usUserPriority, &psfCSType->cCPacketClassificationRule.u16UserPriority, 2); + pstClassifierEntry->usVLANID = ntohs(psfCSType->cCPacketClassificationRule.u16VLANID); + pstClassifierEntry->usValidityBitMap = ntohs(psfCSType->cCPacketClassificationRule.u16ValidityBitMap); + + pstClassifierEntry->bUsed = TRUE; + } +} + + +/** +@ingroup ctrl_pkt_functions +*/ +static inline VOID DeleteClassifierRuleFromSF(PMINI_ADAPTER Adapter,UINT uiSearchRuleIndex,UINT nClassifierIndex) +{ + S_CLASSIFIER_RULE *pstClassifierEntry = NULL; + B_UINT16 u16PacketClassificationRuleIndex; + USHORT usVCID; + //VOID *pvPhsContext = NULL; + //ULONG ulPhsStatus; + + usVCID = Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value; + + if(nClassifierIndex > MAX_CLASSIFIERS-1) + return; + + if(usVCID == 0) + return; + + u16PacketClassificationRuleIndex = Adapter->astClassifierTable[nClassifierIndex].uiClassifierRuleIndex; + + + pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex]; + if(pstClassifierEntry) + { + pstClassifierEntry->bUsed = FALSE; + pstClassifierEntry->uiClassifierRuleIndex = 0; + memset(pstClassifierEntry,0,sizeof(S_CLASSIFIER_RULE)); + + //Delete the PHS Rule for this classifier + PhsDeleteClassifierRule( + &Adapter->stBCMPhsContext, + usVCID, + u16PacketClassificationRuleIndex); + } +} + +/** +@ingroup ctrl_pkt_functions +*/ +VOID DeleteAllClassifiersForSF(PMINI_ADAPTER Adapter,UINT uiSearchRuleIndex) +{ + S_CLASSIFIER_RULE *pstClassifierEntry = NULL; + UINT nClassifierIndex; + //B_UINT16 u16PacketClassificationRuleIndex; + USHORT ulVCID; + //VOID *pvPhsContext = NULL; + //ULONG ulPhsStatus; + + ulVCID = Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value; + + if(ulVCID == 0) + return; + + + for(nClassifierIndex =0 ; nClassifierIndex < MAX_CLASSIFIERS ; nClassifierIndex++) + { + if(Adapter->astClassifierTable[nClassifierIndex].usVCID_Value == ulVCID) + { + pstClassifierEntry = &Adapter->astClassifierTable[nClassifierIndex]; + if(pstClassifierEntry->bUsed) + { + DeleteClassifierRuleFromSF(Adapter,uiSearchRuleIndex,nClassifierIndex); + } + } + } + + //Delete All Phs Rules Associated with this SF + PhsDeleteSFRules( + &Adapter->stBCMPhsContext, + ulVCID); + +} + + +/** +This routinue copies the Connection Management +related data into the Adapter structure. +@ingroup ctrl_pkt_functions +*/ + +static VOID CopyToAdapter( register PMINI_ADAPTER Adapter, /**PackInfo[uiSearchRuleIndex].usVCID_Value; + UINT UGIValue = 0; + + + Adapter->PackInfo[uiSearchRuleIndex].bValid=TRUE; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Search Rule Index = %d\n", uiSearchRuleIndex); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"%s: SFID= %x ",__FUNCTION__, ntohl(psfLocalSet->u32SFID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Updating Queue %d",uiSearchRuleIndex); + + ulSFID = ntohl(psfLocalSet->u32SFID); + //Store IP Version used + //Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF + + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = 0; + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = 0; + + /*Enable IP/ETh CS Support As Required*/ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"CopyToAdapter : u8CSSpecification : %X\n",psfLocalSet->u8CSSpecification); + switch(psfLocalSet->u8CSSpecification) + { + case eCSPacketIPV4: + { + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; + break; + } + case eCSPacketIPV6: + { + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS; + break; + } + + case eCS802_3PacketEthernet: + case eCS802_1QPacketVLAN: + { + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; + break; + } + + case eCSPacketIPV4Over802_1QVLAN: + case eCSPacketIPV4Over802_3Ethernet: + { + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; + break; + } + + case eCSPacketIPV6Over802_1QVLAN: + case eCSPacketIPV6Over802_3Ethernet: + { + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV6_CS; + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = ETH_CS_802_3; + break; + } + + default: + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error in value of CS Classification.. setting default to IP CS\n"); + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport = IPV4_CS; + break; + } + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"CopyToAdapter : Queue No : %X ETH CS Support : %X , IP CS Support : %X \n", + uiSearchRuleIndex, + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport, + Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport); + + //Store IP Version used + //Get The Version Of IP used (IPv6 or IPv4) from CSSpecification field of SF + if(Adapter->PackInfo[uiSearchRuleIndex].bIPCSSupport == IPV6_CS) + { + Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion = IPV6; + } + else + { + Adapter->PackInfo[uiSearchRuleIndex].ucIpVersion = IPV4; + } + + /* To ensure that the ETH CS code doesn't gets executed if the BS doesn't supports ETH CS */ + if(!Adapter->bETHCSEnabled) + Adapter->PackInfo[uiSearchRuleIndex].bEthCSSupport = 0; + + if(psfLocalSet->u8ServiceClassNameLength > 0 && + psfLocalSet->u8ServiceClassNameLength < 32) + { + memcpy(Adapter->PackInfo[uiSearchRuleIndex].ucServiceClassName, + psfLocalSet->u8ServiceClassName, + psfLocalSet->u8ServiceClassNameLength); + } + Adapter->PackInfo[uiSearchRuleIndex].u8QueueType = + psfLocalSet->u8ServiceFlowSchedulingType; + + if(Adapter->PackInfo[uiSearchRuleIndex].u8QueueType==BE && + Adapter->PackInfo[uiSearchRuleIndex].ucDirection) + { + Adapter->usBestEffortQueueIndex=uiSearchRuleIndex; + } + + Adapter->PackInfo[uiSearchRuleIndex].ulSFID = ntohl(psfLocalSet->u32SFID); + + Adapter->PackInfo[uiSearchRuleIndex].u8TrafficPriority = psfLocalSet->u8TrafficPriority; + + //copy all the classifier in the Service Flow param structure + for(nIndex=0; nIndexu8TotalClassifiers; nIndex++) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Classifier index =%d",nIndex); + psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Classifier index =%d",nIndex); + + if(psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority) + { + Adapter->PackInfo[uiSearchRuleIndex].bClassifierPriority=TRUE; + } + + if(psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority) + { + Adapter->PackInfo[uiSearchRuleIndex].bClassifierPriority=TRUE; + } + + + if(ucDsxType== DSA_ACK) + { + eClassifierAction = eAddClassifier; + } + else if(ucDsxType == DSC_ACK) + { + switch(psfCSType->u8ClassfierDSCAction) + { + case 0://DSC Add Classifier + { + eClassifierAction = eAddClassifier; + } + break; + case 1://DSC Replace Classifier + { + eClassifierAction = eReplaceClassifier; + } + break; + case 2://DSC Delete Classifier + { + eClassifierAction = eDeleteClassifier; + + } + break; + default: + { + eClassifierAction = eInvalidClassifierAction; + } + } + } + + u16PacketClassificationRuleIndex = ntohs(psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + + switch(eClassifierAction) + { + case eAddClassifier: + { + //Get a Free Classifier Index From Classifier table for this SF to add the Classifier + //Contained in this message + nClassifierIndex = SearchClsid(Adapter,ulSFID,u16PacketClassificationRuleIndex); + + if(nClassifierIndex > MAX_CLASSIFIERS) + { + nClassifierIndex = SearchFreeClsid(Adapter); + if(nClassifierIndex > MAX_CLASSIFIERS) + { + //Failed To get a free Entry + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error Failed To get a free Classifier Entry"); + break; + } + //Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. + CopyClassifierRuleToSF(Adapter,psfCSType,uiSearchRuleIndex,nClassifierIndex); + } + + else + { + //This Classifier Already Exists and it is invalid to Add Classifier with existing PCRI + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"CopyToAdapter : Error The Specified Classifier Already Exists \ + and attempted To Add Classifier with Same PCRI : 0x%x\n", u16PacketClassificationRuleIndex); + } + } + break; + + case eReplaceClassifier: + { + //Get the Classifier Index From Classifier table for this SF and replace existing Classifier + //with the new classifier Contained in this message + nClassifierIndex = SearchClsid(Adapter,ulSFID,u16PacketClassificationRuleIndex); + if(nClassifierIndex > MAX_CLASSIFIERS) + { + //Failed To search the classifier + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error Search for Classifier To be replaced failed"); + break; + } + //Copy the Classifier Rule for this service flow into our Classifier table maintained per SF. + CopyClassifierRuleToSF(Adapter,psfCSType,uiSearchRuleIndex,nClassifierIndex); + } + break; + + case eDeleteClassifier: + { + //Get the Classifier Index From Classifier table for this SF and replace existing Classifier + //with the new classifier Contained in this message + nClassifierIndex = SearchClsid(Adapter,ulSFID,u16PacketClassificationRuleIndex); + if(nClassifierIndex > MAX_CLASSIFIERS) + { + //Failed To search the classifier + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Error Search for Classifier To be deleted failed"); + break; + } + + //Delete This classifier + DeleteClassifierRuleFromSF(Adapter,uiSearchRuleIndex,nClassifierIndex); + } + break; + + default: + { + //Invalid Action for classifier + break; + } + } + } + + //Repeat parsing Classification Entries to process PHS Rules + for(nIndex=0; nIndex < psfLocalSet->u8TotalClassifiers; nIndex++) + { + psfCSType = &psfLocalSet->cConvergenceSLTypes[nIndex]; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "psfCSType->u8PhsDSCAction : 0x%x\n", + psfCSType->u8PhsDSCAction ); + + switch (psfCSType->u8PhsDSCAction) + { + case eDeleteAllPHSRules: + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Deleting All PHS Rules For VCID: 0x%X\n",uVCID); + + //Delete All the PHS rules for this Service flow + + PhsDeleteSFRules( + &Adapter->stBCMPhsContext, + uVCID); + + break; + } + case eDeletePHSRule: + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"PHS DSC Action = Delete PHS Rule \n"); + + if(psfCSType->cPhsRule.u8PHSI) + { + PhsDeletePHSRule( + &Adapter->stBCMPhsContext, + uVCID, + psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); + } + else + { + //BCM_DEBUG_PRINT(CONN_MSG,("Error CPHSRule.PHSI is ZERO \n")); + } + break; + } + default : + { + if(ucDsxType == DSC_ACK) + { + //BCM_DEBUG_PRINT(CONN_MSG,("Invalid PHS DSC Action For DSC \n",psfCSType->cPhsRule.u8PHSI)); + break; //FOr DSC ACK Case PHS DSC Action must be in valid set + } + } + //Proceed To Add PHS rule for DSA_ACK case even if PHS DSC action is unspecified + //No Break Here . Intentionally! + + case eAddPHSRule: + case eSetPHSRule: + { + if(psfCSType->cPhsRule.u8PHSI) + { + //Apply This PHS Rule to all classifiers whose Associated PHSI Match + unsigned int uiClassifierIndex = 0; + if(pstAddIndication->u8Direction == UPLINK_DIR ) + { + for(uiClassifierIndex=0;uiClassifierIndexastClassifierTable[uiClassifierIndex].bUsed) && + (Adapter->astClassifierTable[uiClassifierIndex].ulSFID == Adapter->PackInfo[uiSearchRuleIndex].ulSFID) && + (Adapter->astClassifierTable[uiClassifierIndex].u8AssociatedPHSI == psfCSType->cPhsRule.u8PHSI)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Adding PHS Rule For Classifier : 0x%x cPhsRule.u8PHSI : 0x%x\n", + Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex, + psfCSType->cPhsRule.u8PHSI); + //Update The PHS Rule for this classifier as Associated PHSI id defined + + //Copy the PHS Rule + sPhsRule.u8PHSI = psfCSType->cPhsRule.u8PHSI; + sPhsRule.u8PHSFLength = psfCSType->cPhsRule.u8PHSFLength; + sPhsRule.u8PHSMLength = psfCSType->cPhsRule.u8PHSMLength; + sPhsRule.u8PHSS = psfCSType->cPhsRule.u8PHSS; + sPhsRule.u8PHSV = psfCSType->cPhsRule.u8PHSV; + memcpy(sPhsRule.u8PHSF,psfCSType->cPhsRule.u8PHSF,MAX_PHS_LENGTHS); + memcpy(sPhsRule.u8PHSM,psfCSType->cPhsRule.u8PHSM,MAX_PHS_LENGTHS); + sPhsRule.u8RefCnt = 0; + sPhsRule.bUnclassifiedPHSRule = FALSE; + sPhsRule.PHSModifiedBytes = 0; + sPhsRule.PHSModifiedNumPackets = 0; + sPhsRule.PHSErrorNumPackets = 0; + + //bPHSRuleAssociated = TRUE; + //Store The PHS Rule for this classifier + + PhsUpdateClassifierRule( + &Adapter->stBCMPhsContext, + uVCID, + Adapter->astClassifierTable[uiClassifierIndex].uiClassifierRuleIndex, + &sPhsRule, + Adapter->astClassifierTable[uiClassifierIndex].u8AssociatedPHSI); + + //Update PHS Rule For the Classifier + if(sPhsRule.u8PHSI) + { + Adapter->astClassifierTable[uiClassifierIndex].u32PHSRuleID = sPhsRule.u8PHSI; + memcpy(&Adapter->astClassifierTable[uiClassifierIndex].sPhsRule,&sPhsRule,sizeof(S_PHS_RULE)); + } + + } + } + } + else + { + //Error PHS Rule specified in signaling could not be applied to any classifier + + //Copy the PHS Rule + sPhsRule.u8PHSI = psfCSType->cPhsRule.u8PHSI; + sPhsRule.u8PHSFLength = psfCSType->cPhsRule.u8PHSFLength; + sPhsRule.u8PHSMLength = psfCSType->cPhsRule.u8PHSMLength; + sPhsRule.u8PHSS = psfCSType->cPhsRule.u8PHSS; + sPhsRule.u8PHSV = psfCSType->cPhsRule.u8PHSV; + memcpy(sPhsRule.u8PHSF,psfCSType->cPhsRule.u8PHSF,MAX_PHS_LENGTHS); + memcpy(sPhsRule.u8PHSM,psfCSType->cPhsRule.u8PHSM,MAX_PHS_LENGTHS); + sPhsRule.u8RefCnt = 0; + sPhsRule.bUnclassifiedPHSRule = TRUE; + sPhsRule.PHSModifiedBytes = 0; + sPhsRule.PHSModifiedNumPackets = 0; + sPhsRule.PHSErrorNumPackets = 0; + //Store The PHS Rule for this classifier + + /* + Passing the argument u8PHSI instead of clsid. Because for DL with no classifier rule, + clsid will be zero hence we cant have multiple PHS rules for the same SF. + To support multiple PHS rule, passing u8PHSI. + */ + + PhsUpdateClassifierRule( + &Adapter->stBCMPhsContext, + uVCID, + sPhsRule.u8PHSI, + &sPhsRule, + sPhsRule.u8PHSI); + + } + + } + } + break; + } + } + + if(psfLocalSet->u32MaxSustainedTrafficRate == 0 ) + { + //No Rate Limit . Set Max Sustained Traffic Rate to Maximum + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = + WIMAX_MAX_ALLOWED_RATE; + + } + else if (ntohl(psfLocalSet->u32MaxSustainedTrafficRate) > + WIMAX_MAX_ALLOWED_RATE) + { + //Too large Allowed Rate specified. Limiting to Wi Max Allowed rate + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = + WIMAX_MAX_ALLOWED_RATE; + } + else + { + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate = + ntohl(psfLocalSet->u32MaxSustainedTrafficRate); + } + + Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency = ntohl(psfLocalSet->u32MaximumLatency); + + if(Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency == 0) /* 0 should be treated as infinite */ + Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency = MAX_LATENCY_ALLOWED; + + + if(( Adapter->PackInfo[uiSearchRuleIndex].u8QueueType == ERTPS || + Adapter->PackInfo[uiSearchRuleIndex].u8QueueType == UGS ) ) + UGIValue = ntohs(psfLocalSet->u16UnsolicitedGrantInterval); + + if(UGIValue == 0) + UGIValue = DEFAULT_UG_INTERVAL; + + /* + For UGI based connections... + DEFAULT_UGI_FACTOR*UGIInterval worth of data is the max token count at host... + The extra amount of token is to ensure that a large amount of jitter won't have loss in throughput... + In case of non-UGI based connection, 200 frames worth of data is the max token count at host... + */ + + Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize = + (DEFAULT_UGI_FACTOR*Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate*UGIValue)/1000; + + if(Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize < WIMAX_MAX_MTU*8) + { + UINT UGIFactor = 0; + /* Special Handling to ensure the biggest size of packet can go out from host to FW as follows: + 1. Any packet from Host to FW can go out in different packet size. + 2. So in case the Bucket count is smaller than MTU, the packets of size (Size > TokenCount), will get dropped. + 3. We can allow packets of MaxSize from Host->FW that can go out from FW in multiple SDUs by fragmentation at Wimax Layer + */ + UGIFactor = (Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency/UGIValue + 1); + + if(UGIFactor > DEFAULT_UGI_FACTOR) + Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize = + (UGIFactor*Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate*UGIValue)/1000; + + if(Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize > WIMAX_MAX_MTU*8) + Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize = WIMAX_MAX_MTU*8; + } + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"LAT: %d, UGI: %d \n", Adapter->PackInfo[uiSearchRuleIndex].uiMaxLatency, UGIValue); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"uiMaxAllowedRate: 0x%x, u32MaxSustainedTrafficRate: 0x%x ,uiMaxBucketSize: 0x%x", + Adapter->PackInfo[uiSearchRuleIndex].uiMaxAllowedRate, + ntohl(psfLocalSet->u32MaxSustainedTrafficRate), + Adapter->PackInfo[uiSearchRuleIndex].uiMaxBucketSize); + + //copy the extended SF Parameters to Support MIBS + CopyMIBSExtendedSFParameters(Adapter,psfLocalSet,uiSearchRuleIndex); + + //store header suppression enabled flag per SF + Adapter->PackInfo[uiSearchRuleIndex].bHeaderSuppressionEnabled = + !(psfLocalSet->u8RequesttransmissionPolicy & + MASK_DISABLE_HEADER_SUPPRESSION); + + if(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication) + { + bcm_kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication); + Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = NULL; + } + Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = pstAddIndication; + + //Re Sort the SF list in PackInfo according to Traffic Priority + SortPackInfo(Adapter); + + /* Re Sort the Classifier Rules table and re - arrange + according to Classifier Rule Priority */ + SortClassifiers(Adapter); + + DumpPhsRules(&Adapter->stBCMPhsContext); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"%s <=====", __FUNCTION__); +} + + +/*********************************************************************** +* Function - DumpCmControlPacket +* +* Description - This routinue Dumps the Contents of the AddIndication +* Structure in the Connection Management Control Packet +* +* Parameter - pvBuffer: Pointer to the buffer containing the +* AddIndication data. +* +* Returns - None +*************************************************************************/ +VOID DumpCmControlPacket(PVOID pvBuffer) +{ + UINT uiLoopIndex; + UINT nIndex; + stLocalSFAddIndicationAlt *pstAddIndication; + UINT nCurClassifierCnt; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + pstAddIndication = (stLocalSFAddIndicationAlt *)pvBuffer; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "======>"); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Type : 0x%X",pstAddIndication->u8Type); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Direction : 0x%X",pstAddIndication->u8Direction); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TID: 0x%X", ntohs(pstAddIndication->u16TID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",ntohs(pstAddIndication->u16CID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VCID : 0x%X",ntohs(pstAddIndication->u16VCID)); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " AuthorizedSet--->"); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID : 0x%X",htonl(pstAddIndication->sfAuthorizedSet.u32SFID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",htons(pstAddIndication->sfAuthorizedSet.u16CID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength : 0x%X", + pstAddIndication->sfAuthorizedSet.u8ServiceClassNameLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName : 0x%X ,0x%X , 0x%X, 0x%X, 0x%X, 0x%X", + pstAddIndication->sfAuthorizedSet.u8ServiceClassName[0], + pstAddIndication->sfAuthorizedSet.u8ServiceClassName[1], + pstAddIndication->sfAuthorizedSet.u8ServiceClassName[2], + pstAddIndication->sfAuthorizedSet.u8ServiceClassName[3], + pstAddIndication->sfAuthorizedSet.u8ServiceClassName[4], + pstAddIndication->sfAuthorizedSet.u8ServiceClassName[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService : 0x%X", + pstAddIndication->sfAuthorizedSet.u8MBSService); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet : 0x%X", + pstAddIndication->sfAuthorizedSet.u8QosParamSet); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%X, %p", + pstAddIndication->sfAuthorizedSet.u8TrafficPriority, &pstAddIndication->sfAuthorizedSet.u8TrafficPriority); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxSustainedTrafficRate : 0x%X 0x%p", + pstAddIndication->sfAuthorizedSet.u32MaxSustainedTrafficRate, + &pstAddIndication->sfAuthorizedSet.u32MaxSustainedTrafficRate); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", + pstAddIndication->sfAuthorizedSet.u32MaxTrafficBurst); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", + pstAddIndication->sfAuthorizedSet.u32MinReservedTrafficRate); +#if 0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinimumTolerableTrafficRate : 0x%X", + pstAddIndication->sfAuthorizedSet.u32MinimumTolerableTrafficRate); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32RequesttransmissionPolicy : 0x%X", + pstAddIndication->sfAuthorizedSet.u32RequesttransmissionPolicy); +#endif + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%X", + pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParamLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%X", + pstAddIndication->sfAuthorizedSet.u8VendorSpecificQoSParam[0]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType : 0x%X", + pstAddIndication->sfAuthorizedSet.u8ServiceFlowSchedulingType); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter : 0x%X", + pstAddIndication->sfAuthorizedSet.u32ToleratedJitter); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency : 0x%X", + pstAddIndication->sfAuthorizedSet.u32MaximumLatency); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%X", + pstAddIndication->sfAuthorizedSet.u8FixedLengthVSVariableLengthSDUIndicator); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize : 0x%X", + pstAddIndication->sfAuthorizedSet.u8SDUSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID : 0x%X", + pstAddIndication->sfAuthorizedSet.u16TargetSAID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable : 0x%X", + pstAddIndication->sfAuthorizedSet.u8ARQEnable); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize : 0x%X", + pstAddIndication->sfAuthorizedSet.u16ARQWindowSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut : 0x%X", + pstAddIndication->sfAuthorizedSet.u16ARQRetryTxTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut : 0x%X", + pstAddIndication->sfAuthorizedSet.u16ARQRetryRxTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime : 0x%X", + pstAddIndication->sfAuthorizedSet.u16ARQBlockLifeTime); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut : 0x%X", + pstAddIndication->sfAuthorizedSet.u16ARQSyncLossTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder : 0x%X", + pstAddIndication->sfAuthorizedSet.u8ARQDeliverInOrder); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut : 0x%X", + pstAddIndication->sfAuthorizedSet.u16ARQRxPurgeTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize : 0x%X", + pstAddIndication->sfAuthorizedSet.u16ARQBlockSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification : 0x%X", + pstAddIndication->sfAuthorizedSet.u8CSSpecification); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService : 0x%X", + pstAddIndication->sfAuthorizedSet.u8TypeOfDataDeliveryService); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime : 0x%X", + pstAddIndication->sfAuthorizedSet.u16SDUInterArrivalTime); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase : 0x%X", + pstAddIndication->sfAuthorizedSet.u16TimeBase); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference : 0x%X", + pstAddIndication->sfAuthorizedSet.u8PagingPreference); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UnsolicitedPollingInterval : 0x%X", + pstAddIndication->sfAuthorizedSet.u16UnsolicitedPollingInterval); +#if 0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignmentLength : 0x%X", + pstAddIndication->sfAuthorizedSet.MBSZoneIdentifierassignmentLength); + for(uiLoopIndex=0; uiLoopIndex < MAX_STRING_LEN; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignment : 0x%X", + pstAddIndication->sfAuthorizedSet.MBSZoneIdentifierassignment[uiLoopIndex]); +#endif + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "sfAuthorizedSet.u8HARQChannelMapping %x %x %x ", + *(unsigned int*)pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping, + *(unsigned int*)&pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[4], + *(USHORT*) &pstAddIndication->sfAuthorizedSet.u8HARQChannelMapping[8]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference : 0x%X", + pstAddIndication->sfAuthorizedSet.u8TrafficIndicationPreference); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Recieved : 0x%X",pstAddIndication->sfAuthorizedSet.u8TotalClassifiers); + + nCurClassifierCnt = pstAddIndication->sfAuthorizedSet.u8TotalClassifiers; + + if(nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) + { + nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; + } + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.bValid %d", pstAddIndication->sfAuthorizedSet.bValid); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "pstAddIndication->sfAuthorizedSet.u16MacOverhead %x", pstAddIndication->sfAuthorizedSet.u16MacOverhead); + if(!pstAddIndication->sfAuthorizedSet.bValid) + pstAddIndication->sfAuthorizedSet.bValid=1; + for(nIndex = 0 ; nIndex < nCurClassifierCnt ; nIndex++) + { + stConvergenceSLTypes *psfCSType = NULL; + psfCSType = &pstAddIndication->sfAuthorizedSet.cConvergenceSLTypes[nIndex]; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "psfCSType = %p", psfCSType); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "CCPacketClassificationRuleSI====>"); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority :0x%X ", + psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3] :0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); +#if 0 + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u8ProtocolLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolLength); +#endif + + for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8Protocol); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); + + for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32] : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength : 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); + + for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32] : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4]: 0x%02X ,0x%02X ,0x%02X ,0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6] : 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6] : 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthertypeLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3] : 0x%02X ,0x%02X ,0x%02X ", + psfCSType->cCPacketClassificationRule.u8Ethertype[0], + psfCSType->cCPacketClassificationRule.u8Ethertype[1], + psfCSType->cCPacketClassificationRule.u8Ethertype[2]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority : 0x%X ", + psfCSType->cCPacketClassificationRule.u16UserPriority); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID : 0x%X ", + psfCSType->cCPacketClassificationRule.u16VLANID); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex : 0x%X ", + psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength : 0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1] : 0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); +#ifdef VERSION_D5 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6] : 0x %02X %02X %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); +#endif + } + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid : 0x%02X",pstAddIndication->sfAuthorizedSet.bValid); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "AdmittedSet--->"); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID : 0x%X",pstAddIndication->sfAdmittedSet.u32SFID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",pstAddIndication->sfAdmittedSet.u16CID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength : 0x%X", + pstAddIndication->sfAdmittedSet.u8ServiceClassNameLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName : 0x %02X %02X %02X %02X %02X %02X", + pstAddIndication->sfAdmittedSet.u8ServiceClassName[0], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[1], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[2], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[3], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[4], + pstAddIndication->sfAdmittedSet.u8ServiceClassName[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService : 0x%02X", + pstAddIndication->sfAdmittedSet.u8MBSService); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet : 0x%02X", + pstAddIndication->sfAdmittedSet.u8QosParamSet); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%02X", + pstAddIndication->sfAdmittedSet.u8TrafficPriority); +#if 0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MaxSustainedTrafficRate : 0x%02X", + ntohl(pstAddIndication->sfAdmittedSet.u32MaxSustainedTrafficRate)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MinimumTolerableTrafficRate : 0x%X", + pstAddIndication->sfAdmittedSet.u32MinimumTolerableTrafficRate); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32RequesttransmissionPolicy : 0x%X", + pstAddIndication->sfAdmittedSet.u32RequesttransmissionPolicy); +#endif + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", + pstAddIndication->sfAdmittedSet.u32MaxTrafficBurst); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", + pstAddIndication->sfAdmittedSet.u32MinReservedTrafficRate); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%02X", + pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParamLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%02X", + pstAddIndication->sfAdmittedSet.u8VendorSpecificQoSParam[0]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType : 0x%02X", + pstAddIndication->sfAdmittedSet.u8ServiceFlowSchedulingType); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter : 0x%X", + pstAddIndication->sfAdmittedSet.u32ToleratedJitter); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency : 0x%X", + pstAddIndication->sfAdmittedSet.u32MaximumLatency); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X", + pstAddIndication->sfAdmittedSet.u8FixedLengthVSVariableLengthSDUIndicator); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize : 0x%02X", + pstAddIndication->sfAdmittedSet.u8SDUSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TargetSAID : 0x%02X", + pstAddIndication->sfAdmittedSet.u16TargetSAID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQEnable : 0x%02X", + pstAddIndication->sfAdmittedSet.u8ARQEnable); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQWindowSize : 0x%X", + pstAddIndication->sfAdmittedSet.u16ARQWindowSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryTxTimeOut : 0x%X", + pstAddIndication->sfAdmittedSet.u16ARQRetryTxTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRetryRxTimeOut : 0x%X", + pstAddIndication->sfAdmittedSet.u16ARQRetryRxTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockLifeTime : 0x%X", + pstAddIndication->sfAdmittedSet.u16ARQBlockLifeTime); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQSyncLossTimeOut : 0x%X", + pstAddIndication->sfAdmittedSet.u16ARQSyncLossTimeOut); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ARQDeliverInOrder : 0x%02X", + pstAddIndication->sfAdmittedSet.u8ARQDeliverInOrder); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQRxPurgeTimeOut : 0x%X", + pstAddIndication->sfAdmittedSet.u16ARQRxPurgeTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16ARQBlockSize : 0x%X", + pstAddIndication->sfAdmittedSet.u16ARQBlockSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8CSSpecification : 0x%02X", + pstAddIndication->sfAdmittedSet.u8CSSpecification); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TypeOfDataDeliveryService : 0x%02X", + pstAddIndication->sfAdmittedSet.u8TypeOfDataDeliveryService); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16SDUInterArrivalTime : 0x%X", + pstAddIndication->sfAdmittedSet.u16SDUInterArrivalTime); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16TimeBase : 0x%X", + pstAddIndication->sfAdmittedSet.u16TimeBase); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8PagingPreference : 0x%X", + pstAddIndication->sfAdmittedSet.u8PagingPreference); +#if 0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignmentLength : 0x%X", + pstAddIndication->sfAdmittedSet.MBSZoneIdentifierassignmentLength); + for(uiLoopIndex=0; uiLoopIndex < MAX_STRING_LEN; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "MBSZoneIdentifierassignment : 0x%X", + pstAddIndication->sfAdmittedSet.MBSZoneIdentifierassignment[uiLoopIndex]); +#endif + + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficIndicationPreference : 0x%02X", + pstAddIndication->sfAdmittedSet.u8TrafficIndicationPreference); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Recieved : 0x%X",pstAddIndication->sfAdmittedSet.u8TotalClassifiers); + + nCurClassifierCnt = pstAddIndication->sfAdmittedSet.u8TotalClassifiers; + + if(nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) + { + nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; + } + + + for(nIndex = 0 ; nIndex < nCurClassifierCnt ; nIndex++) + { + + stConvergenceSLTypes *psfCSType = NULL; + psfCSType = &pstAddIndication->sfAdmittedSet.cConvergenceSLTypes[nIndex]; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ClassifierRulePriority :0x%02X ", + psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfServiceLength :0x%02X", + psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPTypeOfService[3] :0x%02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); +#if 0 + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolLength :0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolLength); +#endif + for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Protocol: 0x%02X ", + psfCSType->cCPacketClassificationRule.u8Protocol); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength :0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); + + for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32] : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); + + for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddress[32] : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRangeLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolSourcePortRange[4] : 0x %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRangeLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ProtocolDestPortRange[4] : 0x %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddressLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetDestMacAddress[6] : 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddressLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6] : 0x %02X %02X %02X %02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthertypeLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8EthertypeLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8Ethertype[3] : 0x%02X %02X %02X", + psfCSType->cCPacketClassificationRule.u8Ethertype[0], + psfCSType->cCPacketClassificationRule.u8Ethertype[1], + psfCSType->cCPacketClassificationRule.u8Ethertype[2]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16UserPriority : 0x%X ", + psfCSType->cCPacketClassificationRule.u16UserPriority); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16VLANID : 0x%X ", + psfCSType->cCPacketClassificationRule.u16VLANID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8AssociatedPHSI : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16PacketClassificationRuleIndex : 0x%X ", + psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParamLength : 0x%02X", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificClassifierParam[1] : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); +#ifdef VERSION_D5 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLableLength : 0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPv6FlowLable[6] : 0x %02X %02X %02X %02X %02X %02X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); +#endif + } + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "bValid : 0x%X",pstAddIndication->sfAdmittedSet.bValid); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " ActiveSet--->"); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32SFID : 0x%X",pstAddIndication->sfActiveSet.u32SFID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u16CID : 0x%X",pstAddIndication->sfActiveSet.u16CID); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassNameLength : 0x%X", + pstAddIndication->sfActiveSet.u8ServiceClassNameLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceClassName : 0x %02X %02X %02X %02X %02X %02X", + pstAddIndication->sfActiveSet.u8ServiceClassName[0], + pstAddIndication->sfActiveSet.u8ServiceClassName[1], + pstAddIndication->sfActiveSet.u8ServiceClassName[2], + pstAddIndication->sfActiveSet.u8ServiceClassName[3], + pstAddIndication->sfActiveSet.u8ServiceClassName[4], + pstAddIndication->sfActiveSet.u8ServiceClassName[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8MBSService : 0x%02X", + pstAddIndication->sfActiveSet.u8MBSService); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8QosParamSet : 0x%02X", + pstAddIndication->sfActiveSet.u8QosParamSet); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8TrafficPriority : 0x%02X", + pstAddIndication->sfActiveSet.u8TrafficPriority); +#if 0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MaxSustainedTrafficRate : 0x%02X", + ntohl(pstAddIndication->sfActiveSet.u32MaxSustainedTrafficRate)); +#endif + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaxTrafficBurst : 0x%X", + pstAddIndication->sfActiveSet.u32MaxTrafficBurst); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MinReservedTrafficRate : 0x%X", + pstAddIndication->sfActiveSet.u32MinReservedTrafficRate); +#if 0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32MinimumTolerableTrafficRate : 0x%X", + pstAddIndication->sfActiveSet.u32MinimumTolerableTrafficRate); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32RequesttransmissionPolicy : 0x%X", + pstAddIndication->sfActiveSet.u32RequesttransmissionPolicy); +#endif + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParamLength : 0x%02X", + pstAddIndication->sfActiveSet.u8VendorSpecificQoSParamLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8VendorSpecificQoSParam : 0x%02X", + pstAddIndication->sfActiveSet.u8VendorSpecificQoSParam[0]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8ServiceFlowSchedulingType : 0x%02X", + pstAddIndication->sfActiveSet.u8ServiceFlowSchedulingType); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32ToleratedJitter : 0x%X", + pstAddIndication->sfActiveSet.u32ToleratedJitter); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u32MaximumLatency : 0x%X", + pstAddIndication->sfActiveSet.u32MaximumLatency); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8FixedLengthVSVariableLengthSDUIndicator: 0x%02X", + pstAddIndication->sfActiveSet.u8FixedLengthVSVariableLengthSDUIndicator); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8SDUSize : 0x%X", + pstAddIndication->sfActiveSet.u8SDUSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TargetSAID : 0x%X", + pstAddIndication->sfActiveSet.u16TargetSAID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQEnable : 0x%X", + pstAddIndication->sfActiveSet.u8ARQEnable); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQWindowSize : 0x%X", + pstAddIndication->sfActiveSet.u16ARQWindowSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryTxTimeOut : 0x%X", + pstAddIndication->sfActiveSet.u16ARQRetryTxTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRetryRxTimeOut : 0x%X", + pstAddIndication->sfActiveSet.u16ARQRetryRxTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockLifeTime : 0x%X", + pstAddIndication->sfActiveSet.u16ARQBlockLifeTime); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQSyncLossTimeOut : 0x%X", + pstAddIndication->sfActiveSet.u16ARQSyncLossTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ARQDeliverInOrder : 0x%X", + pstAddIndication->sfActiveSet.u8ARQDeliverInOrder); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQRxPurgeTimeOut : 0x%X", + pstAddIndication->sfActiveSet.u16ARQRxPurgeTimeOut); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16ARQBlockSize : 0x%X", + pstAddIndication->sfActiveSet.u16ARQBlockSize); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8CSSpecification : 0x%X", + pstAddIndication->sfActiveSet.u8CSSpecification); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TypeOfDataDeliveryService : 0x%X", + pstAddIndication->sfActiveSet.u8TypeOfDataDeliveryService); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16SDUInterArrivalTime : 0x%X", + pstAddIndication->sfActiveSet.u16SDUInterArrivalTime); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16TimeBase : 0x%X", + pstAddIndication->sfActiveSet.u16TimeBase); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8PagingPreference : 0x%X", + pstAddIndication->sfActiveSet.u8PagingPreference); +#if 0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " MBSZoneIdentifierassignmentLength : 0x%X", + pstAddIndication->sfActiveSet.MBSZoneIdentifierassignmentLength); + for(uiLoopIndex=0; uiLoopIndex < MAX_STRING_LEN; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " MBSZoneIdentifierassignment : 0x%X", + pstAddIndication->sfActiveSet.MBSZoneIdentifierassignment[uiLoopIndex]); +#endif + + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8TrafficIndicationPreference : 0x%X", + pstAddIndication->sfActiveSet.u8TrafficIndicationPreference); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " Total Classifiers Recieved : 0x%X",pstAddIndication->sfActiveSet.u8TotalClassifiers); + + nCurClassifierCnt = pstAddIndication->sfActiveSet.u8TotalClassifiers; + + if(nCurClassifierCnt > MAX_CLASSIFIERS_IN_SF) + { + nCurClassifierCnt = MAX_CLASSIFIERS_IN_SF; + } + + for(nIndex = 0 ; nIndex < nCurClassifierCnt ; nIndex++) + { + + stConvergenceSLTypes *psfCSType = NULL; + psfCSType = &pstAddIndication->sfActiveSet.cConvergenceSLTypes[nIndex]; + + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " CCPacketClassificationRuleSI====>"); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ClassifierRulePriority :0x%X ", + psfCSType->cCPacketClassificationRule.u8ClassifierRulePriority); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPTypeOfServiceLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfServiceLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPTypeOfService[3] :0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[0], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[1], + psfCSType->cCPacketClassificationRule.u8IPTypeOfService[2]); +#if 0 + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " u8ProtocolLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolLength); +#endif + for(uiLoopIndex=0; uiLoopIndex < 1; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8Protocol : 0x%X ", + psfCSType->cCPacketClassificationRule.u8Protocol); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddressLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddressLength); + + for(uiLoopIndex=0; uiLoopIndex < 32; uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPMaskedSourceAddress[32]:0x%X ", + psfCSType->cCPacketClassificationRule.u8IPMaskedSourceAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8IPDestinationAddressLength : 0x%02X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddressLength); + + for(uiLoopIndex=0;uiLoopIndex<32;uiLoopIndex++) + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPDestinationAddress[32]:0x%X ", + psfCSType->cCPacketClassificationRule.u8IPDestinationAddress[uiLoopIndex]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolSourcePortRangeLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRangeLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolSourcePortRange[4]:0x%X ,0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolSourcePortRange[3]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolDestPortRangeLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRangeLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8ProtocolDestPortRange[4]:0x%X ,0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[0], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[1], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[2], + psfCSType->cCPacketClassificationRule.u8ProtocolDestPortRange[3]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetDestMacAddressLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetDestMacAddress[6]:0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddress[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthernetSourceMACAddressLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8EthernetDestMacAddressLength); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, "u8EthernetSourceMACAddress[6]:0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X", + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[0], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[1], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[2], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[3], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[4], + psfCSType->cCPacketClassificationRule.u8EthernetSourceMACAddress[5]); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8EthertypeLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8EthertypeLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8Ethertype[3] :0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8Ethertype[0], + psfCSType->cCPacketClassificationRule.u8Ethertype[1], + psfCSType->cCPacketClassificationRule.u8Ethertype[2]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16UserPriority :0x%X ", + psfCSType->cCPacketClassificationRule.u16UserPriority); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16VLANID :0x%X ", + psfCSType->cCPacketClassificationRule.u16VLANID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8AssociatedPHSI :0x%X ", + psfCSType->cCPacketClassificationRule.u8AssociatedPHSI); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u16PacketClassificationRuleIndex:0x%X ", + psfCSType->cCPacketClassificationRule.u16PacketClassificationRuleIndex); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8VendorSpecificClassifierParamLength:0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParamLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8VendorSpecificClassifierParam[1]:0x%X ", + psfCSType->cCPacketClassificationRule.u8VendorSpecificClassifierParam[0]); +#ifdef VERSION_D5 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPv6FlowLableLength :0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLableLength); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " u8IPv6FlowLable[6] :0x%X ,0x%X ,0x%X ,0x%X ,0x%X ,0x%X ", + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[0], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[1], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[2], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[3], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[4], + psfCSType->cCPacketClassificationRule.u8IPv6FlowLable[5]); +#endif + } + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL, " bValid : 0x%X",pstAddIndication->sfActiveSet.bValid); + +} + +static inline ULONG RestoreSFParam(PMINI_ADAPTER Adapter, ULONG ulAddrSFParamSet,PUCHAR pucDestBuffer) +{ + UINT nBytesToRead = sizeof(stServiceFlowParamSI); + + if(ulAddrSFParamSet == 0 || NULL == pucDestBuffer) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Got Param address as 0!!"); + return 0; + } + ulAddrSFParamSet = ntohl(ulAddrSFParamSet); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " RestoreSFParam: Total Words of DSX Message To Read: 0x%x From Target At : 0x%lx ", + nBytesToRead/sizeof(ULONG),ulAddrSFParamSet); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "sizeof(stServiceFlowParamSI) = %x", sizeof(stServiceFlowParamSI)); + + //Read out the SF Param Set At the indicated Location + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "nBytesToRead = %x", nBytesToRead); + if(rdm(Adapter, ulAddrSFParamSet, (PUCHAR)pucDestBuffer, nBytesToRead) < 0) + return STATUS_FAILURE; + + return 1; +} + + +static __inline ULONG StoreSFParam(PMINI_ADAPTER Adapter,PUCHAR pucSrcBuffer,ULONG ulAddrSFParamSet) +{ + UINT nBytesToWrite = sizeof(stServiceFlowParamSI); + UINT uiRetVal =0; + + if(ulAddrSFParamSet == 0 || NULL == pucSrcBuffer) + { + return 0; + } + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " StoreSFParam: Total Words of DSX Message To Write: 0x%X To Target At : 0x%lX ",(nBytesToWrite/sizeof(ULONG)),ulAddrSFParamSet); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "WRM with %x bytes",nBytesToWrite); + + uiRetVal = wrm(Adapter,ulAddrSFParamSet,(PUCHAR)pucSrcBuffer, nBytesToWrite); + if(uiRetVal < 0) { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "%s:%d WRM failed",__FUNCTION__, __LINE__); + return uiRetVal; + } + return 1; +} + +ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *puBufferLength) +{ + stLocalSFAddIndicationAlt *pstAddIndicationAlt = NULL; + stLocalSFAddIndication * pstAddIndication = NULL; + stLocalSFDeleteRequest *pstDeletionRequest; + UINT uiSearchRuleIndex; + ULONG ulSFID; + + pstAddIndicationAlt = (stLocalSFAddIndicationAlt *)(pvBuffer); + + /* + * In case of DSD Req By MS, we should immediately delete this SF so that + * we can stop the further classifying the pkt for this SF. + */ + if(pstAddIndicationAlt->u8Type == DSD_REQ) + { + pstDeletionRequest = (stLocalSFDeleteRequest *)pvBuffer; + + ulSFID = ntohl(pstDeletionRequest->u32SFID); + uiSearchRuleIndex=SearchSfid(Adapter,ulSFID); + + if(uiSearchRuleIndex < NO_OF_QUEUES) + { + deleteSFBySfid(Adapter,uiSearchRuleIndex); + Adapter->u32TotalDSD++; + } + return 1; + } + + + if( (pstAddIndicationAlt->u8Type == DSD_RSP) || + (pstAddIndicationAlt->u8Type == DSD_ACK)) + { + //No Special handling send the message as it is + return 1; + } + // For DSA_REQ, only upto "psfAuthorizedSet" parameter should be accessed by driver! + + pstAddIndication=(stLocalSFAddIndication *)kmalloc(sizeof(*pstAddIndication), GFP_KERNEL); + if(NULL==pstAddIndication) + return 0; + + /* AUTHORIZED SET */ + pstAddIndication->psfAuthorizedSet = (stServiceFlowParamSI *) + GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); + if(!pstAddIndication->psfAuthorizedSet) + return 0; + + if(StoreSFParam(Adapter,(PUCHAR)&pstAddIndicationAlt->sfAuthorizedSet, + (ULONG)pstAddIndication->psfAuthorizedSet)!= 1) + return 0; + + pstAddIndication->psfAuthorizedSet = (stServiceFlowParamSI *) + ntohl((ULONG)pstAddIndication->psfAuthorizedSet); + + if(pstAddIndicationAlt->u8Type == DSA_REQ) + { + stLocalSFAddRequest AddRequest; + + AddRequest.u8Type = pstAddIndicationAlt->u8Type; + AddRequest.eConnectionDir = pstAddIndicationAlt->u8Direction; + AddRequest.u16TID = pstAddIndicationAlt->u16TID; + AddRequest.u16CID = pstAddIndicationAlt->u16CID; + AddRequest.u16VCID = pstAddIndicationAlt->u16VCID; + AddRequest.psfParameterSet =pstAddIndication->psfAuthorizedSet ; + (*puBufferLength) = sizeof(stLocalSFAddRequest); + memcpy(pvBuffer,&AddRequest,sizeof(stLocalSFAddRequest)); + return 1; + } + + // Since it's not DSA_REQ, we can access all field in pstAddIndicationAlt + + //We need to extract the structure from the buffer and pack it differently + + pstAddIndication->u8Type = pstAddIndicationAlt->u8Type; + pstAddIndication->eConnectionDir= pstAddIndicationAlt->u8Direction ; + pstAddIndication->u16TID = pstAddIndicationAlt->u16TID; + pstAddIndication->u16CID = pstAddIndicationAlt->u16CID; + pstAddIndication->u16VCID = pstAddIndicationAlt->u16VCID; + pstAddIndication->u8CC = pstAddIndicationAlt->u8CC; + + /* ADMITTED SET */ + pstAddIndication->psfAdmittedSet = (stServiceFlowParamSI *) + GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); + if(!pstAddIndication->psfAdmittedSet) + return 0; + if(StoreSFParam(Adapter,(PUCHAR)&pstAddIndicationAlt->sfAdmittedSet,(ULONG)pstAddIndication->psfAdmittedSet) != 1) + return 0; + + pstAddIndication->psfAdmittedSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfAdmittedSet); + + + /* ACTIVE SET */ + pstAddIndication->psfActiveSet = (stServiceFlowParamSI *) + GetNextTargetBufferLocation(Adapter, pstAddIndicationAlt->u16TID); + if(!pstAddIndication->psfActiveSet) + return 0; + if(StoreSFParam(Adapter,(PUCHAR)&pstAddIndicationAlt->sfActiveSet,(ULONG)pstAddIndication->psfActiveSet) != 1) + return 0; + + pstAddIndication->psfActiveSet = (stServiceFlowParamSI *)ntohl((ULONG)pstAddIndication->psfActiveSet); + + (*puBufferLength) = sizeof(stLocalSFAddIndication); + *(stLocalSFAddIndication *)pvBuffer = *pstAddIndication; + bcm_kfree(pstAddIndication); + return 1; +} + + +static inline stLocalSFAddIndicationAlt +*RestoreCmControlResponseMessage(register PMINI_ADAPTER Adapter,register PVOID pvBuffer) +{ + ULONG ulStatus=0; + stLocalSFAddIndication *pstAddIndication = NULL; + stLocalSFAddIndicationAlt *pstAddIndicationDest = NULL; + pstAddIndication = (stLocalSFAddIndication *)(pvBuffer); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "=====>" ); + if ((pstAddIndication->u8Type == DSD_REQ) || + (pstAddIndication->u8Type == DSD_RSP) || + (pstAddIndication->u8Type == DSD_ACK)) + { + return (stLocalSFAddIndicationAlt *)pvBuffer; + } + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage "); + /* + //Need to Allocate memory to contain the SUPER Large structures + //Our driver cant create these structures on Stack :( + */ + pstAddIndicationDest=kmalloc(sizeof(stLocalSFAddIndicationAlt), GFP_KERNEL); + + if(pstAddIndicationDest) + { + memset(pstAddIndicationDest,0,sizeof(stLocalSFAddIndicationAlt)); + } + else + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Failed to allocate memory for SF Add Indication Structure "); + return NULL; + } + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8Type : 0x%X",pstAddIndication->u8Type); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8Direction : 0x%X",pstAddIndication->eConnectionDir); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8TID : 0x%X",ntohs(pstAddIndication->u16TID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u8CID : 0x%X",ntohs(pstAddIndication->u16CID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-u16VCID : 0x%X",ntohs(pstAddIndication->u16VCID)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-autorized set loc : 0x%x",ntohl(pstAddIndication->psfAuthorizedSet)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-admitted set loc : 0x%x",ntohl(pstAddIndication->psfAdmittedSet)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "AddIndication-Active set loc : 0x%x",ntohl(pstAddIndication->psfActiveSet)); + + pstAddIndicationDest->u8Type = pstAddIndication->u8Type; + pstAddIndicationDest->u8Direction = pstAddIndication->eConnectionDir; + pstAddIndicationDest->u16TID = pstAddIndication->u16TID; + pstAddIndicationDest->u16CID = pstAddIndication->u16CID; + pstAddIndicationDest->u16VCID = pstAddIndication->u16VCID; + pstAddIndicationDest->u8CC = pstAddIndication->u8CC; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Active Set "); + ulStatus=RestoreSFParam(Adapter,(ULONG)pstAddIndication->psfActiveSet, (PUCHAR)&pstAddIndicationDest->sfActiveSet); + if(ulStatus != 1) + { + goto failed_restore_sf_param; + } + if(pstAddIndicationDest->sfActiveSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) + pstAddIndicationDest->sfActiveSet.u8TotalClassifiers = MAX_CLASSIFIERS_IN_SF; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Admitted Set "); + ulStatus=RestoreSFParam(Adapter,(ULONG)pstAddIndication->psfAdmittedSet,(PUCHAR)&pstAddIndicationDest->sfAdmittedSet); + if(ulStatus != 1) + { + goto failed_restore_sf_param; + } + if(pstAddIndicationDest->sfAdmittedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) + pstAddIndicationDest->sfAdmittedSet.u8TotalClassifiers = MAX_CLASSIFIERS_IN_SF; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Restoring Authorized Set "); + ulStatus=RestoreSFParam(Adapter,(ULONG)pstAddIndication->psfAuthorizedSet,(PUCHAR)&pstAddIndicationDest->sfAuthorizedSet); + if(ulStatus != 1) + { + goto failed_restore_sf_param; + } + if(pstAddIndicationDest->sfAuthorizedSet.u8TotalClassifiers > MAX_CLASSIFIERS_IN_SF) + pstAddIndicationDest->sfAuthorizedSet.u8TotalClassifiers = MAX_CLASSIFIERS_IN_SF; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Dumping the whole raw packet"); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============================================================"); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " pstAddIndicationDest->sfActiveSet size %x %p", sizeof(*pstAddIndicationDest), pstAddIndicationDest); + //BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, (unsigned char *)pstAddIndicationDest, sizeof(*pstAddIndicationDest)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============================================================"); + return pstAddIndicationDest; +failed_restore_sf_param: + bcm_kfree(pstAddIndicationDest); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<=====" ); + return NULL; +} + +ULONG SetUpTargetDsxBuffers(PMINI_ADAPTER Adapter) +{ + ULONG ulTargetDsxBuffersBase = 0; + ULONG ulCntTargetBuffers; + ULONG ulIndex=0; + int Status; + + if(Adapter->astTargetDsxBuffer[0].ulTargetDsxBuffer) + return 1; + + if(NULL == Adapter) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Adapter was NULL!!!"); + return 0; + } + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Size of Each DSX Buffer(Also size of ServiceFlowParamSI): %x ",sizeof(stServiceFlowParamSI)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Reading DSX buffer From Target location %x ",DSX_MESSAGE_EXCHANGE_BUFFER); + + Status = rdmalt(Adapter, DSX_MESSAGE_EXCHANGE_BUFFER, + (PUINT)&ulTargetDsxBuffersBase, sizeof(UINT)); + if(Status < 0) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "RDM failed!!"); + return 0; + } + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Base Address Of DSX Target Buffer : 0x%lx",ulTargetDsxBuffersBase); + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Tgt Buffer is Now %lx :",ulTargetDsxBuffersBase); + + ulCntTargetBuffers = DSX_MESSAGE_EXCHANGE_BUFFER_SIZE/sizeof(stServiceFlowParamSI); + + Adapter->ulTotalTargetBuffersAvailable = + ulCntTargetBuffers > MAX_TARGET_DSX_BUFFERS ? + MAX_TARGET_DSX_BUFFERS : ulCntTargetBuffers; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Total Target DSX Buffer setup %lx ",Adapter->ulTotalTargetBuffersAvailable); + + for(ulIndex=0; ulIndex < Adapter->ulTotalTargetBuffersAvailable ; ulIndex++) + { + Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer = ulTargetDsxBuffersBase; + Adapter->astTargetDsxBuffer[ulIndex].valid=1; + Adapter->astTargetDsxBuffer[ulIndex].tid=0; + ulTargetDsxBuffersBase+=sizeof(stServiceFlowParamSI); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " Target DSX Buffer %lx setup at 0x%lx", + ulIndex, Adapter->astTargetDsxBuffer[ulIndex].ulTargetDsxBuffer); + } + Adapter->ulCurrentTargetBuffer = 0; + Adapter->ulFreeTargetBufferCnt = Adapter->ulTotalTargetBuffersAvailable; + return 1; +} + +ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter,B_UINT16 tid) +{ + ULONG ulTargetDSXBufferAddress; + ULONG ulTargetDsxBufferIndexToUse,ulMaxTry; + + if((Adapter->ulTotalTargetBuffersAvailable == 0)|| + (Adapter->ulFreeTargetBufferCnt == 0)) + { + ClearTargetDSXBuffer(Adapter,tid,FALSE); + return 0; + } + + ulTargetDsxBufferIndexToUse = Adapter->ulCurrentTargetBuffer; + ulMaxTry = Adapter->ulTotalTargetBuffersAvailable; + while((ulMaxTry)&&(Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid != 1)) + { + ulTargetDsxBufferIndexToUse = (ulTargetDsxBufferIndexToUse+1)% + Adapter->ulTotalTargetBuffersAvailable; + ulMaxTry--; + } + + if(ulMaxTry==0) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "\n GetNextTargetBufferLocation : Error No Free Target DSX Buffers FreeCnt : %lx ",Adapter->ulFreeTargetBufferCnt); + ClearTargetDSXBuffer(Adapter,tid,FALSE); + return 0; + } + + + ulTargetDSXBufferAddress = + Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].ulTargetDsxBuffer; + Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].valid=0; + Adapter->astTargetDsxBuffer[ulTargetDsxBufferIndexToUse].tid=tid; + Adapter->ulFreeTargetBufferCnt--; + + + ulTargetDsxBufferIndexToUse = + (ulTargetDsxBufferIndexToUse+1)%Adapter->ulTotalTargetBuffersAvailable; + Adapter->ulCurrentTargetBuffer = ulTargetDsxBufferIndexToUse; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "GetNextTargetBufferLocation :Returning address %lx tid %d\n", + ulTargetDSXBufferAddress,tid); + return ulTargetDSXBufferAddress; +} + + +INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter) +{ + /* + //Need to Allocate memory to contain the SUPER Large structures + //Our driver cant create these structures on Stack + */ + Adapter->caDsxReqResp=kmalloc(sizeof(stLocalSFAddIndicationAlt)+LEADER_SIZE, GFP_KERNEL); + if(!Adapter->caDsxReqResp) + return -ENOMEM; + return 0; +} + +INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter) +{ + if(Adapter->caDsxReqResp) + { + bcm_kfree(Adapter->caDsxReqResp); + } + return 0; + +} +/** +@ingroup ctrl_pkt_functions +This routinue would process the Control responses +for the Connection Management. +@return - Queue index for the free SFID else returns Invalid Index. +*/ +BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter, /**u16TID, FALSE); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "Error in restoring Service Flow param structure from DSx message"); + return FALSE; + } + + DumpCmControlPacket(pstAddIndication); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "====>"); + pLeader = (PLEADER)Adapter->caDsxReqResp; + + pLeader->Status =CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ; + pLeader->Vcid = 0; + + ClearTargetDSXBuffer(Adapter,pstAddIndication->u16TID,FALSE); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "### TID RECEIVED %d\n",pstAddIndication->u16TID); + switch(pstAddIndication->u8Type) + { + case DSA_REQ: + { + pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Sending DSA Response....\n"); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA RESPONSE TO MAC %d", pLeader->PLength ); + *((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) + = *pstAddIndication; + ((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_RSP; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, " VCID = %x", ntohs(pstAddIndication->u16VCID)); + CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); + bcm_kfree(pstAddIndication); + } + break; + case DSA_RSP: + { + pLeader->PLength = sizeof(stLocalSFAddIndicationAlt); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSA ACK TO MAC %d", + pLeader->PLength); + *((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) + = *pstAddIndication; + ((stLocalSFAddIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSA_ACK; + + }//no break here..we should go down. + case DSA_ACK: + { + UINT uiSearchRuleIndex=0; + struct timeval tv = {0}; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "VCID:0x%X", + ntohs(pstAddIndication->u16VCID)); + uiSearchRuleIndex=SearchFreeSfid(Adapter); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"uiSearchRuleIndex:0x%X ", + uiSearchRuleIndex); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Direction:0x%X ", + pstAddIndication->u8Direction); + if((uiSearchRuleIndex< NO_OF_QUEUES) ) + { + Adapter->PackInfo[uiSearchRuleIndex].ucDirection = + pstAddIndication->u8Direction; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "bValid:0x%X ", + pstAddIndication->sfActiveSet.bValid); + if(pstAddIndication->sfActiveSet.bValid==TRUE) + { + Adapter->PackInfo[uiSearchRuleIndex].bActiveSet=TRUE; + } + if(pstAddIndication->sfAuthorizedSet.bValid==TRUE) + { + Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet=TRUE; + } + if(pstAddIndication->sfAdmittedSet.bValid==TRUE) + { + Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet=TRUE; + } + if(FALSE == pstAddIndication->sfActiveSet.bValid) + { + Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; + if(pstAddIndication->sfAdmittedSet.bValid) + { + psfLocalSet = &pstAddIndication->sfAdmittedSet; + } + else if(pstAddIndication->sfAuthorizedSet.bValid) + { + psfLocalSet = &pstAddIndication->sfAuthorizedSet; + } + } + else + { + psfLocalSet = &pstAddIndication->sfActiveSet; + Adapter->PackInfo[uiSearchRuleIndex].bActive=TRUE; + } + + if(!psfLocalSet) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "No set is valid\n"); + Adapter->PackInfo[uiSearchRuleIndex].bActive=FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bValid=FALSE; + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value=0; + bcm_kfree(pstAddIndication); + } + + else if(psfLocalSet->bValid && (pstAddIndication->u8CC == 0)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSA ACK"); + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = + ntohs(pstAddIndication->u16VCID); + Adapter->PackInfo[uiSearchRuleIndex].usCID = + ntohs(pstAddIndication->u16CID); + + if(UPLINK_DIR == pstAddIndication->u8Direction) + atomic_set(&Adapter->PackInfo[uiSearchRuleIndex].uiPerSFTxResourceCount, DEFAULT_PERSFCOUNT); + CopyToAdapter(Adapter,psfLocalSet,uiSearchRuleIndex, + DSA_ACK, pstAddIndication); + // don't free pstAddIndication + + /* Inside CopyToAdapter, Sorting of all the SFs take place. + Hence any access to the newly added SF through uiSearchRuleIndex is invalid. + SHOULD BE STRICTLY AVOIDED. + */ +// *(PULONG)(((PUCHAR)pvBuffer)+1)=psfLocalSet->u32SFID; + memcpy((((PUCHAR)pvBuffer)+1), &psfLocalSet->u32SFID, 4); + + if(pstAddIndication->sfActiveSet.bValid == TRUE) + { + if(UPLINK_DIR == pstAddIndication->u8Direction) + { + if(!Adapter->LinkUpStatus) + { + netif_carrier_on(Adapter->dev); + netif_start_queue(Adapter->dev); + Adapter->LinkUpStatus = 1; + do_gettimeofday(&tv); + + atomic_set(&Adapter->TxPktAvail, 1); + wake_up(&Adapter->tx_packet_wait_queue); + Adapter->liTimeSinceLastNetEntry = tv.tv_sec; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "============Tx Service Flow Created!"); + } + } + } + } + + else + { + Adapter->PackInfo[uiSearchRuleIndex].bActive=FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bValid=FALSE; + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value=0; + bcm_kfree(pstAddIndication); + } + } + else + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "DSA ACK did not get valid SFID"); + bcm_kfree(pstAddIndication); + return FALSE; + } + } + break; + case DSC_REQ: + { + pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); + pstChangeIndication = (stLocalSFChangeIndicationAlt*)pstAddIndication; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC RESPONSE TO MAC %d", pLeader->PLength); + + *((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; + ((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_RSP; + + CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); + bcm_kfree(pstAddIndication); + } + break; + case DSC_RSP: + { + pLeader->PLength = sizeof(stLocalSFChangeIndicationAlt); + pstChangeIndication = (stLocalSFChangeIndicationAlt*)pstAddIndication; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSC ACK TO MAC %d", pLeader->PLength); + *((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *pstChangeIndication; + ((stLocalSFChangeIndicationAlt*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSC_ACK; + } + case DSC_ACK: + { + UINT uiSearchRuleIndex=0; + + pstChangeIndication = (stLocalSFChangeIndicationAlt *)pstAddIndication; + uiSearchRuleIndex=SearchSfid(Adapter,ntohl(pstChangeIndication->sfActiveSet.u32SFID)); + if(uiSearchRuleIndex > NO_OF_QUEUES-1) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "SF doesn't exist for which DSC_ACK is received"); + } + if((uiSearchRuleIndex < NO_OF_QUEUES)) + { + Adapter->PackInfo[uiSearchRuleIndex].ucDirection = pstChangeIndication->u8Direction; + if(pstChangeIndication->sfActiveSet.bValid==TRUE) + { + Adapter->PackInfo[uiSearchRuleIndex].bActiveSet=TRUE; + } + if(pstChangeIndication->sfAuthorizedSet.bValid==TRUE) + { + Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet=TRUE; + } + if(pstChangeIndication->sfAdmittedSet.bValid==TRUE) + { + Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet=TRUE; + } + + if(FALSE==pstChangeIndication->sfActiveSet.bValid) + { + Adapter->PackInfo[uiSearchRuleIndex].bActive = FALSE; + Adapter->PackInfo[uiSearchRuleIndex].bActivateRequestSent = FALSE; + if(pstChangeIndication->sfAdmittedSet.bValid) + { + psfLocalSet = &pstChangeIndication->sfAdmittedSet; + } + else if(pstChangeIndication->sfAuthorizedSet.bValid) + { + psfLocalSet = &pstChangeIndication->sfAuthorizedSet; + } + } + + else + { + psfLocalSet = &pstChangeIndication->sfActiveSet; + Adapter->PackInfo[uiSearchRuleIndex].bActive=TRUE; + } + if(psfLocalSet->bValid && (pstChangeIndication->u8CC == 0)) + { + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = + ntohs(pstChangeIndication->u16VCID); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "CC field is %d bvalid = %d\n", + pstChangeIndication->u8CC, psfLocalSet->bValid); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "VCID= %d\n", ntohs(pstChangeIndication->u16VCID)); + Adapter->PackInfo[uiSearchRuleIndex].usCID = + ntohs(pstChangeIndication->u16CID); + CopyToAdapter(Adapter,psfLocalSet,uiSearchRuleIndex, + DSC_ACK, pstAddIndication); + + *(PULONG)(((PUCHAR)pvBuffer)+1)=psfLocalSet->u32SFID; + } + else if(pstChangeIndication->u8CC == 6) + { + deleteSFBySfid(Adapter,uiSearchRuleIndex); + bcm_kfree(pstAddIndication); + } + } + else + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_PRINTK, 0, 0, "DSC ACK did not get valid SFID"); + bcm_kfree(pstAddIndication); + return FALSE; + } + } + break; + case DSD_REQ: + { + UINT uiSearchRuleIndex; + ULONG ulSFID; + + pLeader->PLength = sizeof(stLocalSFDeleteIndication); + *((stLocalSFDeleteIndication*)&(Adapter->caDsxReqResp[LEADER_SIZE])) = *((stLocalSFDeleteIndication*)pstAddIndication); + + ulSFID = ntohl(((stLocalSFDeleteIndication*)pstAddIndication)->u32SFID); + uiSearchRuleIndex=SearchSfid(Adapter,ulSFID); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD - Removing connection %x",uiSearchRuleIndex); + + if(uiSearchRuleIndex < NO_OF_QUEUES) + { + //Delete All Classifiers Associated with this SFID + deleteSFBySfid(Adapter,uiSearchRuleIndex); + Adapter->u32TotalDSD++; + } + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SENDING DSD RESPONSE TO MAC"); + ((stLocalSFDeleteIndication*)&(Adapter->caDsxReqResp[LEADER_SIZE]))->u8Type = DSD_RSP; + CopyBufferToControlPacket(Adapter,(PVOID)Adapter->caDsxReqResp); + } + case DSD_RSP: + { + //Do nothing as SF has already got Deleted + } + break; + case DSD_ACK: + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "DSD ACK Rcd, let App handle it\n"); + break; + default: + bcm_kfree(pstAddIndication); + return FALSE ; + } + return TRUE; +} + +int get_dsx_sf_data_to_application(PMINI_ADAPTER Adapter, UINT uiSFId, PUCHAR user_buffer) +{ + int status = 0; + struct _packet_info *psSfInfo=NULL; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "status =%d",status); + status = SearchSfid(Adapter, uiSFId); + if(status>NO_OF_QUEUES) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "SFID %d not present in queue !!!", uiSFId ); + return -EINVAL; + } + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "status =%d",status); + psSfInfo=&Adapter->PackInfo[status]; + if(psSfInfo->pstSFIndication && copy_to_user((PCHAR)user_buffer, + (PCHAR)psSfInfo->pstSFIndication, sizeof(stLocalSFAddIndicationAlt))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "copy to user failed SFID %d, present in queue !!!", uiSFId ); + status = -EFAULT; + return status; + } + return STATUS_SUCCESS; +} + +VOID OverrideServiceFlowParams(PMINI_ADAPTER Adapter,PUINT puiBuffer) +{ + B_UINT32 u32NumofSFsinMsg = ntohl(*(puiBuffer + 1)); + stIM_SFHostNotify *pHostInfo = NULL; + UINT uiSearchRuleIndex = 0; + ULONG ulSFID = 0; + + puiBuffer+=2; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "u32NumofSFsinMsg: 0x%x\n",u32NumofSFsinMsg); + + while(u32NumofSFsinMsg != 0 && u32NumofSFsinMsg < NO_OF_QUEUES) + { + u32NumofSFsinMsg--; + pHostInfo = (stIM_SFHostNotify *)puiBuffer; + puiBuffer = (PUINT)(pHostInfo + 1); + + ulSFID = ntohl(pHostInfo->SFID); + uiSearchRuleIndex=SearchSfid(Adapter,ulSFID); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"SFID: 0x%lx\n",ulSFID); + + if(uiSearchRuleIndex >= NO_OF_QUEUES || uiSearchRuleIndex == HiPriority) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"The SFID <%lx> doesn't exist in host entry or is Invalid\n", ulSFID); + continue; + } + + if(pHostInfo->RetainSF == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"Going to Delete SF"); + deleteSFBySfid(Adapter,uiSearchRuleIndex); + } + else + { + + Adapter->PackInfo[uiSearchRuleIndex].usVCID_Value = ntohs(pHostInfo->VCID); + Adapter->PackInfo[uiSearchRuleIndex].usCID = ntohs(pHostInfo->newCID); + Adapter->PackInfo[uiSearchRuleIndex].bActive=FALSE; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL,"pHostInfo->QoSParamSet: 0x%x\n",pHostInfo->QoSParamSet); + + if(pHostInfo->QoSParamSet & 0x1) + Adapter->PackInfo[uiSearchRuleIndex].bAuthorizedSet =TRUE; + if(pHostInfo->QoSParamSet & 0x2) + Adapter->PackInfo[uiSearchRuleIndex].bAdmittedSet =TRUE; + if(pHostInfo->QoSParamSet & 0x4) + { + Adapter->PackInfo[uiSearchRuleIndex].bActiveSet =TRUE; + Adapter->PackInfo[uiSearchRuleIndex].bActive=TRUE; + } + } + } +} + + + diff --git a/drivers/staging/bcm/CmHost.h b/drivers/staging/bcm/CmHost.h new file mode 100644 index 0000000..847782c --- /dev/null +++ b/drivers/staging/bcm/CmHost.h @@ -0,0 +1,166 @@ +/// ************************************************************************** +/// (c) Beceem Communications Inc. +/// All Rights Reserved +/// +/// \file : CmHost.h +/// \author : Rajeev Tirumala +/// \date : September 8 , 2006 +/// \brief : Definitions for Connection Management Requests structure +/// which we will use to setup our connection structures.Its high +/// time we had a header file for CmHost.cpp to isolate the way +/// f/w sends DSx messages and the way we interpret them in code. +/// Revision History +/// +/// Date Author Version Description +/// 08-Sep-06 Rajeev 0.1 Created +/// ************************************************************************** +#ifndef _CM_HOST_H +#define _CM_HOST_H + +#pragma once +#pragma pack (push,4) + +#define DSX_MESSAGE_EXCHANGE_BUFFER 0xBF60AC84 // This contains the pointer +#define DSX_MESSAGE_EXCHANGE_BUFFER_SIZE 72000 // 24 K Bytes + +/// \brief structure stLocalSFAddRequest +typedef struct stLocalSFAddRequestAlt{ + B_UINT8 u8Type; + B_UINT8 u8Direction; + + B_UINT16 u16TID; + /// \brief 16bitCID + B_UINT16 u16CID; + /// \brief 16bitVCID + B_UINT16 u16VCID; + + + /// \brief structure ParameterSet + stServiceFlowParamSI sfParameterSet; + + //USE_MEMORY_MANAGER(); +}stLocalSFAddRequestAlt; + +/// \brief structure stLocalSFAddIndication +typedef struct stLocalSFAddIndicationAlt{ + B_UINT8 u8Type; + B_UINT8 u8Direction; + B_UINT16 u16TID; + /// \brief 16bitCID + B_UINT16 u16CID; + /// \brief 16bitVCID + B_UINT16 u16VCID; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; + + B_UINT8 u8CC; /**< Confirmation Code*/ + B_UINT8 u8Padd; /**< 8-bit Padding */ + B_UINT16 u16Padd; /**< 16 bit Padding */ +// USE_MEMORY_MANAGER(); +}stLocalSFAddIndicationAlt; + +/// \brief structure stLocalSFAddConfirmation +typedef struct stLocalSFAddConfirmationAlt{ + B_UINT8 u8Type; + B_UINT8 u8Direction; + B_UINT16 u16TID; + /// \brief 16bitCID + B_UINT16 u16CID; + /// \brief 16bitVCID + B_UINT16 u16VCID; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; +}stLocalSFAddConfirmationAlt; + + +/// \brief structure stLocalSFChangeRequest +typedef struct stLocalSFChangeRequestAlt{ + B_UINT8 u8Type; + B_UINT8 u8Direction; + B_UINT16 u16TID; + /// \brief 16bitCID + B_UINT16 u16CID; + /// \brief 16bitVCID + B_UINT16 u16VCID; + /* + //Pointer location at which following Service Flow param Structure can be read + //from the target. We get only the address location and we need to read out the + //entire SF param structure at the given location on target + */ + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ParameterSet + stServiceFlowParamSI sfActiveSet; + + B_UINT8 u8CC; /**< Confirmation Code*/ + B_UINT8 u8Padd; /**< 8-bit Padding */ + B_UINT16 u16Padd; /**< 16 bit */ + +}stLocalSFChangeRequestAlt; + +/// \brief structure stLocalSFChangeConfirmation +typedef struct stLocalSFChangeConfirmationAlt{ + B_UINT8 u8Type; + B_UINT8 u8Direction; + B_UINT16 u16TID; + /// \brief 16bitCID + B_UINT16 u16CID; + /// \brief 16bitVCID + B_UINT16 u16VCID; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; + +}stLocalSFChangeConfirmationAlt; + +/// \brief structure stLocalSFChangeIndication +typedef struct stLocalSFChangeIndicationAlt{ + B_UINT8 u8Type; + B_UINT8 u8Direction; + B_UINT16 u16TID; + /// \brief 16bitCID + B_UINT16 u16CID; + /// \brief 16bitVCID + B_UINT16 u16VCID; + /// \brief structure AuthorizedSet + stServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + stServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + stServiceFlowParamSI sfActiveSet; + + B_UINT8 u8CC; /**< Confirmation Code*/ + B_UINT8 u8Padd; /**< 8-bit Padding */ + B_UINT16 u16Padd; /**< 16 bit */ + +}stLocalSFChangeIndicationAlt; + +ULONG StoreCmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT *puBufferLength); + +ULONG GetNextTargetBufferLocation(PMINI_ADAPTER Adapter,B_UINT16 tid); + +INT AllocAdapterDsxBuffer(PMINI_ADAPTER Adapter); + +INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter); +ULONG SetUpTargetDsxBuffers(PMINI_ADAPTER Adapter); + +BOOLEAN CmControlResponseMessage(PMINI_ADAPTER Adapter,PVOID pvBuffer); + +VOID deleteSFBySfid(PMINI_ADAPTER Adapter, UINT uiSearchRuleIndex); + +#pragma pack (pop) + +#endif diff --git a/drivers/staging/bcm/DDRInit.c b/drivers/staging/bcm/DDRInit.c new file mode 100644 index 0000000..8907e21 --- /dev/null +++ b/drivers/staging/bcm/DDRInit.c @@ -0,0 +1,1302 @@ +#include "headers.h" + +#ifndef BCM_SHM_INTERFACE + + +#define DDR_DUMP_INTERNAL_DEVICE_MEMORY 0xBFC02B00 +#define MIPS_CLOCK_REG 0x0f000820 + + //DDR INIT-133Mhz +#define T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 12 //index for 0x0F007000 +static DDR_SET_NODE asT3_DDRSetting133MHz[]= {// # DPLL Clock Setting + {0x0F000800,0x00007212}, + {0x0f000820,0x07F13FFF}, + {0x0f000810,0x00000F95}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + // Changed source for X-bar and MIPS clock to APLL + {0x0f000840,0x0FFF1B00}, + {0x0f000870,0x00000002}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + {0x0F00a04C,0x0000000C}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x02000007}, + {0x0F007028,0x02020202}, + {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030,0x05000000}, + {0x0F007034,0x00000003}, + {0x0F007038,0x110a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C,0x02101010},//ROB - 0x02101010,//0x02101018}, + {0x0F007040,0x45751200},//ROB - 0x45751200,//0x450f1200}, + {0x0F007044,0x110a0d00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048,0x081b0306}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0000001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x0010246c}, + {0x0F007064,0x00000010}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00007000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + //# Enable BW improvement within memory controller + {0x0F007094,0x00000104}, + //# Enable 2 ports within X-bar + {0x0F00A000,0x00000016}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000} + }; +//80Mhz +#define T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 10 //index for 0x0F007000 +static DDR_SET_NODE asT3_DDRSetting80MHz[]= {// # DPLL Clock Setting + {0x0f000810,0x00000F95}, + {0x0f000820,0x07f1ffff}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + {0x0F00a000,0x00000016}, + {0x0F00a04C,0x0000000C}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01000000}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020000}, + {0x0F007020,0x04020107}, + {0x0F007024,0x00000007}, + {0x0F007028,0x02020201}, + {0x0F00702c,0x0204040a}, + {0x0F007030,0x04000000}, + {0x0F007034,0x00000002}, + {0x0F007038,0x1F060200}, + {0x0F00703C,0x1C22221F}, + {0x0F007040,0x8A006600}, + {0x0F007044,0x221a0800}, + {0x0F007048,0x02690204}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0000001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x000A15D6}, + {0x0F007064,0x0000000A}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00004000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + {0x0F007094,0x00000104}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000} + }; +//100Mhz +#define T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 13 //index for 0x0F007000 +static DDR_SET_NODE asT3_DDRSetting100MHz[]= {// # DPLL Clock Setting + {0x0F000800,0x00007008}, + {0x0f000810,0x00000F95}, + {0x0f000820,0x07F13E3F}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + // Changed source for X-bar and MIPS clock to APLL + //0x0f000840,0x0FFF1800, + {0x0f000840,0x0FFF1B00}, + {0x0f000870,0x00000002}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + {0x0F00a04C,0x0000000C}, + //# Enable 2 ports within X-bar + {0x0F00A000,0x00000016}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020001}, // POP - 0x00020000 Normal 0x01020000 + {0x0F007020,0x04020107},//Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x00000007}, + {0x0F007028,0x01020201}, + {0x0F00702c,0x0204040A}, + {0x0F007030,0x06000000}, + {0x0F007034,0x00000004}, + {0x0F007038,0x20080200}, + {0x0F00703C,0x02030320}, + {0x0F007040,0x6E7F1200}, + {0x0F007044,0x01190A00}, + {0x0F007048,0x06120305},//0x02690204 // 0x06120305 + {0x0F00704c,0x00000000}, + {0x0F007050,0x0000001C}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x00082ED6}, + {0x0F007064,0x0000000A}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00005000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + //# Enable BW improvement within memory controller + {0x0F007094,0x00000104}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000} + }; + +//Net T3B DDR Settings +//DDR INIT-133Mhz +static DDR_SET_NODE asDPLL_266MHZ[] = { + {0x0F000800,0x00007212}, + {0x0f000820,0x07F13FFF}, + {0x0f000810,0x00000F95}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + // Changed source for X-bar and MIPS clock to APLL + {0x0f000840,0x0FFF1B00}, + {0x0f000870,0x00000002} + }; +#if 0 +static DDR_SET_NODE asDPLL_800MHZ[] = { + {0x0f000810,0x00000F95}, + {0x0f000810,0x00000F95}, + {0x0f000810,0x00000F95}, + {0x0f000820,0x03F1365B}, + {0x0f000840,0x0FFF0000}, + {0x0f000880,0x000003DD}, + {0x0f000860,0x00000000} + }; +#endif + +#define T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 11 //index for 0x0F007000 +static DDR_SET_NODE asT3B_DDRSetting133MHz[] = {// # DPLL Clock Setting + {0x0f000810,0x00000F95}, + {0x0f000810,0x00000F95}, + {0x0f000810,0x00000F95}, + {0x0f000820,0x07F13652}, + {0x0f000840,0x0FFF0800}, + // Changed source for X-bar and MIPS clock to APLL + {0x0f000880,0x000003DD}, + {0x0f000860,0x00000000}, + // Changed source for X-bar and MIPS clock to APLL + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + //# Enable 2 ports within X-bar + {0x0F00A000,0x00000016}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x02000007}, + {0x0F007028,0x02020202}, + {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030,0x05000000}, + {0x0F007034,0x00000003}, + {0x0F007038,0x130a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C,0x02101012},//ROB - 0x02101010,//0x02101018}, + {0x0F007040,0x457D1200},//ROB - 0x45751200,//0x450f1200}, + {0x0F007044,0x11130d00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048,0x040D0306}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0000001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x0010246c}, + {0x0F007064,0x00000012}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00007000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + //# Enable BW improvement within memory controller + {0x0F007094,0x00000104}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000}, + }; + +#define T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000 +static DDR_SET_NODE asT3B_DDRSetting80MHz[] = {// # DPLL Clock Setting + {0x0f000810,0x00000F95}, + {0x0f000820,0x07F13FFF}, + {0x0f000840,0x0FFF1F00}, + {0x0f000880,0x000003DD}, + {0x0f000860,0x00000000}, + + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + {0x0F00a000,0x00000016}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01000000}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020000}, + {0x0F007020,0x04020107}, + {0x0F007024,0x00000007}, + {0x0F007028,0x02020201}, + {0x0F00702c,0x0204040a}, + {0x0F007030,0x04000000}, + {0x0F007034,0x02000002}, + {0x0F007038,0x1F060202}, + {0x0F00703C,0x1C22221F}, + {0x0F007040,0x8A006600}, + {0x0F007044,0x221a0800}, + {0x0F007048,0x02690204}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0100001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x000A15D6}, + {0x0F007064,0x0000000A}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00004000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + {0x0F007094,0x00000104}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000} + }; + +//100Mhz +#define T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 9 //index for 0x0F007000 +static DDR_SET_NODE asT3B_DDRSetting100MHz[] = {// # DPLL Clock Setting + {0x0f000810,0x00000F95}, + {0x0f000820,0x07F1369B}, + {0x0f000840,0x0FFF0800}, + {0x0f000880,0x000003DD}, + {0x0f000860,0x00000000}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + //# Enable 2 ports within X-bar + {0x0F00A000,0x00000016}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020000}, // POP - 0x00020000 Normal 0x01020000 + {0x0F007020,0x04020107},//Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x00000007}, + {0x0F007028,0x01020201}, + {0x0F00702c,0x0204040A}, + {0x0F007030,0x06000000}, + {0x0F007034,0x02000004}, + {0x0F007038,0x20080200}, + {0x0F00703C,0x02030320}, + {0x0F007040,0x6E7F1200}, + {0x0F007044,0x01190A00}, + {0x0F007048,0x06120305},//0x02690204 // 0x06120305 + {0x0F00704c,0x00000000}, + {0x0F007050,0x0100001C}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x00082ED6}, + {0x0F007064,0x0000000A}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00005000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + //# Enable BW improvement within memory controller + {0x0F007094,0x00000104}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000} + }; + + +#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 9 //index for 0x0F007000 +static DDR_SET_NODE asT3LP_DDRSetting133MHz[]= {// # DPLL Clock Setting + {0x0f000820,0x03F1365B}, + {0x0f000810,0x00002F95}, + {0x0f000880,0x000003DD}, + // Changed source for X-bar and MIPS clock to APLL + {0x0f000840,0x0FFF0000}, + {0x0f000860,0x00000000}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + {0x0F00A000,0x00000016}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x02000007}, + {0x0F007028,0x02020200}, + {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030,0x05000000}, + {0x0F007034,0x00000003}, + {0x0F007038,0x200a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C,0x02101020},//ROB - 0x02101010,//0x02101018, + {0x0F007040,0x45711200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044,0x110D0D00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048,0x04080306}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0100001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x0010245F}, + {0x0F007064,0x00000010}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00007000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + {0x0F007088,0x01000001}, + {0x0F00708c,0x00000101}, + {0x0F007090,0x00000000}, + //# Enable BW improvement within memory controller + {0x0F007094,0x00040000}, + {0x0F007098,0x00000000}, + {0x0F0070c8,0x00000104}, + //# Enable 2 ports within X-bar + //# Enable start bit within memory controller + {0x0F007018,0x01010000} +}; + +#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 11 //index for 0x0F007000 +static DDR_SET_NODE asT3LP_DDRSetting100MHz[]= {// # DPLL Clock Setting + {0x0f000810,0x00002F95}, + {0x0f000820,0x03F1369B}, + {0x0f000840,0x0fff0000}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + // Changed source for X-bar and MIPS clock to APLL + {0x0f000840,0x0FFF0000}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020000},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020,0x04020107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x00000007}, + {0x0F007028,0x01020200}, + {0x0F00702c,0x0204040a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030,0x06000000}, + {0x0F007034,0x00000004}, + {0x0F007038,0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C,0x0203031F},//ROB - 0x02101010,//0x02101018, + {0x0F007040,0x6e001200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044,0x011a0a00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048,0x03000305}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0100001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x00082ED6}, + {0x0F007064,0x0000000A}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00005000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + {0x0F007088,0x01000001}, + {0x0F00708c,0x00000101}, + {0x0F007090,0x00000000}, + {0x0F007094,0x00010000}, + {0x0F007098,0x00000000}, + {0x0F0070C8,0x00000104}, + //# Enable 2 ports within X-bar + {0x0F00A000,0x00000016}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000} +}; + +#define T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 9 //index for 0x0F007000 +static DDR_SET_NODE asT3LP_DDRSetting80MHz[]= {// # DPLL Clock Setting + {0x0f000820,0x07F13FFF}, + {0x0f000810,0x00002F95}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + {0x0f000840,0x0FFF1F00}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0F00a084,0x1Cffffff}, + {0x0F00a080,0x1C000000}, + {0x0F00A000,0x00000016}, + {0x0f007000,0x00010001}, + {0x0f007004,0x01000000}, + {0x0f007008,0x01000001}, + {0x0f00700c,0x00000000}, + {0x0f007010,0x01000000}, + {0x0f007014,0x01000100}, + {0x0f007018,0x01000000}, + {0x0f00701c,0x01020000}, + {0x0f007020,0x04020107}, + {0x0f007024,0x00000007}, + {0x0f007028,0x02020200}, + {0x0f00702c,0x0204040a}, + {0x0f007030,0x04000000}, + {0x0f007034,0x00000002}, + {0x0f007038,0x1d060200}, + {0x0f00703c,0x1c22221d}, + {0x0f007040,0x8A116600}, + {0x0f007044,0x222d0800}, + {0x0f007048,0x02690204}, + {0x0f00704c,0x00000000}, + {0x0f007050,0x0100001c}, + {0x0f007054,0x00000000}, + {0x0f007058,0x00000000}, + {0x0f00705c,0x00000000}, + {0x0f007060,0x000A15D6}, + {0x0f007064,0x0000000A}, + {0x0f007068,0x00000000}, + {0x0f00706c,0x00000001}, + {0x0f007070,0x00004000}, + {0x0f007074,0x00000000}, + {0x0f007078,0x00000000}, + {0x0f00707c,0x00000000}, + {0x0f007080,0x00000000}, + {0x0f007084,0x00000000}, + {0x0f007088,0x01000001}, + {0x0f00708c,0x00000101}, + {0x0f007090,0x00000000}, + {0x0f007094,0x00010000}, + {0x0f007098,0x00000000}, + {0x0F0070C8,0x00000104}, + {0x0F007018,0x01010000} +}; + + + + +///T3 LP-B (UMA-B) + +#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ 7 //index for 0x0F007000 +static DDR_SET_NODE asT3LPB_DDRSetting160MHz[]= {// # DPLL Clock Setting + + {0x0f000820,0x03F137DB}, + {0x0f000810,0x01842795}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + {0x0f000840,0x0FFF0400}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0f003050,0x00000021},//this is flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084,0x1Cffffff},//Now dump from her in internal memory + {0x0F00a080,0x1C000000}, + {0x0F00A000,0x00000016}, + {0x0f007000,0x00010001}, + {0x0f007004,0x01000001}, + {0x0f007008,0x01000101}, + {0x0f00700c,0x00000000}, + {0x0f007010,0x01000100}, + {0x0f007014,0x01000100}, + {0x0f007018,0x01000000}, + {0x0f00701c,0x01020000}, + {0x0f007020,0x04030107}, + {0x0f007024,0x02000007}, + {0x0f007028,0x02020200}, + {0x0f00702c,0x0206060a}, + {0x0f007030,0x050d0d00}, + {0x0f007034,0x00000003}, + {0x0f007038,0x170a0200}, + {0x0f00703c,0x02101012}, + {0x0f007040,0x45161200}, + {0x0f007044,0x11250c00}, + {0x0f007048,0x04da0307}, + {0x0f00704c,0x00000000}, + {0x0f007050,0x0000001c}, + {0x0f007054,0x00000000}, + {0x0f007058,0x00000000}, + {0x0f00705c,0x00000000}, + {0x0f007060,0x00142bb6}, + {0x0f007064,0x20430014}, + {0x0f007068,0x00000000}, + {0x0f00706c,0x00000001}, + {0x0f007070,0x00009000}, + {0x0f007074,0x00000000}, + {0x0f007078,0x00000000}, + {0x0f00707c,0x00000000}, + {0x0f007080,0x00000000}, + {0x0f007084,0x00000000}, + {0x0f007088,0x01000001}, + {0x0f00708c,0x00000101}, + {0x0f007090,0x00000000}, + {0x0f007094,0x00040000}, + {0x0f007098,0x00000000}, + {0x0F0070C8,0x00000104}, + {0x0F007018,0x01010000} +}; + + +#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ 7 //index for 0x0F007000 +static DDR_SET_NODE asT3LPB_DDRSetting133MHz[]= {// # DPLL Clock Setting + {0x0f000820,0x03F1365B}, + {0x0f000810,0x00002F95}, + {0x0f000880,0x000003DD}, + // Changed source for X-bar and MIPS clock to APLL + {0x0f000840,0x0FFF0000}, + {0x0f000860,0x00000000}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084,0x1Cffffff},//dump from here in internal memory + {0x0F00a080,0x1C000000}, + {0x0F00A000,0x00000016}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020001},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020,0x04030107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x02000007}, + {0x0F007028,0x02020200}, + {0x0F00702c,0x0206060a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030,0x05000000}, + {0x0F007034,0x00000003}, + {0x0F007038,0x190a0200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C,0x02101017},//ROB - 0x02101010,//0x02101018, + {0x0F007040,0x45171200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044,0x11290D00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048,0x04080306}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0100001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x0010245F}, + {0x0F007064,0x00000010}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00007000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + {0x0F007088,0x01000001}, + {0x0F00708c,0x00000101}, + {0x0F007090,0x00000000}, + //# Enable BW improvement within memory controller + {0x0F007094,0x00040000}, + {0x0F007098,0x00000000}, + {0x0F0070c8,0x00000104}, + //# Enable 2 ports within X-bar + //# Enable start bit within memory controller + {0x0F007018,0x01010000} +}; + +#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ 8 //index for 0x0F007000 +static DDR_SET_NODE asT3LPB_DDRSetting100MHz[]= {// # DPLL Clock Setting + {0x0f000810,0x00002F95}, + {0x0f000820,0x03F1369B}, + {0x0f000840,0x0fff0000}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + // Changed source for X-bar and MIPS clock to APLL + {0x0f000840,0x0FFF0000}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084,0x1Cffffff}, //dump from here in internal memory + {0x0F00a080,0x1C000000}, + //Memcontroller Default values + {0x0F007000,0x00010001}, + {0x0F007004,0x01010100}, + {0x0F007008,0x01000001}, + {0x0F00700c,0x00000000}, + {0x0F007010,0x01000000}, + {0x0F007014,0x01000100}, + {0x0F007018,0x01000000}, + {0x0F00701c,0x01020000},// POP - 0x00020001 Normal 0x01020001 + {0x0F007020,0x04020107}, //Normal - 0x04030107 POP - 0x05030107 + {0x0F007024,0x00000007}, + {0x0F007028,0x01020200}, + {0x0F00702c,0x0204040a},//ROB- 0x0205050a,//0x0206060a + {0x0F007030,0x06000000}, + {0x0F007034,0x00000004}, + {0x0F007038,0x1F080200},//ROB - 0x110a0200,//0x180a0200,// 0x1f0a0200 + {0x0F00703C,0x0203031F},//ROB - 0x02101010,//0x02101018, + {0x0F007040,0x6e001200},//ROB - 0x45751200,//0x450f1200, + {0x0F007044,0x011a0a00},//ROB - 0x110a0d00//0x111f0d00 + {0x0F007048,0x03000305}, + {0x0F00704c,0x00000000}, + {0x0F007050,0x0100001c}, + {0x0F007054,0x00000000}, + {0x0F007058,0x00000000}, + {0x0F00705c,0x00000000}, + {0x0F007060,0x00082ED6}, + {0x0F007064,0x0000000A}, + {0x0F007068,0x00000000}, + {0x0F00706c,0x00000001}, + {0x0F007070,0x00005000}, + {0x0F007074,0x00000000}, + {0x0F007078,0x00000000}, + {0x0F00707C,0x00000000}, + {0x0F007080,0x00000000}, + {0x0F007084,0x00000000}, + {0x0F007088,0x01000001}, + {0x0F00708c,0x00000101}, + {0x0F007090,0x00000000}, + {0x0F007094,0x00010000}, + {0x0F007098,0x00000000}, + {0x0F0070C8,0x00000104}, + //# Enable 2 ports within X-bar + {0x0F00A000,0x00000016}, + //# Enable start bit within memory controller + {0x0F007018,0x01010000} +}; + +#define T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ 7 //index for 0x0F007000 +static DDR_SET_NODE asT3LPB_DDRSetting80MHz[]= {// # DPLL Clock Setting + {0x0f000820,0x07F13FFF}, + {0x0f000810,0x00002F95}, + {0x0f000860,0x00000000}, + {0x0f000880,0x000003DD}, + {0x0f000840,0x0FFF1F00}, + {0x0F00a044,0x1fffffff}, + {0x0F00a040,0x1f000000}, + {0x0f003050,0x00000021},//flash/eeprom clock divisor which set the flash clock to 20 MHz + {0x0F00a084,0x1Cffffff},// dump from here in internal memory + {0x0F00a080,0x1C000000}, + {0x0F00A000,0x00000016}, + {0x0f007000,0x00010001}, + {0x0f007004,0x01000000}, + {0x0f007008,0x01000001}, + {0x0f00700c,0x00000000}, + {0x0f007010,0x01000000}, + {0x0f007014,0x01000100}, + {0x0f007018,0x01000000}, + {0x0f00701c,0x01020000}, + {0x0f007020,0x04020107}, + {0x0f007024,0x00000007}, + {0x0f007028,0x02020200}, + {0x0f00702c,0x0204040a}, + {0x0f007030,0x04000000}, + {0x0f007034,0x00000002}, + {0x0f007038,0x1d060200}, + {0x0f00703c,0x1c22221d}, + {0x0f007040,0x8A116600}, + {0x0f007044,0x222d0800}, + {0x0f007048,0x02690204}, + {0x0f00704c,0x00000000}, + {0x0f007050,0x0100001c}, + {0x0f007054,0x00000000}, + {0x0f007058,0x00000000}, + {0x0f00705c,0x00000000}, + {0x0f007060,0x000A15D6}, + {0x0f007064,0x0000000A}, + {0x0f007068,0x00000000}, + {0x0f00706c,0x00000001}, + {0x0f007070,0x00004000}, + {0x0f007074,0x00000000}, + {0x0f007078,0x00000000}, + {0x0f00707c,0x00000000}, + {0x0f007080,0x00000000}, + {0x0f007084,0x00000000}, + {0x0f007088,0x01000001}, + {0x0f00708c,0x00000101}, + {0x0f007090,0x00000000}, + {0x0f007094,0x00010000}, + {0x0f007098,0x00000000}, + {0x0F0070C8,0x00000104}, + {0x0F007018,0x01010000} +}; + + +int ddr_init(MINI_ADAPTER *Adapter) +{ + PDDR_SETTING psDDRSetting=NULL; + ULONG RegCount=0; + ULONG value = 0; + UINT uiResetValue = 0; + UINT uiClockSetting = 0; + int retval = STATUS_SUCCESS; + + switch (Adapter->chip_id) + { + case 0xbece3200: + switch (Adapter->DDRSetting) + { + case DDR_80_MHZ: + psDDRSetting=asT3LP_DDRSetting80MHz; + RegCount=(sizeof(asT3LP_DDRSetting80MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_100_MHZ: + psDDRSetting=asT3LP_DDRSetting100MHz; + RegCount=(sizeof(asT3LP_DDRSetting100MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_133_MHZ: + psDDRSetting=asT3LP_DDRSetting133MHz; + RegCount=(sizeof(asT3LP_DDRSetting133MHz)/ + sizeof(DDR_SETTING)); + if(Adapter->bMipsConfig == MIPS_200_MHZ) + { + uiClockSetting = 0x03F13652; + } + else + { + uiClockSetting = 0x03F1365B; + } + break; + default: + return -EINVAL; + } + + break; + case T3LPB: + case BCS220_2: + case BCS220_2BC: + case BCS250_BC: + case BCS220_3 : + /* Set bit 2 and bit 6 to 1 for BBIC 2mA drive + * (please check current value and additionally set these bits) + */ + if( (Adapter->chip_id != BCS220_2) && + (Adapter->chip_id != BCS220_2BC) && + (Adapter->chip_id != BCS220_3) ) + { + retval= rdmalt(Adapter,(UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue |= 0x44; + retval = wrmalt(Adapter,(UINT)0x0f000830, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, WRM, DBG_LVL_ALL, "%s:%d WRM failed\n", __FUNCTION__, __LINE__); + return retval; + } + } + switch(Adapter->DDRSetting) + { + + + + case DDR_80_MHZ: + psDDRSetting = asT3LPB_DDRSetting80MHz; + RegCount=(sizeof(asT3B_DDRSetting80MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_100_MHZ: + psDDRSetting=asT3LPB_DDRSetting100MHz; + RegCount=(sizeof(asT3B_DDRSetting100MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_133_MHZ: + psDDRSetting = asT3LPB_DDRSetting133MHz; + RegCount=(sizeof(asT3B_DDRSetting133MHz)/ + sizeof(DDR_SETTING)); + + if(Adapter->bMipsConfig == MIPS_200_MHZ) + { + uiClockSetting = 0x03F13652; + } + else + { + uiClockSetting = 0x03F1365B; + } + break; + + case DDR_160_MHZ: + psDDRSetting = asT3LPB_DDRSetting160MHz; + RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(DDR_SETTING); + + if(Adapter->bMipsConfig == MIPS_200_MHZ) + { + uiClockSetting = 0x03F137D2; + } + else + { + uiClockSetting = 0x03F137DB; + } + } + break; + + case 0xbece0110: + case 0xbece0120: + case 0xbece0121: + case 0xbece0130: + case 0xbece0300: + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "DDR Setting: %x\n", Adapter->DDRSetting); + switch (Adapter->DDRSetting) + { + case DDR_80_MHZ: + psDDRSetting = asT3_DDRSetting80MHz; + RegCount = (sizeof(asT3_DDRSetting80MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_100_MHZ: + psDDRSetting = asT3_DDRSetting100MHz; + RegCount = (sizeof(asT3_DDRSetting100MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_133_MHZ: + psDDRSetting = asT3_DDRSetting133MHz; + RegCount = (sizeof(asT3_DDRSetting133MHz)/ + sizeof(DDR_SETTING)); + break; + default: + return -EINVAL; + } + case 0xbece0310: + { + switch (Adapter->DDRSetting) + { + case DDR_80_MHZ: + psDDRSetting = asT3B_DDRSetting80MHz; + RegCount=(sizeof(asT3B_DDRSetting80MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_100_MHZ: + psDDRSetting=asT3B_DDRSetting100MHz; + RegCount=(sizeof(asT3B_DDRSetting100MHz)/ + sizeof(DDR_SETTING)); + break; + case DDR_133_MHZ: + + if(Adapter->bDPLLConfig == PLL_266_MHZ)//266Mhz PLL selected. + { + memcpy(asT3B_DDRSetting133MHz, asDPLL_266MHZ, + sizeof(asDPLL_266MHZ)); + psDDRSetting = asT3B_DDRSetting133MHz; + RegCount=(sizeof(asT3B_DDRSetting133MHz)/ + sizeof(DDR_SETTING)); + } + else + { + psDDRSetting = asT3B_DDRSetting133MHz; + RegCount=(sizeof(asT3B_DDRSetting133MHz)/ + sizeof(DDR_SETTING)); + if(Adapter->bMipsConfig == MIPS_200_MHZ) + { + uiClockSetting = 0x07F13652; + } + else + { + uiClockSetting = 0x07F1365B; + } + } + break; + default: + return -EINVAL; + } + break; + + } + default: + return -EINVAL; + } + + value=0; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Register Count is =%lu\n", RegCount); + while(RegCount && !retval) + { + if(uiClockSetting && psDDRSetting->ulRegAddress == MIPS_CLOCK_REG) + { + value = uiClockSetting; + } + else + { + value = psDDRSetting->ulRegValue; + } + retval = wrmalt(Adapter, psDDRSetting->ulRegAddress, (PUINT)&value, sizeof(value)); + if(STATUS_SUCCESS != retval) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"%s:%d\n", __FUNCTION__, __LINE__); + break; + } + + RegCount--; + psDDRSetting++; + } + + if(Adapter->chip_id >= 0xbece3300 ) + { + + mdelay(3); + if( (Adapter->chip_id != BCS220_2)&& + (Adapter->chip_id != BCS220_2BC)&& + (Adapter->chip_id != BCS220_3)) + { + /* drive MDDR to half in case of UMA-B: */ + uiResetValue = 0x01010001; + retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue = 0x00040020; + retval = wrmalt(Adapter, (UINT)0x0F007094, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue = 0x01020101; + retval = wrmalt(Adapter, (UINT)0x0F00701c, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue = 0x01010000; + retval = wrmalt(Adapter, (UINT)0x0F007018, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + } + mdelay(3); + + /* DC/DC standby change... + * This is to be done only for Hybrid PMU mode. + * with the current h/w there is no way to detect this. + * and since we dont have internal PMU lets do it under UMA-B chip id. + * we will change this when we will have internal PMU. + */ + if(Adapter->PmuMode == HYBRID_MODE_7C) + { + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue = 0x1322a8; + retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue = 0x132296; + retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + } + else if(Adapter->PmuMode == HYBRID_MODE_6 ) + { + + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue = 0x6003229a; + retval = wrmalt(Adapter, (UINT)0x0f000d14, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + retval = rdmalt(Adapter,(UINT)0x0f000c00, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + uiResetValue = 0x1322a8; + retval = wrmalt(Adapter, (UINT)0x0f000d1c, &uiResetValue, sizeof(uiResetValue)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,CMHOST, RDM, DBG_LVL_ALL, "%s:%d RDM failed\n", __FUNCTION__, __LINE__); + return retval; + } + } + + } + Adapter->bDDRInitDone = TRUE; + return retval; +} + +int download_ddr_settings(PMINI_ADAPTER Adapter) +{ + PDDR_SET_NODE psDDRSetting=NULL; + ULONG RegCount=0; + unsigned long ul_ddr_setting_load_addr = DDR_DUMP_INTERNAL_DEVICE_MEMORY; + UINT value = 0; + int retval = STATUS_SUCCESS; + BOOLEAN bOverrideSelfRefresh = FALSE; + + switch (Adapter->chip_id) + { + case 0xbece3200: + switch (Adapter->DDRSetting) + { + case DDR_80_MHZ: + psDDRSetting = asT3LP_DDRSetting80MHz; + RegCount = (sizeof(asT3LP_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; + break; + case DDR_100_MHZ: + psDDRSetting = asT3LP_DDRSetting100MHz; + RegCount = (sizeof(asT3LP_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; + break; + case DDR_133_MHZ: + bOverrideSelfRefresh = TRUE; + psDDRSetting = asT3LP_DDRSetting133MHz; + RegCount = (sizeof(asT3LP_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + psDDRSetting += T3LP_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; + break; + default: + return -EINVAL; + } + break; + + case T3LPB: + case BCS220_2: + case BCS220_2BC: + case BCS250_BC: + case BCS220_3 : + switch (Adapter->DDRSetting) + { + case DDR_80_MHZ: + psDDRSetting = asT3LPB_DDRSetting80MHz; + RegCount=(sizeof(asT3LPB_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; + break; + case DDR_100_MHZ: + psDDRSetting = asT3LPB_DDRSetting100MHz; + RegCount = (sizeof(asT3LPB_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; + break; + case DDR_133_MHZ: + bOverrideSelfRefresh = TRUE; + psDDRSetting = asT3LPB_DDRSetting133MHz; + RegCount = (sizeof(asT3LPB_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; + break; + + case DDR_160_MHZ: + bOverrideSelfRefresh = TRUE; + psDDRSetting = asT3LPB_DDRSetting160MHz; + RegCount = sizeof(asT3LPB_DDRSetting160MHz)/sizeof(DDR_SET_NODE); + RegCount -= T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ; + psDDRSetting += T3LPB_SKIP_CLOCK_PROGRAM_DUMP_160MHZ; + + break; + default: + return -EINVAL; + } + break; + case 0xbece0300: + switch (Adapter->DDRSetting) + { + case DDR_80_MHZ: + psDDRSetting = asT3_DDRSetting80MHz; + RegCount = (sizeof(asT3_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); + RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; + break; + case DDR_100_MHZ: + psDDRSetting = asT3_DDRSetting100MHz; + RegCount = (sizeof(asT3_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); + RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; + break; + case DDR_133_MHZ: + psDDRSetting = asT3_DDRSetting133MHz; + RegCount = (sizeof(asT3_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); + RegCount-=T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + psDDRSetting += T3_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + break; + default: + return -EINVAL; + } + break; + case 0xbece0310: + { + switch (Adapter->DDRSetting) + { + case DDR_80_MHZ: + psDDRSetting = asT3B_DDRSetting80MHz; + RegCount = (sizeof(asT3B_DDRSetting80MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ ; + psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_80MHZ; + break; + case DDR_100_MHZ: + psDDRSetting = asT3B_DDRSetting100MHz; + RegCount = (sizeof(asT3B_DDRSetting100MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ ; + psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_100MHZ; + break; + case DDR_133_MHZ: + bOverrideSelfRefresh = TRUE; + psDDRSetting = asT3B_DDRSetting133MHz; + RegCount = (sizeof(asT3B_DDRSetting133MHz)/sizeof(DDR_SET_NODE)); + RegCount -= T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ ; + psDDRSetting += T3B_SKIP_CLOCK_PROGRAM_DUMP_133MHZ; + break; + } + break; + } + default: + return -EINVAL; + } + //total number of Register that has to be dumped + value =RegCount ; + retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value)); + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"%s:%d\n", __FUNCTION__, __LINE__); + + return retval; + } + ul_ddr_setting_load_addr+=sizeof(ULONG); + /*signature */ + value =(0x1d1e0dd0); + retval = wrmalt(Adapter, ul_ddr_setting_load_addr, &value, sizeof(value)); + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"%s:%d\n", __FUNCTION__, __LINE__); + return retval; + } + + ul_ddr_setting_load_addr+=sizeof(ULONG); + RegCount*=(sizeof(DDR_SETTING)/sizeof(ULONG)); + + while(RegCount && !retval) + { + value = psDDRSetting->ulRegAddress ; + retval = wrmalt( Adapter, ul_ddr_setting_load_addr, &value, sizeof(value)); + ul_ddr_setting_load_addr+=sizeof(ULONG); + if(!retval) + { + if(bOverrideSelfRefresh && (psDDRSetting->ulRegAddress == 0x0F007018)) + { + value = (psDDRSetting->ulRegValue |(1<<8)); + if(STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr, + &value, sizeof(value))){ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"%s:%d\n", __FUNCTION__, __LINE__); + break; + } + } + else + { + value = psDDRSetting->ulRegValue; + + if(STATUS_SUCCESS != wrmalt(Adapter, ul_ddr_setting_load_addr , + &value, sizeof(value))){ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"%s:%d\n", __FUNCTION__, __LINE__); + break; + } + } + } + ul_ddr_setting_load_addr+=sizeof(ULONG); + RegCount--; + psDDRSetting++; + } + return retval; +} + +#endif + diff --git a/drivers/staging/bcm/DDRInit.h b/drivers/staging/bcm/DDRInit.h new file mode 100644 index 0000000..550e260 --- /dev/null +++ b/drivers/staging/bcm/DDRInit.h @@ -0,0 +1,9 @@ +#ifndef _DDR_INIT_H_ +#define _DDR_INIT_H_ + + + +int ddr_init(PMINI_ADAPTER psAdapter); +int download_ddr_settings(PMINI_ADAPTER psAdapter); + +#endif diff --git a/drivers/staging/bcm/Debug.c b/drivers/staging/bcm/Debug.c new file mode 100644 index 0000000..213f4bc --- /dev/null +++ b/drivers/staging/bcm/Debug.c @@ -0,0 +1,40 @@ +#include "headers.h" + +char *buff_dump_base[]={"DEC", "HEX", "OCT", "BIN" }; + +static UINT current_debug_level=BCM_SCREAM; + +int bcm_print_buffer( UINT debug_level, const char *function_name, + char *file_name, int line_number, unsigned char *buffer, int bufferlen, unsigned int base) +{ + if(debug_level>=current_debug_level) + { + int i=0; + printk("\n%s:%s:%d:Buffer dump of size 0x%x in the %s:\n", file_name, function_name, line_number, bufferlen, buff_dump_base[1]); + for(;i +#define NONE 0xFFFF + +typedef enum _BASE_TYPE +{ + BCM_BASE_TYPE_DEC, + BCM_BASE_TYPE_OCT, + BCM_BASE_TYPE_BIN, + BCM_BASE_TYPE_HEX, + BCM_BASE_TYPE_NONE, +} BASE_TYPE, *PBASE_TYPE; + +int bcm_print_buffer( UINT debug_level, const char *function_name, + char *file_name, int line_number, unsigned char *buffer, int bufferlen, BASE_TYPE base); + +#ifdef BCM_SHM_INTERFACE +#define CPE_VIRTUAL_ERROR_CODE_BASE_ADDR (0xBFC02E00 + 0x4C) +// ERROR codes for debugging +extern unsigned char u32ErrorCounter ; +#define ERROR_DEVICE_REMOVED 0x1 +#define ERROR_LEADER_LENGTH_ZERO 0x2 +#define ERROR_LEADER_LENGTH_CORRUPTED 0x3 +#define ERROR_NO_SKBUFF 0x4 + +#define ERROR_DL_MODULE 0xaa000000 +extern void CPE_ERROR_LOG(unsigned int module,unsigned int code); + +#endif + + + + +//-------------------------------------------------------------------------------- + +/* TYPE and SUBTYPE + * Define valid TYPE (or category or code-path, however you like to think of it) + * and SUBTYPE s. + * Type and SubType are treated as bitmasks. + */ +/*-----------------BEGIN TYPEs------------------------------------------*/ +#define DBG_TYPE_INITEXIT (1 << 0) // 1 +#define DBG_TYPE_TX (1 << 1) // 2 +#define DBG_TYPE_RX (1 << 2) // 4 +#define DBG_TYPE_OTHERS (1 << 3) // 8 +/*-----------------END TYPEs------------------------------------------*/ +#define NUMTYPES 4 // careful! + +/*-----------------BEGIN SUBTYPEs---------------------------------------*/ + +/*-SUBTYPEs for TX : TYPE is DBG_TYPE_TX -----// + Transmit.c ,Arp.c, LeakyBucket.c, And Qos.c + total 17 macros */ +// Transmit.c +#define TX 1 +#define MP_SEND (TX<<0) +#define NEXT_SEND (TX<<1) +#define TX_FIFO (TX<<2) +#define TX_CONTROL (TX<<3) + +// Arp.c +#define IP_ADDR (TX<<4) +#define ARP_REQ (TX<<5) +#define ARP_RESP (TX<<6) + +// dhcp.c +//#define DHCP TX +//#define DHCP_REQ (DHCP<<7) + +// Leakybucket.c +#define TOKEN_COUNTS (TX<<8) +#define CHECK_TOKENS (TX<<9) +#define TX_PACKETS (TX<<10) +#define TIMER (TX<<11) + +// Qos.c +#define QOS TX +#define QUEUE_INDEX (QOS<<12) +#define IPV4_DBG (QOS<<13) +#define IPV6_DBG (QOS<<14) +#define PRUNE_QUEUE (QOS<<15) +#define SEND_QUEUE (QOS<<16) + +//TX_Misc +#define TX_OSAL_DBG (TX<<17) + + +//--SUBTYPEs for ------INIT & EXIT--------------------- +/*------------ TYPE is DBG_TYPE_INITEXIT -----// +DriverEntry.c, bcmfwup.c, ChipDetectTask.c, HaltnReset.c, InterfaceDDR.c */ +#define MP 1 +#define DRV_ENTRY (MP<<0) +#define MP_INIT (MP<<1) +#define READ_REG (MP<<3) +#define DISPATCH (MP<<2) +#define CLAIM_ADAP (MP<<4) +#define REG_IO_PORT (MP<<5) +#define INIT_DISP (MP<<6) +#define RX_INIT (MP<<7) + + +//-SUBTYPEs for --RX---------------------------------- +//------------RX : TYPE is DBG_TYPE_RX -----// +// Receive.c +#define RX 1 +#define RX_DPC (RX<<0) +#define RX_CTRL (RX<<3) +#define RX_DATA (RX<<4) +#define MP_RETURN (RX<<1) +#define LINK_MSG (RX<<2) + + +//-SUBTYPEs for ----OTHER ROUTINES------------------ +//------------OTHERS : TYPE is DBG_TYPE_OTHER -----// +// HaltnReset,CheckForHang,PnP,Misc,CmHost +// total 12 macros +#define OTHERS 1 +// ??ISR.C + +#define ISR OTHERS +#define MP_DPC (ISR<<0) + +// HaltnReset.c +#define HALT OTHERS +#define MP_HALT (HALT<<1) +#define CHECK_HANG (HALT<<2) +#define MP_RESET (HALT<<3) +#define MP_SHUTDOWN (HALT<<4) + +// pnp.c +#define PNP OTHERS +#define MP_PNP (PNP<<5) + +// Misc.c +#define MISC OTHERS +#define DUMP_INFO (MISC<<6) +#define CLASSIFY (MISC<<7) +#define LINK_UP_MSG (MISC<<8) +#define CP_CTRL_PKT (MISC<<9) +#define DUMP_CONTROL (MISC<<10) +#define LED_DUMP_INFO (MISC<<11) + +// CmHost.c +#define CMHOST OTHERS + + +#define SERIAL (OTHERS<<12) +#define IDLE_MODE (OTHERS<<13) + +#define WRM (OTHERS<<14) +#define RDM (OTHERS<<15) + +// TODO - put PHS_SEND in Tx PHS_RECEIVE in Rx path ? +#define PHS_SEND (OTHERS<<16) +#define PHS_RECIEVE (OTHERS<<17) +#define PHS_MODULE (OTHERS<<18) + +#define INTF_INIT (OTHERS<<19) +#define INTF_ERR (OTHERS<<20) +#define INTF_WARN (OTHERS<<21) +#define INTF_NORM (OTHERS<<22) + +#define IRP_COMPLETION (OTHERS<<23) +#define SF_DESCRIPTOR_CNTS (OTHERS<<24) +#define PHS_DISPATCH (OTHERS << 25) +#define OSAL_DBG (OTHERS << 26) +#define NVM_RW (OTHERS << 27) + +#define HOST_MIBS (OTHERS << 28) +#define CONN_MSG (CMHOST << 29) +//#define OTHERS_MISC (OTHERS << 29) // ProcSupport.c +/*-----------------END SUBTYPEs------------------------------------------*/ + + +/* Debug level + * We have 8 debug levels, in (numerical) increasing order of verbosity. + * IMP: Currently implementing ONLY DBG_LVL_ALL , i.e. , all debug prints will + * appear (of course, iff global debug flag is ON and we match the Type and SubType). + * Finer granularity debug levels are currently not in use, although the feature exists. + * + * Another way to say this: + * All the debug prints currently have 'debug_level' set to DBG_LVL_ALL . + * You can compile-time change that to any of the below, if you wish to. However, as of now, there's + * no dynamic facility to have the userspace 'TestApp' set debug_level. Slated for future expansion. + */ +#define BCM_ALL 7 +#define BCM_LOW 6 +#define BCM_PRINT 5 +#define BCM_NORMAL 4 +#define BCM_MEDIUM 3 +#define BCM_SCREAM 2 +#define BCM_ERR 1 +/* Not meant for developer in debug prints. + * To be used to disable all prints by setting the DBG_LVL_CURR to this value */ +#define BCM_NONE 0 + +/* The current driver logging level. + * Everything at this level and (numerically) lower (meaning higher prio) + * is logged. +* Replace 'BCM_ALL' in the DBG_LVL_CURR macro with the logging level desired. + * For eg. to set the logging level to 'errors only' use: + * #define DBG_LVL_CURR (BCM_ERR) + */ + +#define DBG_LVL_CURR (BCM_ALL) +#define DBG_LVL_ALL BCM_ALL + +/*---Userspace mapping of Debug State. + * Delibrately matches that of the Windows driver.. + * The TestApp's ioctl passes this struct to us. + */ +typedef struct +{ + unsigned int Subtype, Type; + unsigned int OnOff; +// unsigned int debug_level; /* future expansion */ +} __attribute__((packed)) USER_BCM_DBG_STATE; + +//---Kernel-space mapping of Debug State +typedef struct _S_BCM_DEBUG_STATE { + UINT type; + /* A bitmap of 32 bits for Subtype per Type. + * Valid indexes in 'subtype' array are *only* 1,2,4 and 8, + * corresponding to valid Type values. Hence we use the 'Type' field + * as the index value, ignoring the array entries 0,3,5,6,7 ! + */ + UINT subtype[(NUMTYPES*2)+1]; + UINT debug_level; +} S_BCM_DEBUG_STATE; +/* Instantiated in the Adapter structure */ +/* We'll reuse the debug level parameter to include a bit (the MSB) to indicate whether or not + * we want the function's name printed. */ +#define DBG_NO_FUNC_PRINT 1 << 31 +#define DBG_LVL_BITMASK 0xFF + +//--- Only for direct printk's; "hidden" to API. +#define DBG_TYPE_PRINTK 3 +#define PRINTKS_ON 1 // "hidden" from API, set to 0 to turn off all printk's + +#define BCM_DEBUG_PRINT(Adapter, Type, SubType, dbg_level, string, args...) do { \ + if ((DBG_TYPE_PRINTK == Type) && (PRINTKS_ON)) { \ + printk ("%s:" string, __FUNCTION__, ##args); \ + printk("\n"); \ + } else if (!Adapter) \ + ; \ + else { \ + if (((dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level) && \ + ((Type & Adapter->stDebugState.type) && (SubType & Adapter->stDebugState.subtype[Type]))) { \ + if (dbg_level & DBG_NO_FUNC_PRINT) \ + printk (string, ##args); \ + else \ + { \ + printk ("%s:" string, __FUNCTION__, ##args); \ + printk("\n"); \ + } \ + } \ + } \ +} while (0) + +#define BCM_DEBUG_PRINT_BUFFER(Adapter, Type, SubType, dbg_level, buffer, bufferlen) do { \ + if ((DBG_TYPE_PRINTK == Type) && (PRINTKS_ON)) { \ + bcm_print_buffer( dbg_level, __FUNCTION__, __FILE__, __LINE__, buffer, bufferlen, BCM_BASE_TYPE_HEX); \ + } else if (!Adapter) \ + ; \ + else { \ + if (((dbg_level & DBG_LVL_BITMASK) <= Adapter->stDebugState.debug_level) && \ + ((Type & Adapter->stDebugState.type) && (SubType & Adapter->stDebugState.subtype[Type]))) { \ + if (dbg_level & DBG_NO_FUNC_PRINT) \ + bcm_print_buffer( dbg_level, NULL, NULL, __LINE__, buffer, bufferlen, BCM_BASE_TYPE_HEX); \ + else \ + bcm_print_buffer( dbg_level, __FUNCTION__, __FILE__, __LINE__, buffer, bufferlen, BCM_BASE_TYPE_HEX); \ + } \ + } \ + } while (0) + + +#define BCM_SHOW_DEBUG_BITMAP(Adapter) do { \ + int i; \ + for (i=0; i<(NUMTYPES*2)+1; i++) { \ + if ((i == 1) || (i == 2) || (i == 4) || (i == 8)) { \ + /* CAUTION! Forcefully turn on ALL debug paths and subpaths! \ + Adapter->stDebugState.subtype[i] = 0xffffffff; */ \ + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_PRINTK, 0, 0, "subtype[%d] = 0x%08x\n", \ + i, Adapter->stDebugState.subtype[i]); \ + } \ + } \ +} while (0) + +#endif + diff --git a/drivers/staging/bcm/HandleControlPacket.c b/drivers/staging/bcm/HandleControlPacket.c new file mode 100644 index 0000000..8499513 --- /dev/null +++ b/drivers/staging/bcm/HandleControlPacket.c @@ -0,0 +1,247 @@ +/** +@file HandleControlPacket.c +This file contains the routines to deal with +sending and receiving of control packets. +*/ +#include "headers.h" + +/** +When a control packet is received, analyze the +"status" and call appropriate response function. +Enqueue the control packet for Application. +@return None +*/ +VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, /**data); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "=====>"); + /* Get the Leader field */ + + switch(usStatus) + { + case CM_RESPONSES: // 0xA0 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "MAC Version Seems to be Non Multi-Classifier, rejected by Driver"); + HighPriorityMessage = TRUE ; + break; + case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP: + HighPriorityMessage = TRUE ; + if(Adapter->LinkStatus==LINKUP_DONE) + { + CmControlResponseMessage(Adapter,(skb->data +sizeof(USHORT))); + } + break; + case LINK_CONTROL_RESP: //0xA2 + case STATUS_RSP: //0xA1 + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"LINK_CONTROL_RESP"); + HighPriorityMessage = TRUE ; + LinkControlResponseMessage(Adapter,(skb->data + sizeof(USHORT))); + break; + case STATS_POINTER_RESP: //0xA6 + HighPriorityMessage = TRUE ; + StatisticsResponse(Adapter, (skb->data + sizeof(USHORT))); + break; + case IDLE_MODE_STATUS: //0xA3 + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"IDLE_MODE_STATUS Type Message Got from F/W"); + InterfaceIdleModeRespond(Adapter, (PUINT)(skb->data + + sizeof(USHORT))); + HighPriorityMessage = TRUE ; + break; + + case AUTH_SS_HOST_MSG: + HighPriorityMessage = TRUE ; + break; + + default: + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL,"Got Default Response"); + /* Let the Application Deal with This Packet */ + break; + } + + //Queue The Control Packet to The Application Queues + down(&Adapter->RxAppControlQueuelock); + + for (pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) + { + if(Adapter->device_removed) + { + break; + } + + drop_pkt_flag = TRUE ; + /* + There are cntrl msg from A0 to AC. It has been mapped to 0 to C bit in the cntrl mask. + Also, by default AD to BF has been masked to the rest of the bits... which wil be ON by default. + if mask bit is enable to particular pkt status, send it out to app else stop it. + */ + cntrl_msg_mask_bit = (usStatus & 0x1F); + //printk("\ninew msg mask bit which is disable in mask:%X", cntrl_msg_mask_bit); + if(pTarang->RxCntrlMsgBitMask & (1<AppCtrlQueueLen > MAX_APP_QUEUE_LEN) || + ((pTarang->AppCtrlQueueLen > MAX_APP_QUEUE_LEN/2) && (HighPriorityMessage == FALSE))) + { + /* + Assumption:- + 1. every tarang manages it own dropped pkt statitistics + 2. Total packet dropped per tarang will be equal to the sum of all types of dropped + pkt by that tarang only. + + */ + switch(*(PUSHORT)skb->data) + { + case CM_RESPONSES: + pTarang->stDroppedAppCntrlMsgs.cm_responses++; + break; + case CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP: + pTarang->stDroppedAppCntrlMsgs.cm_control_newdsx_multiclassifier_resp++; + break; + case LINK_CONTROL_RESP: + pTarang->stDroppedAppCntrlMsgs.link_control_resp++; + break; + case STATUS_RSP: + pTarang->stDroppedAppCntrlMsgs.status_rsp++; + break; + case STATS_POINTER_RESP: + pTarang->stDroppedAppCntrlMsgs.stats_pointer_resp++; + break; + case IDLE_MODE_STATUS: + pTarang->stDroppedAppCntrlMsgs.idle_mode_status++ ; + break; + case AUTH_SS_HOST_MSG: + pTarang->stDroppedAppCntrlMsgs.auth_ss_host_msg++ ; + break; + default: + pTarang->stDroppedAppCntrlMsgs.low_priority_message++ ; + break; + } + + continue; + } + + newPacket = skb_clone(skb, GFP_KERNEL); + if (!newPacket) + break; + ENQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail, + newPacket); + pTarang->AppCtrlQueueLen++; + } + up(&Adapter->RxAppControlQueuelock); + wake_up(&Adapter->process_read_wait_queue); + bcm_kfree_skb(skb); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "After wake_up_interruptible"); +} + +/** +@ingroup ctrl_pkt_functions +Thread to handle control pkt reception +*/ +int control_packet_handler (PMINI_ADAPTER Adapter /**< pointer to adapter object*/ + ) +{ + struct sk_buff *ctrl_packet= NULL; + unsigned long flags = 0; + //struct timeval tv ; + //int *puiBuffer = NULL ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Entering to make thread wait on control packet event!"); + while(1) + { + wait_event_interruptible(Adapter->process_rx_cntrlpkt, + atomic_read(&Adapter->cntrlpktCnt) || + Adapter->bWakeUpDevice || + kthread_should_stop() + ); + + + if(kthread_should_stop()) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Exiting \n"); + return 0; + } + if(TRUE == Adapter->bWakeUpDevice) + { + Adapter->bWakeUpDevice = FALSE; + if((FALSE == Adapter->bTriedToWakeUpFromlowPowerMode) && + ((TRUE == Adapter->IdleMode)|| (TRUE == Adapter->bShutStatus))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "Calling InterfaceAbortIdlemode\n"); + // Adapter->bTriedToWakeUpFromlowPowerMode = TRUE; + InterfaceIdleModeWakeup (Adapter); + } + continue; + } + + while(atomic_read(&Adapter->cntrlpktCnt)) + { + spin_lock_irqsave(&Adapter->control_queue_lock, flags); + ctrl_packet = Adapter->RxControlHead; + if(ctrl_packet) + { + DEQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail); +// Adapter->RxControlHead=ctrl_packet->next; + ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_packets++; + ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.rx_bytes+= + ((PLEADER)ctrl_packet->data)->PLength; + } + #if 0 //Idle mode debug profiling... + if(*(PUSHORT)ctrl_packet->data == IDLE_MODE_STATUS) + { + puiBuffer = (PUINT)(ctrl_packet->data +sizeof(USHORT)); + if((ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD)) + { + memset(&tv, 0, sizeof(tv)); + do_gettimeofday(&tv); + if((ntohl(*(puiBuffer+1)) == 0)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode Wake-up Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "IdleMode req Msg from f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); + } + } + else if((ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, CP_CTRL_PKT, DBG_LVL_ALL, "GOT IDLE_MODE_SF_UPDATE MSG at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); + } + } + #endif + + spin_unlock_irqrestore (&Adapter->control_queue_lock, flags); + handle_rx_control_packet(Adapter, ctrl_packet); + atomic_dec(&Adapter->cntrlpktCnt); + } + + SetUpTargetDsxBuffers(Adapter); + } + return STATUS_SUCCESS; +} + +INT flushAllAppQ() +{ + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + PPER_TARANG_DATA pTarang = NULL; + struct sk_buff *PacketToDrop = NULL; + for(pTarang = Adapter->pTarangs; pTarang; pTarang = pTarang->next) + { + while(pTarang->RxAppControlHead != NULL) + { + PacketToDrop=pTarang->RxAppControlHead; + DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail); + bcm_kfree_skb(PacketToDrop); + } + pTarang->AppCtrlQueueLen = 0; + //dropped contrl packet statistics also should be reset. + memset((PVOID)&pTarang->stDroppedAppCntrlMsgs, 0, sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); + + } + return STATUS_SUCCESS ; +} + + diff --git a/drivers/staging/bcm/HostMIBSInterface.h b/drivers/staging/bcm/HostMIBSInterface.h new file mode 100644 index 0000000..f17a4f1 --- /dev/null +++ b/drivers/staging/bcm/HostMIBSInterface.h @@ -0,0 +1,230 @@ + + +#ifndef _HOST_MIBSINTERFACE_H +#define _HOST_MIBSINTERFACE_H + +/* + * Copyright (c) 2007 Beceem Communications Pvt. Ltd + * File Name: HostMIBSInterface.h + * Abstract: This file contains DS used by the Host to update the Host + * statistics used for the MIBS. + */ + +#define MIBS_MAX_CLASSIFIERS 100 +#define MIBS_MAX_PHSRULES 100 +#define MIBS_MAX_SERVICEFLOWS 17 +#define MIBS_MAX_IP_RANGE_LENGTH 4 +#define MIBS_MAX_PORT_RANGE 4 +#define MIBS_MAX_PROTOCOL_LENGTH 32 +#define MIBS_MAX_PHS_LENGTHS 255 +#define MIBS_IPV6_ADDRESS_SIZEINBYTES 0x10 +#define MIBS_IP_LENGTH_OF_ADDRESS 4 +#define MIBS_MAX_HIST_ENTRIES 12 +#define MIBS_PKTSIZEHIST_RANGE 128 + +typedef union _U_MIBS_IP_ADDRESS +{ + struct + { + //Source Ip Address Range + ULONG ulIpv4Addr[MIBS_MAX_IP_RANGE_LENGTH]; + //Source Ip Mask Address Range + ULONG ulIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH]; + }; + struct + { + //Source Ip Address Range + ULONG ulIpv6Addr[MIBS_MAX_IP_RANGE_LENGTH * 4]; + //Source Ip Mask Address Range + ULONG ulIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * 4]; + + }; + struct + { + UCHAR ucIpv4Address[MIBS_MAX_IP_RANGE_LENGTH * + MIBS_IP_LENGTH_OF_ADDRESS]; + UCHAR ucIpv4Mask[MIBS_MAX_IP_RANGE_LENGTH * + MIBS_IP_LENGTH_OF_ADDRESS]; + }; + struct + { + UCHAR ucIpv6Address[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES]; + UCHAR ucIpv6Mask[MIBS_MAX_IP_RANGE_LENGTH * MIBS_IPV6_ADDRESS_SIZEINBYTES]; + }; +}U_MIBS_IP_ADDRESS; + + +typedef struct _S_MIBS_HOST_INFO +{ + ULONG64 GoodTransmits; + ULONG64 GoodReceives; + // this to keep track of the Tx and Rx MailBox Registers. + ULONG NumDesUsed; + ULONG CurrNumFreeDesc; + ULONG PrevNumFreeDesc; + // to keep track the no of byte recieved + ULONG PrevNumRcevBytes; + ULONG CurrNumRcevBytes; + + /* QOS Related */ + ULONG BEBucketSize; + ULONG rtPSBucketSize; + ULONG LastTxQueueIndex; + BOOLEAN TxOutofDescriptors; + BOOLEAN TimerActive; + UINT32 u32TotalDSD; + UINT32 aTxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; + UINT32 aRxPktSizeHist[MIBS_MAX_HIST_ENTRIES]; +}S_MIBS_HOST_INFO; + +typedef struct _S_MIBS_CLASSIFIER_RULE +{ + ULONG ulSFID; + UCHAR ucReserved[2]; + B_UINT16 uiClassifierRuleIndex; + BOOLEAN bUsed; + USHORT usVCID_Value; + // This field detemines the Classifier Priority + B_UINT8 u8ClassifierRulePriority; + U_MIBS_IP_ADDRESS stSrcIpAddress; + /*IP Source Address Length*/ + UCHAR ucIPSourceAddressLength; + + U_MIBS_IP_ADDRESS stDestIpAddress; + /* IP Destination Address Length */ + UCHAR ucIPDestinationAddressLength; + UCHAR ucIPTypeOfServiceLength;//Type of service Length + UCHAR ucTosLow;//Tos Low + UCHAR ucTosHigh;//Tos High + UCHAR ucTosMask;//Tos Mask + UCHAR ucProtocolLength;//protocol Length + UCHAR ucProtocol[MIBS_MAX_PROTOCOL_LENGTH];//protocol Length + USHORT usSrcPortRangeLo[MIBS_MAX_PORT_RANGE]; + USHORT usSrcPortRangeHi[MIBS_MAX_PORT_RANGE]; + UCHAR ucSrcPortRangeLength; + USHORT usDestPortRangeLo[MIBS_MAX_PORT_RANGE]; + USHORT usDestPortRangeHi[MIBS_MAX_PORT_RANGE]; + UCHAR ucDestPortRangeLength; + BOOLEAN bProtocolValid; + BOOLEAN bTOSValid; + BOOLEAN bDestIpValid; + BOOLEAN bSrcIpValid; + UCHAR ucDirection; + BOOLEAN bIpv6Protocol; + UINT32 u32PHSRuleID; +}S_MIBS_CLASSIFIER_RULE; + + +typedef struct _S_MIBS_PHS_RULE +{ + ULONG ulSFID; + /// brief 8bit PHSI Of The Service Flow + B_UINT8 u8PHSI; + /// brief PHSF Of The Service Flow + B_UINT8 u8PHSFLength; + B_UINT8 u8PHSF[MIBS_MAX_PHS_LENGTHS]; + /// brief PHSM Of The Service Flow + B_UINT8 u8PHSMLength; + B_UINT8 u8PHSM[MIBS_MAX_PHS_LENGTHS]; + /// brief 8bit PHSS Of The Service Flow + B_UINT8 u8PHSS; + /// brief 8bit PHSV Of The Service Flow + B_UINT8 u8PHSV; + // Reserved bytes are 5, so that it is similar to S_PHS_RULE structure. + B_UINT8 reserved[5]; + + LONG PHSModifiedBytes; + ULONG PHSModifiedNumPackets; + ULONG PHSErrorNumPackets; +}S_MIBS_PHS_RULE; + +typedef struct _S_MIBS_EXTSERVICEFLOW_PARAMETERS +{ + UINT32 wmanIfSfid; + UINT32 wmanIfCmnCpsSfState; + UINT32 wmanIfCmnCpsMaxSustainedRate; + UINT32 wmanIfCmnCpsMaxTrafficBurst; + UINT32 wmanIfCmnCpsMinReservedRate; + UINT32 wmanIfCmnCpsToleratedJitter; + UINT32 wmanIfCmnCpsMaxLatency; + UINT32 wmanIfCmnCpsFixedVsVariableSduInd; + UINT32 wmanIfCmnCpsSduSize; + UINT32 wmanIfCmnCpsSfSchedulingType; + UINT32 wmanIfCmnCpsArqEnable; + UINT32 wmanIfCmnCpsArqWindowSize; + UINT32 wmanIfCmnCpsArqBlockLifetime; + UINT32 wmanIfCmnCpsArqSyncLossTimeout; + UINT32 wmanIfCmnCpsArqDeliverInOrder; + UINT32 wmanIfCmnCpsArqRxPurgeTimeout; + UINT32 wmanIfCmnCpsArqBlockSize; + UINT32 wmanIfCmnCpsMinRsvdTolerableRate; + UINT32 wmanIfCmnCpsReqTxPolicy; + UINT32 wmanIfCmnSfCsSpecification; + UINT32 wmanIfCmnCpsTargetSaid; + +}S_MIBS_EXTSERVICEFLOW_PARAMETERS; + + +typedef struct _S_MIBS_SERVICEFLOW_TABLE +{ + //classification extension Rule + ULONG ulSFID; + USHORT usVCID_Value; + UINT uiThreshold; + // This field determines the priority of the SF Queues + B_UINT8 u8TrafficPriority; + + BOOLEAN bValid; + BOOLEAN bActive; + BOOLEAN bActivateRequestSent; + //BE or rtPS + B_UINT8 u8QueueType; + //maximum size of the bucket for the queue + UINT uiMaxBucketSize; + UINT uiCurrentQueueDepthOnTarget; + UINT uiCurrentBytesOnHost; + UINT uiCurrentPacketsOnHost; + UINT uiDroppedCountBytes; + UINT uiDroppedCountPackets; + UINT uiSentBytes; + UINT uiSentPackets; + UINT uiCurrentDrainRate; + UINT uiThisPeriodSentBytes; + LARGE_INTEGER liDrainCalculated; + UINT uiCurrentTokenCount; + LARGE_INTEGER liLastUpdateTokenAt; + UINT uiMaxAllowedRate; + UINT NumOfPacketsSent; + UCHAR ucDirection; + USHORT usCID; + S_MIBS_EXTSERVICEFLOW_PARAMETERS stMibsExtServiceFlowTable; + UINT uiCurrentRxRate; + UINT uiThisPeriodRxBytes; + UINT uiTotalRxBytes; + UINT uiTotalTxBytes; +}S_MIBS_SERVICEFLOW_TABLE; + +typedef struct _S_MIBS_DROPPED_APP_CNTRL_MESSAGES +{ + ULONG cm_responses; + ULONG cm_control_newdsx_multiclassifier_resp; + ULONG link_control_resp; + ULONG status_rsp; + ULONG stats_pointer_resp; + ULONG idle_mode_status; + ULONG auth_ss_host_msg; + ULONG low_priority_message; + +}S_MIBS_DROPPED_APP_CNTRL_MESSAGES; + +typedef struct _S_MIBS_HOST_STATS_MIBS +{ + S_MIBS_HOST_INFO stHostInfo; + S_MIBS_CLASSIFIER_RULE astClassifierTable[MIBS_MAX_CLASSIFIERS]; + S_MIBS_SERVICEFLOW_TABLE astSFtable[MIBS_MAX_SERVICEFLOWS]; + S_MIBS_PHS_RULE astPhsRulesTable[MIBS_MAX_PHSRULES]; + S_MIBS_DROPPED_APP_CNTRL_MESSAGES stDroppedAppCntrlMsgs; +}S_MIBS_HOST_STATS_MIBS; +#endif + + diff --git a/drivers/staging/bcm/HostMibs.h b/drivers/staging/bcm/HostMibs.h new file mode 100644 index 0000000..28a5783 --- /dev/null +++ b/drivers/staging/bcm/HostMibs.h @@ -0,0 +1,7 @@ +#ifndef _HOST_MIBS_H +#define _HOST_MIBS_H + +INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, + PVOID ioBuffer, + ULONG inputBufferLength); +#endif diff --git a/drivers/staging/bcm/IPv6Protocol.c b/drivers/staging/bcm/IPv6Protocol.c new file mode 100644 index 0000000..cb4ca9a --- /dev/null +++ b/drivers/staging/bcm/IPv6Protocol.c @@ -0,0 +1,400 @@ +#include "headers.h" + +UCHAR * GetNextIPV6ChainedHeader(UCHAR **ppucPayload,UCHAR *pucNextHeader,BOOLEAN *bParseDone,USHORT *pusPayloadLength) +{ + UCHAR *pucRetHeaderPtr = NULL; + UCHAR *pucPayloadPtr = NULL; + USHORT usNextHeaderOffset = 0 ; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + if((NULL == ppucPayload) || (*pusPayloadLength == 0) || (*bParseDone)) + { + *bParseDone = TRUE; + return NULL; + + } + + pucRetHeaderPtr = *ppucPayload; + pucPayloadPtr = *ppucPayload; + + if(!pucRetHeaderPtr || !pucPayloadPtr) + { + *bParseDone = TRUE; + return NULL; + } + + //Get the Nextt Header Type + *bParseDone = FALSE; + + + + switch(*pucNextHeader) + { + case IPV6HDR_TYPE_HOPBYHOP: + { + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 HopByHop Header"); + usNextHeaderOffset+=sizeof(IPV6HopByHopOptionsHeader); + } + break; + + case IPV6HDR_TYPE_ROUTING: + { + IPV6RoutingHeader *pstIpv6RoutingHeader; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Routing Header"); + pstIpv6RoutingHeader = (IPV6RoutingHeader *)pucPayloadPtr; + usNextHeaderOffset += sizeof(IPV6RoutingHeader); + usNextHeaderOffset += pstIpv6RoutingHeader->ucNumAddresses * IPV6_ADDRESS_SIZEINBYTES; + + } + break; + case IPV6HDR_TYPE_FRAGMENTATION: + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Fragmentation Header"); + usNextHeaderOffset+= sizeof(IPV6FragmentHeader); + + } + break; + case IPV6HDR_TYPE_DESTOPTS: + { + IPV6DestOptionsHeader *pstIpv6DestOptsHdr = (IPV6DestOptionsHeader *)pucPayloadPtr; + int nTotalOptions = pstIpv6DestOptsHdr->ucHdrExtLen; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 DestOpts Header Header"); + usNextHeaderOffset+= sizeof(IPV6DestOptionsHeader); + usNextHeaderOffset+= nTotalOptions * IPV6_DESTOPTS_HDR_OPTIONSIZE ; + + } + break; + case IPV6HDR_TYPE_AUTHENTICATION: + { + IPV6AuthenticationHeader *pstIpv6AuthHdr = (IPV6AuthenticationHeader *)pucPayloadPtr; + int nHdrLen = pstIpv6AuthHdr->ucLength; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Authentication Header"); + usNextHeaderOffset+= nHdrLen * 4; + } + break; + case IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD: + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Encrypted Security Payload Header"); + *bParseDone = TRUE; + + } + break; + case IPV6_ICMP_HDR_TYPE: + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " ICMP Header"); + *bParseDone = TRUE; + } + break; + case TCP_HEADER_TYPE: + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nTCP Header"); + *bParseDone = TRUE; + } + break; + case UDP_HEADER_TYPE: + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nUDP Header"); + *bParseDone = TRUE; + } + break; + default : + { + *bParseDone = TRUE; + + } + break; + + + } + + if(*bParseDone == FALSE) + { + if(*pusPayloadLength <= usNextHeaderOffset) + { + *bParseDone = TRUE; + } + else + { + *pucNextHeader = *pucPayloadPtr; + pucPayloadPtr+=usNextHeaderOffset; + (*pusPayloadLength)-=usNextHeaderOffset; + } + + } + + + + *ppucPayload = pucPayloadPtr; + return pucRetHeaderPtr; +} + + +UCHAR GetIpv6ProtocolPorts(UCHAR *pucPayload,USHORT *pusSrcPort,USHORT *pusDestPort,USHORT usPayloadLength,UCHAR ucNextHeader) +{ + UCHAR *pIpv6HdrScanContext = pucPayload; + BOOLEAN bDone = FALSE; + UCHAR ucHeaderType =0; + UCHAR *pucNextHeader = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + if( !pucPayload || (usPayloadLength == 0)) + { + return 0; + } + + *pusSrcPort = *pusDestPort = 0; + ucHeaderType = ucNextHeader; + while(!bDone) + { + pucNextHeader = GetNextIPV6ChainedHeader(&pIpv6HdrScanContext,&ucHeaderType,&bDone,&usPayloadLength); + if(bDone) + { + if((ucHeaderType==TCP_HEADER_TYPE) || (ucHeaderType == UDP_HEADER_TYPE)) + { + *pusSrcPort=*((PUSHORT)(pucNextHeader)); + *pusDestPort=*((PUSHORT)(pucNextHeader+2)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, " \nProtocol Ports - Src Port :0x%x Dest Port : 0x%x",ntohs(*pusSrcPort),ntohs(*pusDestPort)); + } + break; + + } + } + return ucHeaderType; +} + + + +USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */ + PVOID pcIpHeader, /**\n"); + + pstIpv6Header = (IPV6Header *)pcIpHeader; + + DumpIpv6Header(pstIpv6Header); + + //Try to get the next higher layer protocol and the Ports Nos if TCP or UDP + ucNextProtocolAboveIP = GetIpv6ProtocolPorts((UCHAR *)(pcIpHeader + sizeof(IPV6Header)), + &ushSrcPort, + &ushDestPort, + pstIpv6Header->usPayloadLength, + pstIpv6Header->ucNextHeader); + + do + { + if(0 == pstClassifierRule->ucDirection) + { + //cannot be processed for classification. + // it is a down link connection + break; + } + + if(!pstClassifierRule->bIpv6Protocol) + { + //We are looking for Ipv6 Classifiers . Lets ignore this classifier and try the next one. + break; + } + + bClassificationSucceed=MatchSrcIpv6Address(pstClassifierRule,pstIpv6Header); + if(!bClassificationSucceed) + break; + + bClassificationSucceed=MatchDestIpv6Address(pstClassifierRule,pstIpv6Header); + if(!bClassificationSucceed) + break; + + //Match the protocol type.For IPv6 the next protocol at end of Chain of IPv6 prot headers + bClassificationSucceed=MatchProtocol(pstClassifierRule,ucNextProtocolAboveIP); + if(!bClassificationSucceed) + break; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Protocol Matched"); + + if((ucNextProtocolAboveIP == TCP_HEADER_TYPE) || (ucNextProtocolAboveIP == UDP_HEADER_TYPE)) + { + //Match Src Port + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Source Port:%x\n",ntohs(ushSrcPort)); + bClassificationSucceed=MatchSrcPort(pstClassifierRule,ntohs(ushSrcPort)); + if(!bClassificationSucceed) + break; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Src Port Matched"); + + //Match Dest Port + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Destination Port:%x\n",ntohs(ushDestPort)); + bClassificationSucceed=MatchDestPort(pstClassifierRule,ntohs(ushDestPort)); + if(!bClassificationSucceed) + break; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\nIPv6 Dest Port Matched"); + } + }while(0); + + if(TRUE==bClassificationSucceed) + { + INT iMatchedSFQueueIndex = 0; + iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID); + if(iMatchedSFQueueIndex >= NO_OF_QUEUES) + { + bClassificationSucceed = FALSE; + } + else + { + if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive) + { + bClassificationSucceed = FALSE; + } + } + } + + return bClassificationSucceed; +} + + +BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) +{ + UINT uiLoopIndex=0; + UINT uiIpv6AddIndex=0; + UINT uiIpv6AddrNoLongWords = 4; + ULONG aulSrcIP[4]; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + /* + //This is the no. of Src Addresses ie Range of IP Addresses contained + //in the classifier rule for which we need to match + */ + UINT uiCountIPSrcAddresses = (UINT)pstClassifierRule->ucIPSourceAddressLength; + + + if(0 == uiCountIPSrcAddresses) + return TRUE; + + + //First Convert the Ip Address in the packet to Host Endian order + for(uiIpv6AddIndex=0;uiIpv6AddIndexulSrcIpAddress[uiIpv6AddIndex]); + } + + for(uiLoopIndex=0;uiLoopIndexstSrcIpAddress.ulIpv6Mask[uiLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Classifier Rule : \n"); + DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex]); + + for(uiIpv6AddIndex=0;uiIpv6AddIndexstSrcIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulSrcIP[uiIpv6AddIndex]) + != pstClassifierRule->stSrcIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) + { + //Match failed for current Ipv6 Address.Try next Ipv6 Address + break; + } + + if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) + { + //Match Found + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Src Ip Address Matched\n"); + return TRUE; + } + } + } + return FALSE; +} + +BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header) +{ + UINT uiLoopIndex=0; + UINT uiIpv6AddIndex=0; + UINT uiIpv6AddrNoLongWords = 4; + ULONG aulDestIP[4]; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + /* + //This is the no. of Destination Addresses ie Range of IP Addresses contained + //in the classifier rule for which we need to match + */ + UINT uiCountIPDestinationAddresses = (UINT)pstClassifierRule->ucIPDestinationAddressLength; + + + if(0 == uiCountIPDestinationAddresses) + return TRUE; + + + //First Convert the Ip Address in the packet to Host Endian order + for(uiIpv6AddIndex=0;uiIpv6AddIndexulDestIpAddress[uiIpv6AddIndex]); + } + + for(uiLoopIndex=0;uiLoopIndexstDestIpAddress.ulIpv6Mask[uiLoopIndex]); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Classifier Rule : \n"); + DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex]); + + for(uiIpv6AddIndex=0;uiIpv6AddIndexstDestIpAddress.ulIpv6Mask[uiLoopIndex+uiIpv6AddIndex] & aulDestIP[uiIpv6AddIndex]) + != pstClassifierRule->stDestIpAddress.ulIpv6Addr[uiLoopIndex+uiIpv6AddIndex]) + { + //Match failed for current Ipv6 Address.Try next Ipv6 Address + break; + } + + if(uiIpv6AddIndex == uiIpv6AddrNoLongWords-1) + { + //Match Found + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Ipv6 Destination Ip Address Matched\n"); + return TRUE; + } + } + } + return FALSE; + +} + +VOID DumpIpv6Address(ULONG *puIpv6Address) +{ + UINT uiIpv6AddrNoLongWords = 4; + UINT uiIpv6AddIndex=0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + for(uiIpv6AddIndex=0;uiIpv6AddIndexucVersionPrio & 0xf0; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Version : %x \n",ucVersion); + ucPrio = pstIpv6Header->ucVersionPrio & 0x0f; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Priority : %x \n",ucPrio); + //BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Flow Label : %x \n",(pstIpv6Header->ucVersionPrio &0xf0); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Payload Length : %x \n",ntohs(pstIpv6Header->usPayloadLength)); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Next Header : %x \n",pstIpv6Header->ucNextHeader); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Hop Limit : %x \n",pstIpv6Header->ucHopLimit); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Src Address :\n"); + DumpIpv6Address(pstIpv6Header->ulSrcIpAddress); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "Dest Address :\n"); + DumpIpv6Address(pstIpv6Header->ulDestIpAddress); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "----Ipv6 Header End---"); + + +} diff --git a/drivers/staging/bcm/IPv6ProtocolHdr.h b/drivers/staging/bcm/IPv6ProtocolHdr.h new file mode 100644 index 0000000..b93f790 --- /dev/null +++ b/drivers/staging/bcm/IPv6ProtocolHdr.h @@ -0,0 +1,119 @@ +#ifndef _IPV6_PROTOCOL_DEFINES_ +#define _IPV6_PROTOCOL_DEFINES_ + + +#define IPV6HDR_TYPE_HOPBYHOP 0x0 +#define IPV6HDR_TYPE_ROUTING 0x2B +#define IPV6HDR_TYPE_FRAGMENTATION 0x2C +#define IPV6HDR_TYPE_DESTOPTS 0x3c +#define IPV6HDR_TYPE_AUTHENTICATION 0x33 +#define IPV6HDR_TYPE_ENCRYPTEDSECURITYPAYLOAD 0x34 +#define MASK_IPV6_CS_SPEC 0x2 + + +#define TCP_HEADER_TYPE 0x6 +#define UDP_HEADER_TYPE 0x11 +#define IPV6_ICMP_HDR_TYPE 0x2 +#define IPV6_FLOWLABEL_BITOFFSET 9 + +#define IPV6_MAX_CHAINEDHDR_BUFFBYTES 0x64 +/* +// Size of Dest Options field of Destinations Options Header +// in bytes. +*/ +#define IPV6_DESTOPTS_HDR_OPTIONSIZE 0x8 + +//typedef unsigned char UCHAR; +//typedef unsigned short USHORT; +//typedef unsigned long int ULONG; + +typedef struct IPV6HeaderFormatTag +{ + UCHAR ucVersionPrio; + UCHAR aucFlowLabel[3]; + USHORT usPayloadLength; + UCHAR ucNextHeader; + UCHAR ucHopLimit; + ULONG ulSrcIpAddress[4]; + ULONG ulDestIpAddress[4]; +}IPV6Header; + +typedef struct IPV6RoutingHeaderFormatTag +{ + UCHAR ucNextHeader; + UCHAR ucRoutingType; + UCHAR ucNumAddresses; + UCHAR ucNextAddress; + ULONG ulReserved; + //UCHAR aucAddressList[0]; + +}IPV6RoutingHeader; + +typedef struct IPV6FragmentHeaderFormatTag +{ + UCHAR ucNextHeader; + UCHAR ucReserved; + USHORT usFragmentOffset; + ULONG ulIdentification; +}IPV6FragmentHeader; + +typedef struct IPV6DestOptionsHeaderFormatTag +{ + UCHAR ucNextHeader; + UCHAR ucHdrExtLen; + UCHAR ucDestOptions[6]; + //UCHAR udExtDestOptions[0]; +}IPV6DestOptionsHeader; + +typedef struct IPV6HopByHopOptionsHeaderFormatTag +{ + UCHAR ucNextHeader; + UCHAR ucMisc[3]; + ULONG ulJumboPayloadLen; +}IPV6HopByHopOptionsHeader; + +typedef struct IPV6AuthenticationHeaderFormatTag +{ + UCHAR ucNextHeader; + UCHAR ucLength; + USHORT usReserved; + ULONG ulSecurityParametersIndex; + //UCHAR ucAuthenticationData[0]; + +}IPV6AuthenticationHeader; + +typedef struct IPV6IcmpHeaderFormatTag +{ + UCHAR ucType; + UCHAR ucCode; + USHORT usChecksum; + //UCHAR ucIcmpMsg[0]; + +}IPV6IcmpHeader; + +typedef enum _E_IPADDR_CONTEXT +{ + eSrcIpAddress, + eDestIpAddress + +}E_IPADDR_CONTEXT; + + + +//Function Prototypes +BOOLEAN MatchSrcIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); +BOOLEAN MatchDestIpv6Address(S_CLASSIFIER_RULE *pstClassifierRule,IPV6Header *pstIpv6Header); + +USHORT IpVersion6(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */ + PVOID pcIpHeader, /**psAdapter; + + buff=(PCHAR)kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); + if(!buff) + { + return -ENOMEM; + } + while(1) + { + oldfs=get_fs(); set_fs(get_ds()); + len=vfs_read(flp, buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos); + set_fs(oldfs); + if(len<=0) + { + if(len<0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0"); + errno=len; + } + else + { + errno = 0; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!"); + } + break; + } + //BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, buff, MAX_TRANSFER_CTRL_BYTE_USB); + errno = InterfaceWRM(psIntfAdapter, on_chip_loc, buff, len) ; + if(errno) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "WRM Failed! status: %d", errno); + break; + + } + on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB; + }/* End of for(;;)*/ + + bcm_kfree(buff); + return errno; +} + +int InterfaceFileReadbackFromChip( PVOID arg, + struct file *flp, + unsigned int on_chip_loc) +{ + char *buff=NULL, *buff_readback=NULL; + unsigned int reg=0; + mm_segment_t oldfs={0}; + int errno=0, len=0, is_config_file = 0; + loff_t pos=0; + static int fw_down = 0; + INT Status = STATUS_SUCCESS; + PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; + + buff=(PCHAR)kmalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_DMA); + buff_readback=(PCHAR)kmalloc(MAX_TRANSFER_CTRL_BYTE_USB , GFP_DMA); + if(!buff || !buff_readback) + { + bcm_kfree(buff); + bcm_kfree(buff_readback); + + return -ENOMEM; + } + + is_config_file = (on_chip_loc == CONFIG_BEGIN_ADDR)? 1:0; + + memset(buff_readback, 0, MAX_TRANSFER_CTRL_BYTE_USB); + memset(buff, 0, MAX_TRANSFER_CTRL_BYTE_USB); + while(1) + { + oldfs=get_fs(); set_fs(get_ds()); + len=vfs_read(flp, buff, MAX_TRANSFER_CTRL_BYTE_USB, &pos); + set_fs(oldfs); + fw_down++; + if(len<=0) + { + if(len<0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len < 0"); + errno=len; + } + else + { + errno = 0; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got end of file!"); + } + break; + } + + + Status = InterfaceRDM(psIntfAdapter, on_chip_loc, buff_readback, len); + if(Status) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "RDM of len %d Failed! %d", len, reg); + goto exit; + } + reg++; + if((len-sizeof(unsigned int))<4) + { + if(memcmp(buff_readback, buff, len)) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT,DBG_LVL_ALL,"Length is: %d",len); + Status = -EIO; + goto exit; + } + } + else + { + len-=4; + while(len) + { + if(*(unsigned int*)&buff_readback[len] != *(unsigned int *)&buff[len]) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper %d", fw_down); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&buff_readback[len]); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len); + Status = -EIO; + goto exit; + } + len-=4; + } + } + on_chip_loc+=MAX_TRANSFER_CTRL_BYTE_USB; + }/* End of while(1)*/ +exit: + bcm_kfree(buff); + bcm_kfree(buff_readback); + return Status; +} + +static int bcm_download_config_file(PMINI_ADAPTER Adapter, + FIRMWARE_INFO *psFwInfo) +{ + int retval = STATUS_SUCCESS; + B_UINT32 value = 0; + + if(Adapter->pstargetparams == NULL) + { + if((Adapter->pstargetparams = + kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL) + { + return -ENOMEM; + } + } + if(psFwInfo->u32FirmwareLength != sizeof(STARGETPARAMS)) + { + return -EIO; + } + retval = copy_from_user(Adapter->pstargetparams, + psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); + if(retval) + { + bcm_kfree (Adapter->pstargetparams); + Adapter->pstargetparams = NULL; + return retval; + } + /* Parse the structure and then Download the Firmware */ + beceem_parse_target_struct(Adapter); + + //Initializing the NVM. + BcmInitNVM(Adapter); + + retval = InitLedSettings (Adapter); + + if(retval) + { + BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "INIT LED Failed\n"); + return retval; + } + + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->LEDInfo.bLedInitDone = FALSE; + Adapter->DriverState = DRIVER_INIT; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = FW_DOWNLOAD; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + + /* Initialize the DDR Controller */ + retval = ddr_init(Adapter); + if(retval) + { + BCM_DEBUG_PRINT (Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Init Failed\n"); + return retval; + } + + value = 0; + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); + + if(Adapter->eNVMType == NVM_FLASH) + { + retval = PropagateCalParamsFromFlashToMemory(Adapter); + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"propagaion of cal param failed with status :%d", retval); + return retval; + } + } + + + retval =buffDnldVerify(Adapter,(PUCHAR)Adapter->pstargetparams,sizeof(STARGETPARAMS),CONFIG_BEGIN_ADDR); + + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "configuration file not downloaded properly"); + } + else + Adapter->bCfgDownloaded = TRUE; + + + return retval; +} +#if 0 +static int bcm_download_buffer(PMINI_ADAPTER Adapter, + unsigned char *mappedbuffer, unsigned int u32FirmwareLength, + unsigned long u32StartingAddress) +{ + char *buff=NULL; + unsigned int len = 0; + int retval = STATUS_SUCCESS; + buff = kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); + + len = u32FirmwareLength; + + while(u32FirmwareLength) + { + len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); + if(STATUS_SUCCESS != (retval = copy_from_user(buff, + (unsigned char *)mappedbuffer, len))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copy_from_user failed\n"); + break; + } + retval = wrm (Adapter, u32StartingAddress, buff, len); + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed\n"); + break; + } + u32StartingAddress += len; + u32FirmwareLength -= len; + mappedbuffer +=len; + } + bcm_kfree(buff); + return retval; +} +#endif +static int bcm_compare_buff_contents(unsigned char *readbackbuff, + unsigned char *buff,unsigned int len) +{ + int retval = STATUS_SUCCESS; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + if((len-sizeof(unsigned int))<4) + { + if(memcmp(readbackbuff , buff, len)) + { + retval=-EINVAL; + } + } + else + { + len-=4; + while(len) + { + if(*(unsigned int*)&readbackbuff[len] != + *(unsigned int *)&buff[len]) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Firmware Download is not proper"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Val from Binary %x, Val From Read Back %x ", *(unsigned int *)&buff[len], *(unsigned int*)&readbackbuff[len]); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "len =%x!!!", len); + retval=-EINVAL; + break; + } + len-=4; + } + } + return retval; +} +#if 0 +static int bcm_buffer_readback(PMINI_ADAPTER Adapter, + unsigned char *mappedbuffer, unsigned int u32FirmwareLength, + unsigned long u32StartingAddress) +{ + unsigned char *buff = NULL; + unsigned char *readbackbuff = NULL; + unsigned int len = u32FirmwareLength; + int retval = STATUS_SUCCESS; + + buff=(unsigned char *)kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, GFP_KERNEL); + if(NULL == buff) + return -ENOMEM; + readbackbuff = (unsigned char *)kzalloc(MAX_TRANSFER_CTRL_BYTE_USB, + GFP_KERNEL); + if(NULL == readbackbuff) + { + bcm_kfree(buff); + return -ENOMEM; + } + while (u32FirmwareLength && !retval) + { + len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); + + /* read from the appl buff and then read from the target, compare */ + if(STATUS_SUCCESS != (retval = copy_from_user(buff, + (unsigned char *)mappedbuffer, len))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copy_from_user failed\n"); + break; + } + retval = rdm (Adapter, u32StartingAddress, readbackbuff, len); + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed\n"); + break; + } + + if (STATUS_SUCCESS != + (retval = bcm_compare_buff_contents (readbackbuff, buff, len))) + { + break; + } + u32StartingAddress += len; + u32FirmwareLength -= len; + mappedbuffer +=len; + }/* end of while (u32FirmwareLength && !retval) */ + bcm_kfree(buff); + bcm_kfree(readbackbuff); + return retval; +} +#endif +int bcm_ioctl_fw_download(PMINI_ADAPTER Adapter, FIRMWARE_INFO *psFwInfo) +{ + int retval = STATUS_SUCCESS; + PUCHAR buff = NULL; + + /* Config File is needed for the Driver to download the Config file and + Firmware. Check for the Config file to be first to be sent from the + Application + */ + atomic_set (&Adapter->uiMBupdate, FALSE); + if(!Adapter->bCfgDownloaded && + psFwInfo->u32StartingAddress != CONFIG_BEGIN_ADDR) + { + /*Can't Download Firmware.*/ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Download the config File first\n"); + return -EINVAL; + } + + /* If Config File, Finish the DDR Settings and then Download CFG File */ + if(psFwInfo->u32StartingAddress == CONFIG_BEGIN_ADDR) + { + retval = bcm_download_config_file (Adapter, psFwInfo); + } + else + { + + buff = (PUCHAR)kzalloc(psFwInfo->u32FirmwareLength,GFP_KERNEL); + if(buff==NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Failed in allocation memory"); + return -ENOMEM; + } + retval = copy_from_user(buff,(PUCHAR)psFwInfo->pvMappedFirmwareAddress, psFwInfo->u32FirmwareLength); + if(retval != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "copying buffer from user space failed"); + goto error ; + } + + #if 0 + retval = bcm_download_buffer(Adapter, + (unsigned char *)psFwInfo->pvMappedFirmwareAddress, + psFwInfo->u32FirmwareLength, psFwInfo->u32StartingAddress); + if(retval != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "User space buffer download fails...."); + } + retval = bcm_buffer_readback (Adapter, + (unsigned char *)psFwInfo->pvMappedFirmwareAddress, + psFwInfo->u32FirmwareLength, psFwInfo->u32StartingAddress); + + if(retval != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "read back verifier failed ...."); + } + #endif + retval = buffDnldVerify(Adapter, + buff, + psFwInfo->u32FirmwareLength, + psFwInfo->u32StartingAddress); + if(retval != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"f/w download failed status :%d", retval); + goto error; + } + } +error: + bcm_kfree(buff); + return retval; +} + +static INT buffDnld(PMINI_ADAPTER Adapter, PUCHAR mappedbuffer, UINT u32FirmwareLength, + ULONG u32StartingAddress) +{ + + unsigned int len = 0; + int retval = STATUS_SUCCESS; + len = u32FirmwareLength; + + while(u32FirmwareLength) + { + len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); + retval = wrm (Adapter, u32StartingAddress, mappedbuffer, len); + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "wrm failed with status :%d", retval); + break; + } + u32StartingAddress += len; + u32FirmwareLength -= len; + mappedbuffer +=len; + } + return retval; + +} + +static INT buffRdbkVerify(PMINI_ADAPTER Adapter, + PUCHAR mappedbuffer, UINT u32FirmwareLength, + ULONG u32StartingAddress) +{ + PUCHAR readbackbuff = NULL; + UINT len = u32FirmwareLength; + INT retval = STATUS_SUCCESS; + + readbackbuff = (PUCHAR)kzalloc(MAX_TRANSFER_CTRL_BYTE_USB,GFP_KERNEL); + if(NULL == readbackbuff) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "MEMORY ALLOCATION FAILED"); + return -ENOMEM; + } + while (u32FirmwareLength && !retval) + { + + len = MIN_VAL (u32FirmwareLength, MAX_TRANSFER_CTRL_BYTE_USB); + + retval = rdm (Adapter, u32StartingAddress, readbackbuff, len); + if(retval) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "rdm failed with status %d" ,retval); + break; + } + + if (STATUS_SUCCESS != (retval = bcm_compare_buff_contents (readbackbuff, mappedbuffer, len))) + { + break; + } + u32StartingAddress += len; + u32FirmwareLength -= len; + mappedbuffer +=len; + }/* end of while (u32FirmwareLength && !retval) */ + bcm_kfree(readbackbuff); + return retval; +} + +INT buffDnldVerify(PMINI_ADAPTER Adapter, unsigned char *mappedbuffer, unsigned int u32FirmwareLength, + unsigned long u32StartingAddress) +{ + INT status = STATUS_SUCCESS; + + status = buffDnld(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress); + if(status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer download failed"); + goto error; + } + + status= buffRdbkVerify(Adapter,mappedbuffer,u32FirmwareLength,u32StartingAddress); + if(status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Buffer readback verifier failed"); + goto error; + } +error: + return status; +} + +#endif + diff --git a/drivers/staging/bcm/InterfaceIdleMode.c b/drivers/staging/bcm/InterfaceIdleMode.c new file mode 100644 index 0000000..d99fc7c --- /dev/null +++ b/drivers/staging/bcm/InterfaceIdleMode.c @@ -0,0 +1,318 @@ +#include "headers.h" + +/* +Function: InterfaceIdleModeWakeup + +Description: This is the hardware specific Function for waking up HW device from Idle mode. + A software abort pattern is written to the device to wake it and necessary power state + transitions from host are performed here. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + + +Return: BCM_STATUS_SUCCESS - If Wakeup of the HW Interface was successful. + Other - If an error occured. +*/ + + +/* +Function: InterfaceIdleModeRespond + +Description: This is the hardware specific Function for responding to Idle mode request from target. + Necessary power state transitions from host for idle mode or other device specific + initializations are performed here. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + + +Return: BCM_STATUS_SUCCESS - If Idle mode response related HW configuration was successful. + Other - If an error occured. +*/ + +/* +"dmem bfc02f00 100" tells how many time device went in Idle mode. +this value will be at address bfc02fa4.just before value d0ea1dle. + +Set time value by writing at bfc02f98 7d0 + +checking the Ack timer expire on kannon by running command +d qcslog .. if it shows e means host has not send response to f/w with in 200 ms. Response should be +send to f/w with in 200 ms after the Idle/Shutdown req issued + +*/ + + +int InterfaceIdleModeRespond(PMINI_ADAPTER Adapter,int* puiBuffer) +{ + int status = STATUS_SUCCESS; + unsigned int uiRegRead = 0; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"SubType of Message :0x%X", ntohl(*puiBuffer)); + + if(ntohl(*puiBuffer) == GO_TO_IDLE_MODE_PAYLOAD) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL," Got GO_TO_IDLE_MODE_PAYLOAD(210) Msg Subtype"); + if(ntohl(*(puiBuffer+1)) == 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Got IDLE MODE WAKE UP Response From F/W"); + + status = wrmalt (Adapter,SW_ABORT_IDLEMODE_LOC, &uiRegRead, sizeof(uiRegRead)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg"); + return status; + } + + if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) + { + uiRegRead = 0x00000000 ; + status = wrmalt (Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegRead, sizeof(uiRegRead)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg"); + return status; + } + } + //Below Register should not br read in case of Manual and Protocol Idle mode. + else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) + { + //clear on read Register + status = rdmalt(Adapter, DEVICE_INT_OUT_EP_REG0, &uiRegRead, sizeof(uiRegRead)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg0"); + return status; + } + //clear on read Register + status = rdmalt (Adapter, DEVICE_INT_OUT_EP_REG1, &uiRegRead, sizeof(uiRegRead)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed while clearing H/W Abort Reg1"); + return status; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Device Up from Idle Mode"); + + // Set Idle Mode Flag to False and Clear IdleMode reg. + Adapter->IdleMode = FALSE; + Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; + + wake_up(&Adapter->lowpower_mode_wait_queue); + #if 0 + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"LED Thread is Running. Hence Setting the LED Event as IDLEMODE_EXIT"); + Adapter->DriverState = IDLEMODE_EXIT; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + #endif + + } + else + { + if(TRUE == Adapter->IdleMode) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Device is already in Idle mode...."); + return status ; + } + + uiRegRead = 0; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Got Req from F/W to go in IDLE mode \n"); + + if (Adapter->chip_id== BCS220_2 || + Adapter->chip_id == BCS220_2BC || + Adapter->chip_id== BCS250_BC || + Adapter->chip_id== BCS220_3) + { + + status = rdmalt(Adapter, HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "rdm failed while Reading HPM_CONFIG_LDO145 Reg 0\n"); + return status; + } + + + uiRegRead |= (1<<17); + + status = wrmalt (Adapter,HPM_CONFIG_MSW, &uiRegRead, sizeof(uiRegRead)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm failed while clearing Idle Mode Reg\n"); + return status; + } + + } + SendIdleModeResponse(Adapter); + } + } + else if(ntohl(*puiBuffer) == IDLE_MODE_SF_UPDATE_MSG) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "OverRiding Service Flow Params"); + OverrideServiceFlowParams(Adapter,puiBuffer); + } + return status; +} + + +VOID InterfaceWriteIdleModeWakePattern(PMINI_ADAPTER Adapter) +{ +/* BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Low, 0x1d1e); + BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Low, 0x1d1e); + BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Upp, 0xd0ea); + BeceemWriteMemoryUshort(Adapter, Host2CPU_Mailbox_Upp, 0xd0ea);*/ + return; +} + +int InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern) +{ + int status = STATUS_SUCCESS; + unsigned int value; + unsigned int chip_id ; + unsigned long timeout = 0 ,itr = 0; + + int lenwritten = 0; + unsigned char aucAbortPattern[8]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + PS_INTERFACE_ADAPTER psInterfaceAdapter = Adapter->pvInterfaceAdapter; + + //Abort Bus suspend if its already suspended + if((TRUE == psInterfaceAdapter->bSuspended) && (TRUE == Adapter->bDoSuspend)) + { + status = usb_autopm_get_interface(psInterfaceAdapter->interface); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Bus got wakeup..Aborting Idle mode... status:%d \n",status); + + } + + if((Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) + || + (Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE)) + { + //write the SW abort pattern. + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Writing pattern<%d> to SW_ABORT_IDLEMODE_LOC\n", Pattern); + status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(Pattern)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to Register SW_ABORT_IDLEMODE_LOC failed.."); + return status; + } + } + + if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) + { + value = 0x80000000; + status = wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &value, sizeof(value)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Register failed"); + return status; + } + } + else if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) + { + /* + * Get a Interrupt Out URB and send 8 Bytes Down + * To be Done in Thread Context. + * Not using Asynchronous Mechanism. + */ + status = usb_interrupt_msg (psInterfaceAdapter->udev, + usb_sndintpipe(psInterfaceAdapter->udev, + psInterfaceAdapter->sIntrOut.int_out_endpointAddr), + aucAbortPattern, + 8, + &lenwritten, + 5000); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Sending Abort pattern down fails with status:%d..\n",status); + return status; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "NOB Sent down :%d", lenwritten); + } + + //mdelay(25); + + timeout= jiffies + msecs_to_jiffies(50) ; + while( timeout > jiffies ) + { + itr++ ; + rdmalt(Adapter, CHIP_ID_REG, &chip_id, sizeof(UINT)); + if(0xbece3200==(chip_id&~(0xF0))) + { + chip_id = chip_id&~(0xF0); + } + if(chip_id == Adapter->chip_id) + break; + } + if(timeout < jiffies ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Not able to read chip-id even after 25 msec"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Number of completed iteration to read chip-id :%lu", itr); + } + + status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, &Pattern, sizeof(status)); + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to Register SW_ABORT_IDLEMODE_LOC failed.."); + return status; + } + } + return status; +} +int InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter) +{ + ULONG Status = 0; + if(Adapter->bTriedToWakeUpFromlowPowerMode) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL, "Wake up already attempted.. ignoring\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, IDLE_MODE, DBG_LVL_ALL,"Writing Low Power Mode Abort pattern to the Device\n"); + Adapter->bTriedToWakeUpFromlowPowerMode = TRUE; + InterfaceAbortIdlemode(Adapter, Adapter->usIdleModePattern); + + } + return Status; +} + +void InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter) +{ + unsigned int uiRegVal = 0; + INT Status = 0; + if(Adapter->ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING) + { + // clear idlemode interrupt. + uiRegVal = 0; + Status =wrmalt(Adapter,DEBUG_INTERRUPT_GENERATOR_REGISTOR, &uiRegVal, sizeof(uiRegVal)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"WRM to DEBUG_INTERRUPT_GENERATOR_REGISTOR Failed with err :%d", Status); + return; + } + } + + else + { + + //clear Interrupt EP registers. + Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG0, &uiRegVal, sizeof(uiRegVal)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG0 failed with Err :%d", Status); + return; + } + + Status = rdmalt(Adapter,DEVICE_INT_OUT_EP_REG1, &uiRegVal, sizeof(uiRegVal)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RDM of DEVICE_INT_OUT_EP_REG1 failed with Err :%d", Status); + return; + } + } +} + diff --git a/drivers/staging/bcm/InterfaceIdleMode.h b/drivers/staging/bcm/InterfaceIdleMode.h new file mode 100644 index 0000000..f87c132 --- /dev/null +++ b/drivers/staging/bcm/InterfaceIdleMode.h @@ -0,0 +1,16 @@ +#ifndef _INTERFACE_IDLEMODE_H +#define _INTERFACE_IDLEMODE_H + +INT InterfaceIdleModeWakeup(PMINI_ADAPTER Adapter); + +INT InterfaceIdleModeRespond(PMINI_ADAPTER Adapter,PINT puiBuffer); + +VOID InterfaceWriteIdleModeWakePattern(PMINI_ADAPTER Adapter); + +INT InterfaceAbortIdlemode(PMINI_ADAPTER Adapter, unsigned int Pattern); + +INT InterfaceWakeUp(PMINI_ADAPTER Adapter); + +VOID InterfaceHandleShutdownModeWakeup(PMINI_ADAPTER Adapter); +#endif + diff --git a/drivers/staging/bcm/InterfaceInit.c b/drivers/staging/bcm/InterfaceInit.c new file mode 100644 index 0000000..e06f168 --- /dev/null +++ b/drivers/staging/bcm/InterfaceInit.c @@ -0,0 +1,868 @@ +#include "headers.h" + +static struct usb_device_id InterfaceUsbtable[] = { + { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3B) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_T3, BCM_USB_PRODUCT_ID_T3L) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_ZTE, BCM_USB_PRODUCT_ID_226) }, + { USB_DEVICE(BCM_USB_VENDOR_ID_FOXCONN, BCM_USB_PRODUCT_ID_1901) }, + {} +}; + +VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + INT i = 0; + // Wake up the wait_queue... + if(psIntfAdapter->psAdapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + psIntfAdapter->psAdapter->DriverState = DRIVER_HALT; + wake_up(&psIntfAdapter->psAdapter->LEDInfo.notify_led_event); + } + reset_card_proc(psIntfAdapter->psAdapter); + + //worst case time taken by the RDM/WRM will be 5 sec. will check after every 100 ms + //to accertain the device is not being accessed. After this No RDM/WRM should be made. + while(psIntfAdapter->psAdapter->DeviceAccess) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Device is being Accessed \n"); + msleep(100); + } + /* Free interrupt URB */ + //psIntfAdapter->psAdapter->device_removed = TRUE; + if(psIntfAdapter->psInterruptUrb) + { + usb_free_urb(psIntfAdapter->psInterruptUrb); + } + + /* Free transmit URBs */ + for(i = 0; i < MAXIMUM_USB_TCB; i++) + { + if(psIntfAdapter->asUsbTcb[i].urb != NULL) + { + usb_free_urb(psIntfAdapter->asUsbTcb[i].urb); + psIntfAdapter->asUsbTcb[i].urb = NULL; + } + } + /* Free receive URB and buffers */ + for(i = 0; i < MAXIMUM_USB_RCB; i++) + { + if (psIntfAdapter->asUsbRcb[i].urb != NULL) + { + bcm_kfree(psIntfAdapter->asUsbRcb[i].urb->transfer_buffer); + usb_free_urb(psIntfAdapter->asUsbRcb[i].urb); + psIntfAdapter->asUsbRcb[i].urb = NULL; + } + } + AdapterFree(psIntfAdapter->psAdapter); +} + + + +static int usbbcm_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int usbbcm_release(struct inode *inode, struct file *file) +{ + return 0; +} + +static ssize_t usbbcm_read(struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + return 0; +} + +static ssize_t usbbcm_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) +{ + return 0; +} + + +VOID ConfigureEndPointTypesThroughEEPROM(PMINI_ADAPTER Adapter) +{ + ULONG ulReg = 0; + +// Program EP2 MAX_PKT_SIZE + ulReg = ntohl(EP2_MPS_REG); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x128,4,TRUE); + ulReg = ntohl(EP2_MPS); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x12C,4,TRUE); + + ulReg = ntohl(EP2_CFG_REG); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x132,4,TRUE); + if(((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter))->bHighSpeedDevice == TRUE) + { + ulReg = ntohl(EP2_CFG_INT); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x136,4,TRUE); + } + else + { +// USE BULK EP as TX in FS mode. + ulReg = ntohl(EP2_CFG_BULK); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x136,4,TRUE); + } + + +// Program EP4 MAX_PKT_SIZE. + ulReg = ntohl(EP4_MPS_REG); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x13C,4,TRUE); + ulReg = ntohl(EP4_MPS); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x140,4,TRUE); + +// Program TX EP as interrupt (Alternate Setting) + if( rdmalt(Adapter,0x0F0110F8, (PUINT)&ulReg,4)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reading of Tx EP is failing"); + return ; + } + ulReg |= 0x6; + + ulReg = ntohl(ulReg); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1CC,4,TRUE); + + ulReg = ntohl(EP4_CFG_REG); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1C8,4,TRUE); +// Program ISOCHRONOUS EP size to zero. + ulReg = ntohl(ISO_MPS_REG); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1D2,4,TRUE); + ulReg = ntohl(ISO_MPS); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1D6,4,TRUE); + +// Update EEPROM Version. +// Read 4 bytes from 508 and modify 511 and 510. +// + ReadBeceemEEPROM(Adapter,0x1FC,(PUINT)&ulReg); + ulReg &= 0x0101FFFF; + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1FC,4,TRUE); +// +//Update length field if required. Also make the string NULL terminated. +// + ReadBeceemEEPROM(Adapter,0xA8,(PUINT)&ulReg); + if((ulReg&0x00FF0000)>>16 > 0x30) + { + ulReg = (ulReg&0xFF00FFFF)|(0x30<<16); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0xA8,4,TRUE); + } + ReadBeceemEEPROM(Adapter,0x148,(PUINT)&ulReg); + if((ulReg&0x00FF0000)>>16 > 0x30) + { + ulReg = (ulReg&0xFF00FFFF)|(0x30<<16); + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x148,4,TRUE); + } + ulReg = 0; + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x122,4,TRUE); + ulReg = 0; + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&ulReg,0x1C2,4,TRUE); + +} + +static struct file_operations usbbcm_fops = { + .open = usbbcm_open, + .release = usbbcm_release, + .read = usbbcm_read, + .write = usbbcm_write, + .owner = THIS_MODULE, +}; + +static struct usb_class_driver usbbcm_class = { + .name = "usbbcm", + .fops = &usbbcm_fops, + .minor_base = BCM_USB_MINOR_BASE, +}; + +static int +usbbcm_device_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + int retval =0 ; + PMINI_ADAPTER psAdapter = NULL; + PS_INTERFACE_ADAPTER psIntfAdapter = NULL; + struct usb_device *udev = NULL; + +// BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usbbcm probe!!"); + if((intf == NULL) || (id == NULL)) + { + // BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf or id is NULL"); + return -EINVAL; + } + + /* Allocate Adapter structure */ + if((psAdapter = kmalloc(sizeof(MINI_ADAPTER), GFP_KERNEL)) == NULL) + { + //BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory"); + return -ENOMEM; + } + + memset(psAdapter, 0, sizeof(MINI_ADAPTER)); + + /* Init default driver debug state */ + + psAdapter->stDebugState.debug_level = DBG_LVL_CURR; + psAdapter->stDebugState.type = DBG_TYPE_INITEXIT; + memset (psAdapter->stDebugState.subtype, 0, sizeof (psAdapter->stDebugState.subtype)); + + /* Technically, one can start using BCM_DEBUG_PRINT after this point. + * However, realize that by default the Type/Subtype bitmaps are all zero now; + * so no prints will actually appear until the TestApp turns on debug paths via + * the ioctl(); so practically speaking, in early init, no logging happens. + * + * A solution (used below): we explicitly set the bitmaps to 1 for Type=DBG_TYPE_INITEXIT + * and ALL subtype's of the same. Now all bcm debug statements get logged, enabling debug + * during early init. + * Further, we turn this OFF once init_module() completes. + */ + + psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0xff; + BCM_SHOW_DEBUG_BITMAP(psAdapter); + + retval = InitAdapter(psAdapter); + if(retval) + { + BCM_DEBUG_PRINT (psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InitAdapter Failed\n"); + AdapterFree(psAdapter); + return retval; + } + + /* Allocate interface adapter structure */ + if((psAdapter->pvInterfaceAdapter = + kmalloc(sizeof(S_INTERFACE_ADAPTER), GFP_KERNEL)) == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Out of memory"); + AdapterFree (psAdapter); + return -ENOMEM; + } + memset(psAdapter->pvInterfaceAdapter, 0, sizeof(S_INTERFACE_ADAPTER)); + + psIntfAdapter = InterfaceAdapterGet(psAdapter); + psIntfAdapter->psAdapter = psAdapter; + + /* Store usb interface in Interface Adapter */ + psIntfAdapter->interface = intf; + usb_set_intfdata(intf, psIntfAdapter); + + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%x",(unsigned int)psIntfAdapter); + retval = InterfaceAdapterInit(psIntfAdapter); + if(retval) + { + /* If the Firmware/Cfg File is not present + * then return success, let the application + * download the files. + */ + if(-ENOENT == retval){ + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "File Not Found, Use App to Download\n"); + return STATUS_SUCCESS; + } + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapterInit Failed \n"); + usb_set_intfdata(intf, NULL); + udev = interface_to_usbdev (intf); + usb_put_dev(udev); + if(psAdapter->bUsbClassDriverRegistered == TRUE) + usb_deregister_dev (intf, &usbbcm_class); + InterfaceAdapterFree(psIntfAdapter); + return retval ; + } + if(psAdapter->chip_id > T3) + { + uint32_t uiNackZeroLengthInt=4; + if(wrmalt(psAdapter, DISABLE_USB_ZERO_LEN_INT, &uiNackZeroLengthInt, sizeof(uiNackZeroLengthInt))) + { + return -EIO;; + } + } + + udev = interface_to_usbdev (intf); + /* Check whether the USB-Device Supports remote Wake-Up */ + if(USB_CONFIG_ATT_WAKEUP & udev->actconfig->desc.bmAttributes) + { + /* If Suspend then only support dynamic suspend */ + if(psAdapter->bDoSuspend) + { + udev->autosuspend_delay = 0; + intf->needs_remote_wakeup = 1; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) + udev->autosuspend_disabled = 0; +#else + usb_enable_autosuspend(udev); +#endif + device_init_wakeup(&intf->dev,1); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) + usb_autopm_disable(intf); +#endif + INIT_WORK(&psIntfAdapter->usbSuspendWork, putUsbSuspend); + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Enabling USB Auto-Suspend\n"); + } + else + { + intf->needs_remote_wakeup = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) + udev->autosuspend_disabled = 1; +#else + usb_disable_autosuspend(udev); +#endif + } + } + + psAdapter->stDebugState.subtype[DBG_TYPE_INITEXIT] = 0x0; + return retval; +} + +static void usbbcm_disconnect (struct usb_interface *intf) +{ + PS_INTERFACE_ADAPTER psIntfAdapter = NULL; + PMINI_ADAPTER psAdapter = NULL; + struct usb_device *udev = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Usb disconnected"); + if(intf == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "intf pointer is NULL"); + return; + } + psIntfAdapter = usb_get_intfdata(intf); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "psIntfAdapter 0x%x",(unsigned int)psIntfAdapter); + if(psIntfAdapter == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "InterfaceAdapter pointer is NULL"); + return; + } + psAdapter = psIntfAdapter->psAdapter; + if(psAdapter->bDoSuspend) + intf->needs_remote_wakeup = 0; + + psAdapter->device_removed = TRUE ; + usb_set_intfdata(intf, NULL); + InterfaceAdapterFree(psIntfAdapter); + udev = interface_to_usbdev (intf); + usb_put_dev(udev); + usb_deregister_dev (intf, &usbbcm_class); +} + + +static __inline int AllocUsbCb(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + int i = 0; + for(i = 0; i < MAXIMUM_USB_TCB; i++) + { + if((psIntfAdapter->asUsbTcb[i].urb = + usb_alloc_urb(0, GFP_KERNEL)) == NULL) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Tx urb for index %d", i); + return -ENOMEM; + } + } + + for(i = 0; i < MAXIMUM_USB_RCB; i++) + { + if ((psIntfAdapter->asUsbRcb[i].urb = + usb_alloc_urb(0, GFP_KERNEL)) == NULL) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx urb for index %d", i); + return -ENOMEM; + } + if((psIntfAdapter->asUsbRcb[i].urb->transfer_buffer = + kmalloc(MAX_DATA_BUFFER_SIZE, GFP_KERNEL)) == NULL) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cant allocate Rx buffer for index %d", i); + return -ENOMEM; + } + psIntfAdapter->asUsbRcb[i].urb->transfer_buffer_length = MAX_DATA_BUFFER_SIZE; + } + return 0; +} + + + +static int device_run(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + INT value = 0; + UINT status = STATUS_SUCCESS; + + status = InitCardAndDownloadFirmware(psIntfAdapter->psAdapter); + if(status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "InitCardAndDownloadFirmware failed.\n"); + return status; + } + if(TRUE == psIntfAdapter->psAdapter->fw_download_done) + { + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Sending first interrupt URB down......"); + if(StartInterruptUrb(psIntfAdapter)) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Cannot send interrupt in URB"); + } + //now register the cntrl interface. + //after downloading the f/w waiting for 5 sec to get the mailbox interrupt. + + psIntfAdapter->psAdapter->waiting_to_fw_download_done = FALSE; + value = wait_event_timeout(psIntfAdapter->psAdapter->ioctl_fw_dnld_wait_queue, + psIntfAdapter->psAdapter->waiting_to_fw_download_done, 5*HZ); + + if(value == 0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Mailbox Interrupt has not reached to Driver.."); + } + else + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Got the mailbox interrupt ...Registering control interface...\n "); + } + if(register_control_device_interface(psIntfAdapter->psAdapter) < 0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Register Control Device failed..."); + return -EIO; + } + } + return 0; +} + +#if 0 +static void print_usb_interface_desc(struct usb_interface_descriptor *usb_intf_desc) +{ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** INTERFACE DESCRIPTOR *********************"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength: %x", usb_intf_desc->bLength); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType: %x", usb_intf_desc->bDescriptorType); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceNumber: %x", usb_intf_desc->bInterfaceNumber); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bAlternateSetting: %x", usb_intf_desc->bAlternateSetting); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bNumEndpoints: %x", usb_intf_desc->bNumEndpoints); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceClass: %x", usb_intf_desc->bInterfaceClass); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceSubClass: %x", usb_intf_desc->bInterfaceSubClass); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterfaceProtocol: %x", usb_intf_desc->bInterfaceProtocol); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "iInterface :%x\n",usb_intf_desc->iInterface); +} +static void print_usb_endpoint_descriptor(struct usb_endpoint_descriptor *usb_ep_desc) +{ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "**************** ENDPOINT DESCRIPTOR *********************"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bLength :%x ", usb_ep_desc->bLength); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bDescriptorType :%x ", usb_ep_desc->bDescriptorType); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bEndpointAddress :%x ", usb_ep_desc->bEndpointAddress); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bmAttributes :%x ", usb_ep_desc->bmAttributes); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "wMaxPacketSize :%x ",usb_ep_desc->wMaxPacketSize); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "bInterval :%x ",usb_ep_desc->bInterval); +} + +#endif + +static inline int bcm_usb_endpoint_num(const struct usb_endpoint_descriptor *epd) +{ + return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; +} + +static inline int bcm_usb_endpoint_type(const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; +} + +static inline int bcm_usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); +} + +static inline int bcm_usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +static inline int bcm_usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK); +} + +static inline int bcm_usb_endpoint_xfer_control(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL); +} + +static inline int bcm_usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT); +} + +static inline int bcm_usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC); +} + +static inline int bcm_usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd) +{ + return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_in(epd)); +} + +static inline int bcm_usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd) +{ + return (bcm_usb_endpoint_xfer_bulk(epd) && bcm_usb_endpoint_dir_out(epd)); +} + +static inline int bcm_usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd) +{ + return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_in(epd)); +} + +static inline int bcm_usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd) +{ + return (bcm_usb_endpoint_xfer_int(epd) && bcm_usb_endpoint_dir_out(epd)); +} + +static inline int bcm_usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd) +{ + return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_in(epd)); +} + +static inline int bcm_usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd) +{ + return (bcm_usb_endpoint_xfer_isoc(epd) && bcm_usb_endpoint_dir_out(epd)); +} + +INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + size_t buffer_size; + ULONG value; + INT retval = 0; + INT usedIntOutForBulkTransfer = 0 ; + BOOLEAN bBcm16 = FALSE; + UINT uiData = 0; + + if(psIntfAdapter == NULL) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Interface Adapter is NULL"); + return -EINVAL; + } + /* Store the usb dev into interface adapter */ + psIntfAdapter->udev = usb_get_dev(interface_to_usbdev( + psIntfAdapter->interface)); + + if((psIntfAdapter->udev->speed == USB_SPEED_HIGH)) + { + psIntfAdapter->bHighSpeedDevice = TRUE ; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO HIGH_SPEED "); + } + else + { + psIntfAdapter->bHighSpeedDevice = FALSE ; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "MODEM IS CONFIGURED TO FULL_SPEED "); + } + + psIntfAdapter->psAdapter->interface_rdm = BcmRDM; + psIntfAdapter->psAdapter->interface_wrm = BcmWRM; + + if(rdmalt(psIntfAdapter->psAdapter, CHIP_ID_REG, (PUINT)&(psIntfAdapter->psAdapter->chip_id), sizeof(UINT)) < 0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "CHIP ID Read Failed\n"); + return STATUS_FAILURE; + } + if(0xbece3200==(psIntfAdapter->psAdapter->chip_id&~(0xF0))) + { + psIntfAdapter->psAdapter->chip_id=(psIntfAdapter->psAdapter->chip_id&~(0xF0)); + } + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "First RDM Chip ID 0x%lx\n", psIntfAdapter->psAdapter->chip_id); + + iface_desc = psIntfAdapter->interface->cur_altsetting; + //print_usb_interface_desc(&(iface_desc->desc)); + + if(psIntfAdapter->psAdapter->chip_id == T3B) + { + + // + //T3B device will have EEPROM,check if EEPROM is proper and BCM16 can be done or not. + // + BeceemEEPROMBulkRead(psIntfAdapter->psAdapter,&uiData,0x0,4); + if(uiData == BECM) + { + bBcm16 = TRUE; + } + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Number of Altsetting aviailable for This Modem 0x%x\n", psIntfAdapter->interface->num_altsetting); + if(bBcm16 == TRUE) + { + //selecting alternate setting one as a default setting for High Speed modem. + if(psIntfAdapter->bHighSpeedDevice) + retval= usb_set_interface(psIntfAdapter->udev,DEFAULT_SETTING_0,ALTERNATE_SETTING_1); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "BCM16 is Applicable on this dongle"); + if(retval || (psIntfAdapter->bHighSpeedDevice == FALSE)) + { + usedIntOutForBulkTransfer = EP2 ; + endpoint = &iface_desc->endpoint[EP2].desc; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Interface altsetting got failed or Moemd is configured to FS.hence will work on default setting 0 \n"); + /* + If Modem is high speed device EP2 should be INT OUT End point + If Mode is FS then EP2 should be bulk end point + */ + if(((psIntfAdapter->bHighSpeedDevice ==TRUE ) && (bcm_usb_endpoint_is_int_out(endpoint)== FALSE)) + ||((psIntfAdapter->bHighSpeedDevice == FALSE)&& (bcm_usb_endpoint_is_bulk_out(endpoint)== FALSE))) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Configuring the EEPROM "); + //change the EP2, EP4 to INT OUT end point + ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter); + + /* + It resets the device and if any thing gets changed in USB descriptor it will show fail and + re-enumerate the device + */ + retval = usb_reset_device(psIntfAdapter->udev); + if(retval) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n"); + return retval ; + } + + } + if((psIntfAdapter->bHighSpeedDevice == FALSE) && bcm_usb_endpoint_is_bulk_out(endpoint)) + { + // Once BULK is selected in FS mode. Revert it back to INT. Else USB_IF will fail. + UINT uiData = ntohl(EP2_CFG_INT); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL,"Reverting Bulk to INT as it is FS MODE"); + BeceemEEPROMBulkWrite(psIntfAdapter->psAdapter,(PUCHAR)&uiData,0x136,4,TRUE); + } + } + else + { + usedIntOutForBulkTransfer = EP4 ; + endpoint = &iface_desc->endpoint[EP4].desc; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Choosing AltSetting as a default setting"); + if( bcm_usb_endpoint_is_int_out(endpoint) == FALSE) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, " Dongle does not have BCM16 Fix"); + //change the EP2, EP4 to INT OUT end point and use EP4 in altsetting + ConfigureEndPointTypesThroughEEPROM(psIntfAdapter->psAdapter); + + /* + It resets the device and if any thing gets changed in USB descriptor it will show fail and + re-enumerate the device + */ + retval = usb_reset_device(psIntfAdapter->udev); + if(retval) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "reset got failed. hence Re-enumerating the device \n"); + return retval ; + } + + } + } + } + } + + iface_desc = psIntfAdapter->interface->cur_altsetting; + //print_usb_interface_desc(&(iface_desc->desc)); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Current number of endpoints :%x \n", iface_desc->desc.bNumEndpoints); + for (value = 0; value < iface_desc->desc.bNumEndpoints; ++value) + { + endpoint = &iface_desc->endpoint[value].desc; + //print_usb_endpoint_descriptor(endpoint); + + if (!psIntfAdapter->sBulkIn.bulk_in_endpointAddr && bcm_usb_endpoint_is_bulk_in(endpoint)) + { + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + psIntfAdapter->sBulkIn.bulk_in_size = buffer_size; + psIntfAdapter->sBulkIn.bulk_in_endpointAddr = + endpoint->bEndpointAddress; + psIntfAdapter->sBulkIn.bulk_in_pipe = + usb_rcvbulkpipe(psIntfAdapter->udev, + psIntfAdapter->sBulkIn.bulk_in_endpointAddr); + } + + if (!psIntfAdapter->sBulkOut.bulk_out_endpointAddr && bcm_usb_endpoint_is_bulk_out(endpoint)) + { + + psIntfAdapter->sBulkOut.bulk_out_endpointAddr = + endpoint->bEndpointAddress; + psIntfAdapter->sBulkOut.bulk_out_pipe = + usb_sndbulkpipe(psIntfAdapter->udev, + psIntfAdapter->sBulkOut.bulk_out_endpointAddr); + } + + if (!psIntfAdapter->sIntrIn.int_in_endpointAddr && bcm_usb_endpoint_is_int_in(endpoint)) + { + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + psIntfAdapter->sIntrIn.int_in_size = buffer_size; + psIntfAdapter->sIntrIn.int_in_endpointAddr = + endpoint->bEndpointAddress; + psIntfAdapter->sIntrIn.int_in_interval = endpoint->bInterval; + psIntfAdapter->sIntrIn.int_in_buffer = + kmalloc(buffer_size, GFP_KERNEL); + if (!psIntfAdapter->sIntrIn.int_in_buffer) { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_in_buffer"); + return -EINVAL; + } + //psIntfAdapter->sIntrIn.int_in_pipe = + } + + if (!psIntfAdapter->sIntrOut.int_out_endpointAddr && bcm_usb_endpoint_is_int_out(endpoint)) + { + + if( !psIntfAdapter->sBulkOut.bulk_out_endpointAddr && + (psIntfAdapter->psAdapter->chip_id == T3B) && (value == usedIntOutForBulkTransfer)) + { + //use first intout end point as a bulk out end point + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + psIntfAdapter->sBulkOut.bulk_out_size = buffer_size; + //printk("\nINT OUT Endpoing buffer size :%x endpoint :%x\n", buffer_size, value +1); + psIntfAdapter->sBulkOut.bulk_out_endpointAddr = + endpoint->bEndpointAddress; + psIntfAdapter->sBulkOut.bulk_out_pipe = + usb_sndintpipe(psIntfAdapter->udev, + psIntfAdapter->sBulkOut.bulk_out_endpointAddr); + psIntfAdapter->sBulkOut.int_out_interval = endpoint->bInterval; + + } + else if(value == EP6) + { + buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); + psIntfAdapter->sIntrOut.int_out_size = buffer_size; + psIntfAdapter->sIntrOut.int_out_endpointAddr = + endpoint->bEndpointAddress; + psIntfAdapter->sIntrOut.int_out_interval = endpoint->bInterval; + psIntfAdapter->sIntrOut.int_out_buffer= kmalloc(buffer_size, + GFP_KERNEL); + if (!psIntfAdapter->sIntrOut.int_out_buffer) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Could not allocate interrupt_out_buffer"); + return -EINVAL; + } + } + } + } + usb_set_intfdata(psIntfAdapter->interface, psIntfAdapter); + retval = usb_register_dev(psIntfAdapter->interface, &usbbcm_class); + if(retval) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb register dev failed = %d", retval); + psIntfAdapter->psAdapter->bUsbClassDriverRegistered = FALSE; + return retval; + } + else + { + psIntfAdapter->psAdapter->bUsbClassDriverRegistered = TRUE; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "usb dev registered"); + } + + psIntfAdapter->psAdapter->bcm_file_download = InterfaceFileDownload; + psIntfAdapter->psAdapter->bcm_file_readback_from_chip = + InterfaceFileReadbackFromChip; + psIntfAdapter->psAdapter->interface_transmit = InterfaceTransmitPacket; + + retval = CreateInterruptUrb(psIntfAdapter); + + if(retval) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cannot create interrupt urb"); + return retval; + } + + retval = AllocUsbCb(psIntfAdapter); + if(retval) + { + return retval; + } + + + retval = device_run(psIntfAdapter); + if(retval) + { + return retval; + } + + + return 0; +} +int InterfaceSuspend (struct usb_interface *intf, pm_message_t message) +{ + PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "=================================\n"); + //Bcm_kill_all_URBs(psIntfAdapter); + psIntfAdapter->bSuspended = TRUE; + + if(TRUE == psIntfAdapter->bPreparingForBusSuspend) + { + psIntfAdapter->bPreparingForBusSuspend = FALSE; + + if(psIntfAdapter->psAdapter->LinkStatus == LINKUP_DONE) + { + psIntfAdapter->psAdapter->IdleMode = TRUE ; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Idle Mode.."); + } + else + { + psIntfAdapter->psAdapter->bShutStatus = TRUE; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Host Entered in PMU Shutdown Mode.."); + } + } + psIntfAdapter->psAdapter->bPreparingForLowPowerMode = FALSE; + + //Signaling the control pkt path + wake_up(&psIntfAdapter->psAdapter->lowpower_mode_wait_queue); + + return 0; +} +int InterfaceResume (struct usb_interface *intf) +{ + PS_INTERFACE_ADAPTER psIntfAdapter = usb_get_intfdata(intf); + printk("=================================\n"); + mdelay(100); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) + intf->pm_usage_cnt =1 ; +#endif + psIntfAdapter->bSuspended = FALSE; + + StartInterruptUrb(psIntfAdapter); + InterfaceRx(psIntfAdapter); + return 0; +} +int InterfacePreReset(struct usb_interface *intf) +{ + printk("====================>"); + return STATUS_SUCCESS; +} +int InterfacePostReset(struct usb_interface *intf) +{ + printk("Do Post chip reset setting here if it is required"); + return STATUS_SUCCESS; +} +static struct usb_driver usbbcm_driver = { + .name = "usbbcm", + .probe = usbbcm_device_probe, + .disconnect = usbbcm_disconnect, + .suspend = InterfaceSuspend, + .resume = InterfaceResume, + .pre_reset=InterfacePreReset, + .post_reset=InterfacePostReset, + .id_table = InterfaceUsbtable, + .supports_autosuspend = 1, +}; + + +/* +Function: InterfaceInitialize + +Description: This is the hardware specific initialization Function. + Registering the driver with NDIS , other device specific NDIS + and hardware initializations are done here. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + + +Return: BCM_STATUS_SUCCESS - If Initialization of the + HW Interface was successful. + Other - If an error occured. +*/ +INT InterfaceInitialize(void) +{ +// BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Registering Usb driver!!"); + return usb_register(&usbbcm_driver); +} + +INT InterfaceExit(void) +{ + //PMINI_ADAPTER psAdapter = NULL; + int status = 0; + + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, DRV_ENTRY, DBG_LVL_ALL, "Deregistering Usb driver!!"); + usb_deregister(&usbbcm_driver); + return status; +} +MODULE_LICENSE ("GPL"); diff --git a/drivers/staging/bcm/InterfaceInit.h b/drivers/staging/bcm/InterfaceInit.h new file mode 100644 index 0000000..e7a96e5 --- /dev/null +++ b/drivers/staging/bcm/InterfaceInit.h @@ -0,0 +1,51 @@ +#ifndef _INTERFACE_INIT_H +#define _INTERFACE_INIT_H + +#define BCM_USB_VENDOR_ID_T3 0x198f +#define BCM_USB_VENDOR_ID_FOXCONN 0x0489 +#define BCM_USB_VENDOR_ID_ZTE 0x19d2 + +#define BCM_USB_PRODUCT_ID_T3 0x0300 +#define BCM_USB_PRODUCT_ID_T3B 0x0210 +#define BCM_USB_PRODUCT_ID_T3L 0x0220 +#define BCM_USB_PRODUCT_ID_SYM 0x15E +#define BCM_USB_PRODUCT_ID_1901 0xe017 +#define BCM_USB_PRODUCT_ID_226 0x0132 + +#define BCM_USB_MINOR_BASE 192 + + +INT InterfaceInitialize(void); + +INT InterfaceExit(void); + +#ifndef BCM_SHM_INTERFACE +INT InterfaceAdapterInit(PS_INTERFACE_ADAPTER Adapter); + +INT usbbcm_worker_thread(PS_INTERFACE_ADAPTER psIntfAdapter); + +VOID InterfaceAdapterFree(PS_INTERFACE_ADAPTER psIntfAdapter); + +#else +INT InterfaceAdapterInit(PMINI_ADAPTER Adapter); +#endif + + +#if 0 + +ULONG InterfaceClaimAdapter(PMINI_ADAPTER Adapter); + +VOID InterfaceDDRControllerInit(PMINI_ADAPTER Adapter); + +ULONG InterfaceReset(PMINI_ADAPTER Adapter); + +ULONG InterfaceRegisterResources(PMINI_ADAPTER Adapter); + +VOID InterfaceUnRegisterResources(PMINI_ADAPTER Adapter); + +ULONG InterfaceFirmwareDownload(PMINI_ADAPTER Adapter); + +#endif + +#endif + diff --git a/drivers/staging/bcm/InterfaceIsr.c b/drivers/staging/bcm/InterfaceIsr.c new file mode 100644 index 0000000..f928fe4 --- /dev/null +++ b/drivers/staging/bcm/InterfaceIsr.c @@ -0,0 +1,203 @@ +#include "headers.h" + +#ifndef BCM_SHM_INTERFACE + +static void read_int_callback(struct urb *urb/*, struct pt_regs *regs*/) +{ + int status = urb->status; + PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)urb->context; + PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter ; + + if(Adapter->device_removed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Device has Got Removed."); + return ; + } + + if(((Adapter->bPreparingForLowPowerMode == TRUE) && (Adapter->bDoSuspend == TRUE)) || + psIntfAdapter->bSuspended || + psIntfAdapter->bPreparingForBusSuspend) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt call back is called while suspending the device"); + return ; + } + + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "interrupt urb status %d", status); + switch (status) { + /* success */ + case STATUS_SUCCESS: + if ( urb->actual_length ) + { + + if(psIntfAdapter->ulInterruptData[1] & 0xFF) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Got USIM interrupt"); + } + + if(psIntfAdapter->ulInterruptData[1] & 0xFF00) + { + atomic_set(&Adapter->CurrNumFreeTxDesc, + (psIntfAdapter->ulInterruptData[1] & 0xFF00) >> 8); + atomic_set (&Adapter->uiMBupdate, TRUE); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "TX mailbox contains %d", + atomic_read(&Adapter->CurrNumFreeTxDesc)); + } + if(psIntfAdapter->ulInterruptData[1] >> 16) + { + Adapter->CurrNumRecvDescs= + (psIntfAdapter->ulInterruptData[1] >> 16); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"RX mailbox contains %d", + Adapter->CurrNumRecvDescs); + InterfaceRx(psIntfAdapter); + } + if(Adapter->fw_download_done && + !Adapter->downloadDDR && + atomic_read(&Adapter->CurrNumFreeTxDesc)) + { + psIntfAdapter->psAdapter->downloadDDR +=1; + wake_up(&Adapter->tx_packet_wait_queue); + } + if(FALSE == Adapter->waiting_to_fw_download_done) + { + Adapter->waiting_to_fw_download_done = TRUE; + wake_up(&Adapter->ioctl_fw_dnld_wait_queue); + } + if(!atomic_read(&Adapter->TxPktAvail)) + { + atomic_set(&Adapter->TxPktAvail, 1); + wake_up(&Adapter->tx_packet_wait_queue); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Firing interrupt in URB"); + } + break; + case -ENOENT : + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"URB has got disconnected ...."); + return ; + } + case -EINPROGRESS: + { + //This situation may happend when URBunlink is used. for detail check usb_unlink_urb documentation. + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Impossibe condition has occured... something very bad is going on"); + break ; + //return; + } + case -EPIPE: + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt IN endPoint has got halted/stalled...need to clear this"); + Adapter->bEndPointHalted = TRUE ; + wake_up(&Adapter->tx_packet_wait_queue); + urb->status = STATUS_SUCCESS ;; + return; + } + /* software-driven interface shutdown */ + case -ECONNRESET: //URB got unlinked. + case -ESHUTDOWN: // hardware gone. this is the serious problem. + //Occurs only when something happens with the host controller device + case -ENODEV : //Device got removed + case -EINVAL : //Some thing very bad happened with the URB. No description is available. + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"interrupt urb error %d", status); + urb->status = STATUS_SUCCESS ; + break ; + //return; + default: + //This is required to check what is the defaults conditions when it occurs.. + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"GOT DEFAULT INTERRUPT URB STATUS :%d..Please Analyze it...", status); + break; + } + + StartInterruptUrb(psIntfAdapter); + + +} + +int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + psIntfAdapter->psInterruptUrb = usb_alloc_urb(0, GFP_KERNEL); + if (!psIntfAdapter->psInterruptUrb) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Cannot allocate interrupt urb"); + return -ENOMEM; + } + psIntfAdapter->psInterruptUrb->transfer_buffer = + psIntfAdapter->ulInterruptData; + psIntfAdapter->psInterruptUrb->transfer_buffer_length = + sizeof(psIntfAdapter->ulInterruptData); + + psIntfAdapter->sIntrIn.int_in_pipe = usb_rcvintpipe(psIntfAdapter->udev, + psIntfAdapter->sIntrIn.int_in_endpointAddr); + + usb_fill_int_urb(psIntfAdapter->psInterruptUrb, psIntfAdapter->udev, + psIntfAdapter->sIntrIn.int_in_pipe, + psIntfAdapter->psInterruptUrb->transfer_buffer, + psIntfAdapter->psInterruptUrb->transfer_buffer_length, + read_int_callback, psIntfAdapter, + psIntfAdapter->sIntrIn.int_in_interval); + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Interrupt Interval: %d\n", + psIntfAdapter->sIntrIn.int_in_interval); + return 0; +} + + +INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + INT status = 0; + + if( FALSE == psIntfAdapter->psAdapter->device_removed && + FALSE == psIntfAdapter->psAdapter->bEndPointHalted && + FALSE == psIntfAdapter->bSuspended && + FALSE == psIntfAdapter->bPreparingForBusSuspend && + FALSE == psIntfAdapter->psAdapter->StopAllXaction) + { + status = usb_submit_urb(psIntfAdapter->psInterruptUrb, GFP_ATOMIC); + if (status) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Cannot send int urb %d\n", status); + if(status == -EPIPE) + { + psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; + wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); + } + } + } + return status; +} + +/* +Function: InterfaceEnableInterrupt + +Description: This is the hardware specific Function for configuring + and enabling the interrupts on the device. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + + +Return: BCM_STATUS_SUCCESS - If configuring the interrupts was successful. + Other - If an error occured. +*/ + +void InterfaceEnableInterrupt(PMINI_ADAPTER Adapter) +{ + +} + +/* +Function: InterfaceDisableInterrupt + +Description: This is the hardware specific Function for disabling the interrupts on the device. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + + +Return: BCM_STATUS_SUCCESS - If disabling the interrupts was successful. + Other - If an error occured. +*/ + +void InterfaceDisableInterrupt(PMINI_ADAPTER Adapter) +{ + +} + +#endif + diff --git a/drivers/staging/bcm/InterfaceIsr.h b/drivers/staging/bcm/InterfaceIsr.h new file mode 100644 index 0000000..6065a71 --- /dev/null +++ b/drivers/staging/bcm/InterfaceIsr.h @@ -0,0 +1,15 @@ +#ifndef _INTERFACE_ISR_H +#define _INTERFACE_ISR_H + +int CreateInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter); + + +INT StartInterruptUrb(PS_INTERFACE_ADAPTER psIntfAdapter); + + +VOID InterfaceEnableInterrupt(PMINI_ADAPTER Adapter); + +VOID InterfaceDisableInterrupt(PMINI_ADAPTER Adapter); + +#endif + diff --git a/drivers/staging/bcm/InterfaceMacros.h b/drivers/staging/bcm/InterfaceMacros.h new file mode 100644 index 0000000..7001caf --- /dev/null +++ b/drivers/staging/bcm/InterfaceMacros.h @@ -0,0 +1,18 @@ +#ifndef _INTERFACE_MACROS_H +#define _INTERFACE_MACROS_H + +#define BCM_USB_MAX_READ_LENGTH 2048 + +#define MAXIMUM_USB_TCB 128 +#define MAXIMUM_USB_RCB 128 + +#define MAX_BUFFERS_PER_QUEUE 256 + +#define MAX_DATA_BUFFER_SIZE 2048 + +//Num of Asynchronous reads pending +#define NUM_RX_DESC 64 + +#define SYS_CFG 0x0F000C00 + +#endif diff --git a/drivers/staging/bcm/InterfaceMisc.c b/drivers/staging/bcm/InterfaceMisc.c new file mode 100644 index 0000000..8fc893b --- /dev/null +++ b/drivers/staging/bcm/InterfaceMisc.c @@ -0,0 +1,290 @@ +#include "headers.h" + +#ifndef BCM_SHM_INTERFACE + +PS_INTERFACE_ADAPTER +InterfaceAdapterGet(PMINI_ADAPTER psAdapter) +{ + if(psAdapter == NULL) + { + return NULL; + } + return (PS_INTERFACE_ADAPTER)(psAdapter->pvInterfaceAdapter); +} + +INT +InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, + UINT addr, + PVOID buff, + INT len) +{ + int retval = 0; + USHORT usRetries = 0 ; + if(psIntfAdapter == NULL ) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Interface Adapter is NULL"); + return -EINVAL ; + } + + if(psIntfAdapter->psAdapter->device_removed == TRUE) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed"); + return -ENODEV; + } + + if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus"); + return -EACCES; + } + + if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed.."); + return -EACCES; + } + psIntfAdapter->psAdapter->DeviceAccess = TRUE ; + do { + retval = usb_control_msg(psIntfAdapter->udev, + usb_rcvctrlpipe(psIntfAdapter->udev,0), + 0x02, + 0xC2, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); + + usRetries++ ; + if(-ENODEV == retval) + { + psIntfAdapter->psAdapter->device_removed =TRUE; + break; + } + + }while((retval < 0) && (usRetries < MAX_RDM_WRM_RETIRES ) ); + + if(retval < 0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM failed status :%d, retires :%d", retval,usRetries); + psIntfAdapter->psAdapter->DeviceAccess = FALSE ; + return retval; + } + else + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, RDM, DBG_LVL_ALL, "RDM sent %d", retval); + psIntfAdapter->psAdapter->DeviceAccess = FALSE ; + return STATUS_SUCCESS; + } +} + +INT +InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, + UINT addr, + PVOID buff, + INT len) +{ + int retval = 0; + USHORT usRetries = 0 ; + + if(psIntfAdapter == NULL ) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Interface Adapter is NULL"); + return -EINVAL; + } + if(psIntfAdapter->psAdapter->device_removed == TRUE) + { + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0,"Device got removed"); + return -ENODEV; + } + + if((psIntfAdapter->psAdapter->StopAllXaction == TRUE) && (psIntfAdapter->psAdapter->chip_id >= T3LPB)) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Currently Xaction is not allowed on the bus..."); + return EACCES; + } + + if(psIntfAdapter->bSuspended ==TRUE || psIntfAdapter->bPreparingForBusSuspend == TRUE) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL,"Bus is in suspended states hence RDM not allowed.."); + return -EACCES; + } + psIntfAdapter->psAdapter->DeviceAccess = TRUE ; + do{ + retval = usb_control_msg(psIntfAdapter->udev, + usb_sndctrlpipe(psIntfAdapter->udev,0), + 0x01, + 0x42, + (addr & 0xFFFF), + ((addr >> 16) & 0xFFFF), + buff, + len, + 5000); + + usRetries++ ; + if(-ENODEV == retval) + { + psIntfAdapter->psAdapter->device_removed = TRUE ; + break; + } + + }while((retval < 0) && ( usRetries < MAX_RDM_WRM_RETIRES)); + + if(retval < 0) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM failed status :%d, retires :%d", retval, usRetries); + psIntfAdapter->psAdapter->DeviceAccess = FALSE ; + return retval; + } + else + { + psIntfAdapter->psAdapter->DeviceAccess = FALSE ; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_OTHERS, WRM, DBG_LVL_ALL, "WRM sent %d", retval); + return STATUS_SUCCESS; + + } + +} + +INT +BcmRDM(PVOID arg, + UINT addr, + PVOID buff, + INT len) +{ + return InterfaceRDM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); +} + +INT +BcmWRM(PVOID arg, + UINT addr, + PVOID buff, + INT len) +{ + return InterfaceWRM((PS_INTERFACE_ADAPTER)arg, addr, buff, len); +} + + + +INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter) +{ + PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter); + INT status = STATUS_SUCCESS ; + + /* + usb_clear_halt - tells device to clear endpoint halt/stall condition + @dev: device whose endpoint is halted + @pipe: endpoint "pipe" being cleared + @ Context: !in_interrupt () + + usb_clear_halt is the synchrnous call and returns 0 on success else returns with error code. + This is used to clear halt conditions for bulk and interrupt endpoints only. + Control and isochronous endpoints never halts. + + Any URBs queued for such an endpoint should normally be unlinked by the driver + before clearing the halt condition. + + */ + + //Killing all the submitted urbs to different end points. + Bcm_kill_all_URBs(psIntfAdapter); + + + //clear the halted/stalled state for every end point + status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sIntrIn.int_in_pipe); + if(status != STATUS_SUCCESS) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Interrupt IN end point. :%d ", status); + + status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkIn.bulk_in_pipe); + if(status != STATUS_SUCCESS) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk IN end point. :%d ", status); + + status = usb_clear_halt(psIntfAdapter->udev,psIntfAdapter->sBulkOut.bulk_out_pipe); + if(status != STATUS_SUCCESS) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL, "Unable to Clear Halt of Bulk OUT end point. :%d ", status); + + return status ; +} + + +VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + struct urb *tempUrb = NULL; + UINT i; + + /** + * usb_kill_urb - cancel a transfer request and wait for it to finish + * @urb: pointer to URB describing a previously submitted request, + * returns nothing as it is void returned API. + * + * This routine cancels an in-progress request. It is guaranteed that + * upon return all completion handlers will have finished and the URB + * will be totally idle and available for reuse + + * This routine may not be used in an interrupt context (such as a bottom + * half or a completion handler), or when holding a spinlock, or in other + * situations where the caller can't schedule(). + * + **/ + + /* Cancel submitted Interrupt-URB's */ + if(psIntfAdapter->psInterruptUrb != NULL) + { + if(psIntfAdapter->psInterruptUrb->status == -EINPROGRESS) + usb_kill_urb(psIntfAdapter->psInterruptUrb); + } + + /* Cancel All submitted TX URB's */ + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All Submitted TX Urbs \n"); + + for(i = 0; i < MAXIMUM_USB_TCB; i++) + { + tempUrb = psIntfAdapter->asUsbTcb[i].urb; + if(tempUrb) + { + if(tempUrb->status == -EINPROGRESS) + usb_kill_urb(tempUrb); + } + } + + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Cancelling All submitted Rx Urbs \n"); + + for(i = 0; i < MAXIMUM_USB_RCB; i++) + { + tempUrb = psIntfAdapter->asUsbRcb[i].urb; + if(tempUrb) + { + if(tempUrb->status == -EINPROGRESS) + usb_kill_urb(tempUrb); + } + } + + + atomic_set(&psIntfAdapter->uNumTcbUsed, 0); + atomic_set(&psIntfAdapter->uCurrTcb, 0); + + atomic_set(&psIntfAdapter->uNumRcbUsed, 0); + atomic_set(&psIntfAdapter->uCurrRcb, 0); + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "TCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumTcbUsed), atomic_read(&psIntfAdapter->uCurrTcb)); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "RCB: used- %d cur-%d\n", atomic_read(&psIntfAdapter->uNumRcbUsed), atomic_read(&psIntfAdapter->uCurrRcb)); + +} + +VOID putUsbSuspend(struct work_struct *work) +{ + PS_INTERFACE_ADAPTER psIntfAdapter = NULL ; + struct usb_interface *intf = NULL ; + psIntfAdapter = container_of(work, S_INTERFACE_ADAPTER,usbSuspendWork); + intf=psIntfAdapter->interface ; + + if(psIntfAdapter->bSuspended == FALSE) + usb_autopm_put_interface(intf); + else + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Interface Resumed Completely\n"); + +} + +#endif diff --git a/drivers/staging/bcm/InterfaceMisc.h b/drivers/staging/bcm/InterfaceMisc.h new file mode 100644 index 0000000..74c81d4 --- /dev/null +++ b/drivers/staging/bcm/InterfaceMisc.h @@ -0,0 +1,45 @@ +#ifndef __INTERFACE_MISC_H +#define __INTERFACE_MISC_H + +PS_INTERFACE_ADAPTER +InterfaceAdapterGet(PMINI_ADAPTER psAdapter); + +INT +InterfaceRDM(PS_INTERFACE_ADAPTER psIntfAdapter, + UINT addr, + PVOID buff, + INT len); + +INT +InterfaceWRM(PS_INTERFACE_ADAPTER psIntfAdapter, + UINT addr, + PVOID buff, + INT len); + + +int InterfaceFileDownload( PVOID psIntfAdapter, + struct file *flp, + unsigned int on_chip_loc); + +int InterfaceFileReadbackFromChip( PVOID psIntfAdapter, + struct file *flp, + unsigned int on_chip_loc); + + +int BcmRDM(PVOID arg, + UINT addr, + PVOID buff, + INT len); + +int BcmWRM(PVOID arg, + UINT addr, + PVOID buff, + INT len); + +INT Bcm_clear_halt_of_endpoints(PMINI_ADAPTER Adapter); + +VOID Bcm_kill_all_URBs(PS_INTERFACE_ADAPTER psIntfAdapter); + +#define DISABLE_USB_ZERO_LEN_INT 0x0F011878 + +#endif // __INTERFACE_MISC_H diff --git a/drivers/staging/bcm/InterfaceRx.c b/drivers/staging/bcm/InterfaceRx.c new file mode 100644 index 0000000..6fee968 --- /dev/null +++ b/drivers/staging/bcm/InterfaceRx.c @@ -0,0 +1,256 @@ +#include "headers.h" +extern int SearchVcid(PMINI_ADAPTER , unsigned short); + + +static PUSB_RCB +GetBulkInRcb(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + PUSB_RCB pRcb = NULL; + UINT index = 0; + + if((atomic_read(&psIntfAdapter->uNumRcbUsed) < MAXIMUM_USB_RCB) && + (psIntfAdapter->psAdapter->StopAllXaction == FALSE)) + { + index = atomic_read(&psIntfAdapter->uCurrRcb); + pRcb = &psIntfAdapter->asUsbRcb[index]; + pRcb->bUsed = TRUE; + pRcb->psIntfAdapter= psIntfAdapter; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Got Rx desc %d used %d", + index, atomic_read(&psIntfAdapter->uNumRcbUsed)); + index = (index + 1) % MAXIMUM_USB_RCB; + atomic_set(&psIntfAdapter->uCurrRcb, index); + atomic_inc(&psIntfAdapter->uNumRcbUsed); + } + return pRcb; +} + +/*this is receive call back - when pkt avilable for receive (BULK IN- end point)*/ +static void read_bulk_callback(struct urb *urb) +{ + struct sk_buff *skb = NULL; + BOOLEAN bHeaderSupressionEnabled = FALSE; + int QueueIndex = NO_OF_QUEUES + 1; + UINT uiIndex=0; + int process_done = 1; + //int idleflag = 0 ; + PUSB_RCB pRcb = (PUSB_RCB)urb->context; + PS_INTERFACE_ADAPTER psIntfAdapter = pRcb->psIntfAdapter; + PMINI_ADAPTER Adapter = psIntfAdapter->psAdapter; + PLEADER pLeader = urb->transfer_buffer; + + + #if 0 + int *puiBuffer = NULL; + struct timeval tv; + memset(&tv, 0, sizeof(tv)); + do_gettimeofday(&tv); + #endif + + if((Adapter->device_removed == TRUE) || + (TRUE == Adapter->bEndPointHalted) || + (0 == urb->actual_length) + ) + { + pRcb->bUsed = FALSE; + atomic_dec(&psIntfAdapter->uNumRcbUsed); + return; + } + + if(urb->status != STATUS_SUCCESS) + { + if(urb->status == -EPIPE) + { + Adapter->bEndPointHalted = TRUE ; + wake_up(&Adapter->tx_packet_wait_queue); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"Rx URB has got cancelled. status :%d", urb->status); + } + pRcb->bUsed = FALSE; + atomic_dec(&psIntfAdapter->uNumRcbUsed); + urb->status = STATUS_SUCCESS ; + return ; + } + + if(Adapter->bDoSuspend && (Adapter->bPreparingForLowPowerMode)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"device is going in low power mode while PMU option selected..hence rx packet should not be process"); + return ; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Read back done len %d\n", pLeader->PLength); + if(!pLeader->PLength) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Length 0"); + atomic_dec(&psIntfAdapter->uNumRcbUsed); + return; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "Leader Status:0x%hX, Length:0x%hX, VCID:0x%hX", pLeader->Status,pLeader->PLength,pLeader->Vcid); + if(MAX_CNTL_PKT_SIZE < pLeader->PLength) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Corrupted leader length...%d\n", + pLeader->PLength); + atomic_inc(&Adapter->RxPacketDroppedCount); + atomic_add(pLeader->PLength, &Adapter->BadRxByteCount); + atomic_dec(&psIntfAdapter->uNumRcbUsed); + return; + } + + QueueIndex = SearchVcid( Adapter,pLeader->Vcid); + if(QueueIndex < NO_OF_QUEUES) + { + bHeaderSupressionEnabled = + Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled; + bHeaderSupressionEnabled = + bHeaderSupressionEnabled & Adapter->bPHSEnabled; + } + + skb = dev_alloc_skb (pLeader->PLength + SKB_RESERVE_PHS_BYTES + SKB_RESERVE_ETHERNET_HEADER);//2 //2 for allignment + if(!skb) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "NO SKBUFF!!! Dropping the Packet"); + atomic_dec(&psIntfAdapter->uNumRcbUsed); + return; + } + /* If it is a control Packet, then call handle_bcm_packet ()*/ + if((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) || + (!(pLeader->Status >= 0x20 && pLeader->Status <= 0x3F))) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Recived control pkt..."); + *(PUSHORT)skb->data = pLeader->Status; + memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer + + (sizeof(LEADER)), pLeader->PLength); + skb->len = pLeader->PLength + sizeof(USHORT); + + spin_lock(&Adapter->control_queue_lock); + ENQUEUEPACKET(Adapter->RxControlHead,Adapter->RxControlTail,skb); + spin_unlock(&Adapter->control_queue_lock); + + atomic_inc(&Adapter->cntrlpktCnt); + wake_up(&Adapter->process_rx_cntrlpkt); + } + else + { + /* + * Data Packet, Format a proper Ethernet Header + * and give it to the stack + */ + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt..."); + skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES); + memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(LEADER), pLeader->PLength); + skb->dev = Adapter->dev; + + /* currently skb->len has extra ETH_HLEN bytes in the beginning */ + skb_put (skb, pLeader->PLength + ETH_HLEN); + Adapter->PackInfo[QueueIndex].uiTotalRxBytes+=pLeader->PLength; + Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes+= pLeader->PLength; + atomic_add(pLeader->PLength, &Adapter->GoodRxByteCount); + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt of len :0x%X", pLeader->PLength); + + if(Adapter->if_up) + { + /* Moving ahead by ETH_HLEN to the data ptr as received from FW */ + skb_pull(skb, ETH_HLEN); + PHSRecieve(Adapter, pLeader->Vcid, skb, &skb->len, + NULL,bHeaderSupressionEnabled); + + if(!Adapter->PackInfo[QueueIndex].bEthCSSupport) + { + skb_push(skb, ETH_HLEN); + + memcpy(skb->data, skb->dev->dev_addr, 6); + memcpy(skb->data+6, skb->dev->dev_addr, 6); + (*(skb->data+11))++; + *(skb->data+12) = 0x08; + *(skb->data+13) = 0x00; + pLeader->PLength+=ETH_HLEN; + } + + skb->protocol = eth_type_trans(skb, Adapter->dev); + process_done = netif_rx(skb); + } + else + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "i/f not up hance freeing SKB..."); + bcm_kfree_skb(skb); + } + atomic_inc(&Adapter->GoodRxPktCount); + for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++) + { + if((pLeader->PLength <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) + && (pLeader->PLength > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) + Adapter->aRxPktSizeHist[uiIndex]++; + } + } + Adapter->PrevNumRecvDescs++; + pRcb->bUsed = FALSE; + atomic_dec(&psIntfAdapter->uNumRcbUsed); +} + +static int ReceiveRcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_RCB pRcb) +{ + struct urb *urb = pRcb->urb; + int retval = 0; + + usb_fill_bulk_urb(urb, psIntfAdapter->udev, usb_rcvbulkpipe( + psIntfAdapter->udev, psIntfAdapter->sBulkIn.bulk_in_endpointAddr), + urb->transfer_buffer, BCM_USB_MAX_READ_LENGTH, read_bulk_callback, + pRcb); + if(FALSE == psIntfAdapter->psAdapter->device_removed && + FALSE == psIntfAdapter->psAdapter->bEndPointHalted && + FALSE == psIntfAdapter->bSuspended && + FALSE == psIntfAdapter->bPreparingForBusSuspend) + { + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "failed submitting read urb, error %d", retval); + //if this return value is because of pipe halt. need to clear this. + if(retval == -EPIPE) + { + psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; + wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); + } + + } + } + return retval; +} + +/* +Function: InterfaceRx + +Description: This is the hardware specific Function for Recieveing + data packet/control packets from the device. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + + + +Return: TRUE - If Rx was successful. + Other - If an error occured. +*/ + +BOOLEAN InterfaceRx (PS_INTERFACE_ADAPTER psIntfAdapter) +{ + USHORT RxDescCount = NUM_RX_DESC - atomic_read(&psIntfAdapter->uNumRcbUsed); + PUSB_RCB pRcb = NULL; + +// RxDescCount = psIntfAdapter->psAdapter->CurrNumRecvDescs - +// psIntfAdapter->psAdapter->PrevNumRecvDescs; + while(RxDescCount) + { + pRcb = GetBulkInRcb(psIntfAdapter); + if(pRcb == NULL) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Unable to get Rcb pointer"); + return FALSE; + } + //atomic_inc(&psIntfAdapter->uNumRcbUsed); + ReceiveRcb(psIntfAdapter, pRcb); + RxDescCount--; + } + return TRUE; +} + diff --git a/drivers/staging/bcm/InterfaceRx.h b/drivers/staging/bcm/InterfaceRx.h new file mode 100644 index 0000000..96e81a1 --- /dev/null +++ b/drivers/staging/bcm/InterfaceRx.h @@ -0,0 +1,7 @@ +#ifndef _INTERFACE_RX_H +#define _INTERFACE_RX_H + +BOOLEAN InterfaceRx(PS_INTERFACE_ADAPTER Adapter); + +#endif + diff --git a/drivers/staging/bcm/InterfaceTx.c b/drivers/staging/bcm/InterfaceTx.c new file mode 100644 index 0000000..771f7b3 --- /dev/null +++ b/drivers/staging/bcm/InterfaceTx.c @@ -0,0 +1,259 @@ +#include "headers.h" + +#ifndef BCM_SHM_INTERFACE + +/* +Function: InterfaceTxDataPacket + +Description: This is the hardware specific Function for Transmitting + data packet to the device. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + PVOID Packet - Packet Containing the data to be transmitted + USHORT usVcid - VCID on which data packet is to be sent + + +Return: BCM_STATUS_SUCCESS - If Tx was successful. + Other - If an error occured. +*/ + +ULONG InterfaceTxDataPacket(PMINI_ADAPTER Adapter,PVOID Packet,USHORT usVcid) +{ + ULONG Status = 0; + return Status; +} + +/* +Function: InterfaceTxControlPacket + +Description: This is the hardware specific Function for Transmitting + control packet to the device. + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + PVOID pvBuffer - Buffer containg control packet + UINT uiBufferLength - Buffer Length + +Return: BCM_STATUS_SUCCESS - If control packet transmit was successful. + Other - If an error occured. +*/ + +ULONG InterfaceTxControlPacket(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT uiBufferLength) +{ + ULONG Status = 0; + + + + return Status; +} +/*this is transmit call-back(BULK OUT)*/ +static void write_bulk_callback(struct urb *urb/*, struct pt_regs *regs*/) +{ + PUSB_TCB pTcb= (PUSB_TCB)urb->context; + PS_INTERFACE_ADAPTER psIntfAdapter = pTcb->psIntfAdapter; + CONTROL_MESSAGE *pControlMsg = (CONTROL_MESSAGE *)urb->transfer_buffer; + PMINI_ADAPTER psAdapter = psIntfAdapter->psAdapter ; + BOOLEAN bpowerDownMsg = FALSE ; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); +#if 0 + struct timeval tv; + UINT time_ms = 0; +#endif + if(urb->status != STATUS_SUCCESS) + { + if(urb->status == -EPIPE) + { + psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; + wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Tx URB has got cancelled. status :%d", urb->status); + } + } + + pTcb->bUsed = FALSE; + atomic_dec(&psIntfAdapter->uNumTcbUsed); + + + + if(TRUE == psAdapter->bPreparingForLowPowerMode) + { + #if 0 + do_gettimeofday(&tv); + time_ms = tv.tv_sec *1000 + tv.tv_usec/1000; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, " %s Idle Mode ACK_Sent got from device at time :0x%x", __FUNCTION__, time_ms); + #endif + + if(((pControlMsg->szData[0] == GO_TO_IDLE_MODE_PAYLOAD) && + (pControlMsg->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE))) + + { + bpowerDownMsg = TRUE ; + //This covers the bus err while Idle Request msg sent down. + if(urb->status != STATUS_SUCCESS) + { + psAdapter->bPreparingForLowPowerMode = FALSE ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Idle Mode Request msg failed to reach to Modem"); + //Signalling the cntrl pkt path in Ioctl + wake_up(&psAdapter->lowpower_mode_wait_queue); + StartInterruptUrb(psIntfAdapter); + goto err_exit; + } + + if(psAdapter->bDoSuspend == FALSE) + { + psAdapter->IdleMode = TRUE; + //since going in Idle mode completed hence making this var false; + psAdapter->bPreparingForLowPowerMode = FALSE ; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Host Entered in Idle Mode State..."); + //Signalling the cntrl pkt path in Ioctl + wake_up(&psAdapter->lowpower_mode_wait_queue); + } + + } + else if((pControlMsg->Leader.Status == LINK_UP_CONTROL_REQ) && + (pControlMsg->szData[0] == LINK_UP_ACK) && + (pControlMsg->szData[1] == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) && + (pControlMsg->szData[2] == SHUTDOWN_ACK_FROM_DRIVER)) + { + //This covers the bus err while shutdown Request msg sent down. + if(urb->status != STATUS_SUCCESS) + { + psAdapter->bPreparingForLowPowerMode = FALSE ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Shutdown Request Msg failed to reach to Modem"); + //Signalling the cntrl pkt path in Ioctl + wake_up(&psAdapter->lowpower_mode_wait_queue); + StartInterruptUrb(psIntfAdapter); + goto err_exit; + } + + bpowerDownMsg = TRUE ; + if(psAdapter->bDoSuspend == FALSE) + { + psAdapter->bShutStatus = TRUE; + //since going in shutdown mode completed hence making this var false; + psAdapter->bPreparingForLowPowerMode = FALSE ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Host Entered in shutdown Mode State..."); + //Signalling the cntrl pkt path in Ioctl + wake_up(&psAdapter->lowpower_mode_wait_queue); + } + } + + if(psAdapter->bDoSuspend && bpowerDownMsg) + { + //issuing bus suspend request + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"Issuing the Bus suspend request to USB stack"); + psIntfAdapter->bPreparingForBusSuspend = TRUE; + schedule_work(&psIntfAdapter->usbSuspendWork); + + } + + } + +err_exit : +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) + usb_buffer_free(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); +#else + usb_free_coherent(urb->dev, urb->transfer_buffer_length, + urb->transfer_buffer, urb->transfer_dma); +#endif +} + + +static __inline PUSB_TCB GetBulkOutTcb(PS_INTERFACE_ADAPTER psIntfAdapter) +{ + PUSB_TCB pTcb = NULL; + UINT index = 0; + + if((atomic_read(&psIntfAdapter->uNumTcbUsed) < MAXIMUM_USB_TCB) && + (psIntfAdapter->psAdapter->StopAllXaction ==FALSE)) + { + index = atomic_read(&psIntfAdapter->uCurrTcb); + pTcb = &psIntfAdapter->asUsbTcb[index]; + pTcb->bUsed = TRUE; + pTcb->psIntfAdapter= psIntfAdapter; + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got Tx desc %d used %d", + index, atomic_read(&psIntfAdapter->uNumTcbUsed)); + index = (index + 1) % MAXIMUM_USB_TCB; + atomic_set(&psIntfAdapter->uCurrTcb, index); + atomic_inc(&psIntfAdapter->uNumTcbUsed); + } + return pTcb; +} + +static __inline int TransmitTcb(PS_INTERFACE_ADAPTER psIntfAdapter, PUSB_TCB pTcb, PVOID data, int len) +{ + + struct urb *urb = pTcb->urb; + int retval = 0; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) + urb->transfer_buffer = usb_buffer_alloc(psIntfAdapter->udev, len, + GFP_ATOMIC, &urb->transfer_dma); +#else + urb->transfer_buffer = usb_alloc_coherent(psIntfAdapter->udev, len, + GFP_ATOMIC, &urb->transfer_dma); +#endif + + if (!urb->transfer_buffer) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "Error allocating memory\n"); + return -ENOMEM; + } + memcpy(urb->transfer_buffer, data, len); + urb->transfer_buffer_length = len; + + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending Bulk out packet\n"); + //For T3B,INT OUT end point will be used as bulk out end point + if((psIntfAdapter->psAdapter->chip_id == T3B) && (psIntfAdapter->bHighSpeedDevice == TRUE)) + { + usb_fill_int_urb(urb, psIntfAdapter->udev, + psIntfAdapter->sBulkOut.bulk_out_pipe, + urb->transfer_buffer, len, write_bulk_callback, pTcb, + psIntfAdapter->sBulkOut.int_out_interval); + } + else + { + usb_fill_bulk_urb(urb, psIntfAdapter->udev, + psIntfAdapter->sBulkOut.bulk_out_pipe, + urb->transfer_buffer, len, write_bulk_callback, pTcb); + } + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; /* For DMA transfer */ + + if(FALSE == psIntfAdapter->psAdapter->device_removed && + FALSE == psIntfAdapter->psAdapter->bEndPointHalted && + FALSE == psIntfAdapter->bSuspended && + FALSE == psIntfAdapter->bPreparingForBusSuspend) + { + retval = usb_submit_urb(urb, GFP_ATOMIC); + if (retval) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "failed submitting write urb, error %d", retval); + if(retval == -EPIPE) + { + psIntfAdapter->psAdapter->bEndPointHalted = TRUE ; + wake_up(&psIntfAdapter->psAdapter->tx_packet_wait_queue); + } + } + } + return retval; +} + +int InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len) +{ + PUSB_TCB pTcb= NULL; + + PS_INTERFACE_ADAPTER psIntfAdapter = (PS_INTERFACE_ADAPTER)arg; + pTcb= GetBulkOutTcb(psIntfAdapter); + if(pTcb == NULL) + { + BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_PRINTK, 0, 0, "No URB to transmit packet, dropping packet"); + return -EFAULT; + } + return TransmitTcb(psIntfAdapter, pTcb, data, len); +} + +#endif + diff --git a/drivers/staging/bcm/InterfaceTx.h b/drivers/staging/bcm/InterfaceTx.h new file mode 100644 index 0000000..053f631 --- /dev/null +++ b/drivers/staging/bcm/InterfaceTx.h @@ -0,0 +1,13 @@ +#ifndef _INTERFACE_TX_H +#define _INTERFACE_TX_H + +INT InterfaceTransmitPacket(PVOID arg, PVOID data, UINT len); + + +ULONG InterfaceTxDataPacket(PMINI_ADAPTER Adapter,PVOID Packet,USHORT usVcid); + +ULONG InterfaceTxControlPacket(PMINI_ADAPTER Adapter,PVOID pvBuffer,UINT uiBufferLength); + + +#endif + diff --git a/drivers/staging/bcm/Interfacemain.h b/drivers/staging/bcm/Interfacemain.h new file mode 100644 index 0000000..e0db563 --- /dev/null +++ b/drivers/staging/bcm/Interfacemain.h @@ -0,0 +1,10 @@ +#ifndef _MAIN_ +#define _MAIN_ +#if 0 +typedef struct _MINI_ADAPTER +{ + S_INTERFACE_ADAPTER stInterfaceAdapter; +}MINI_ADAPTER,*PMINI_ADAPTER; + +#endif +#endif diff --git a/drivers/staging/bcm/Ioctl.h b/drivers/staging/bcm/Ioctl.h new file mode 100644 index 0000000..2651fc2 --- /dev/null +++ b/drivers/staging/bcm/Ioctl.h @@ -0,0 +1,360 @@ +#ifndef _IOCTL_H_ +#define _IOCTL_H_ + +typedef struct rdmbuffer +{ + ULONG Register; + ULONG Length; +}__attribute__((packed)) RDM_BUFFER, *PRDM_BUFFER; + + +typedef struct wrmbuffer +{ + ULONG Register; + ULONG Length; + UCHAR Data[4]; +}__attribute__((packed)) WRM_BUFFER, *PWRM_BUFFER; + + +typedef struct ioctlbuffer +{ + PVOID InputBuffer; + ULONG InputLength; + PVOID OutputBuffer; + ULONG OutputLength; +}__attribute__((packed)) IOCTL_BUFFER, *PIOCTL_BUFFER; + +typedef struct stGPIOInfo +{ + UINT uiGpioNumber ; /* valid numbers 0-15 */ + UINT uiGpioValue; /* 1 set ; 0 not set */ +}__attribute__((packed))GPIO_INFO,*PGPIO_INFO; +typedef struct stUserThreadReq +{ + //0->Inactivate LED thread. + //1->Activate the LED thread + UINT ThreadState; +}__attribute__((packed))USER_THREAD_REQ,*PUSER_THREAD_REQ; +#define LED_THREAD_ACTIVATION_REQ 1 + + +////********** ioctl codes ***********//// + +#define BCM_IOCTL 'k' + +//1.Control code for CONTROL MESSAGES + +#define IOCTL_SEND_CONTROL_MESSAGE _IOW(BCM_IOCTL, 0x801,int) + +//2.Control code to write a particular value to a particular register +#define IOCTL_BCM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x802, int) // + +//3. +#define IOCTL_BCM_REGISTER_READ _IOR(BCM_IOCTL, 0x803, int) // + +//4.Control code to write x number of bytes to common memory +//starting from address y +#define IOCTL_BCM_COMMON_MEMORY_WRITE _IOW(BCM_IOCTL, 0x804, int)// + +//5.Control code to write x number of bytes to common memory +//starting from address y +#define IOCTL_BCM_COMMON_MEMORY_READ _IOR(BCM_IOCTL, 0x805, int)// + +//6.Control code for CONTROL MESSAGES +#define IOCTL_GET_CONTROL_MESSAGE _IOR(BCM_IOCTL, 0x806, int)// + +//7.Control code for FIRMWARE DOWNLOAD +#define IOCTL_BCM_FIRMWARE_DOWNLOAD _IOW(BCM_IOCTL, 0x807, int)// + +#define IOCTL_BCM_SET_SEND_VCID _IOW(BCM_IOCTL, 0x808, int) + +//9.Control code for TRANSFER MODE SWITCHING +#define IOCTL_BCM_SWITCH_TRANSFER_MODE _IOW(BCM_IOCTL, 0x809, int) +//10.Control code for LINK UP +#define IOCTL_LINK_REQ _IOW(BCM_IOCTL, 0x80A, int) + +//11.Control code for RSSI Level Request +#define IOCTL_RSSI_LEVEL_REQ _IOW(BCM_IOCTL, 0x80B, int) +//12.Control code for IDLE MODE CONTROL +#define IOCTL_IDLE_REQ _IOW(BCM_IOCTL, 0x80C, int) +//13.Control code for SS/BS info +#define IOCTL_SS_INFO_REQ _IOW(BCM_IOCTL, 0x80D, int) + +#define IOCTL_GET_STATISTICS_POINTER _IOW(BCM_IOCTL, 0x80E, int) + +#define IOCTL_CM_REQUEST _IOW(BCM_IOCTL, 0x80F, int) + +#define IOCTL_INIT_PARAM_REQ _IOW(BCM_IOCTL, 0x810, int) + +#define IOCTL_MAC_ADDR_REQ _IOW(BCM_IOCTL, 0x811, int) + +#define IOCTL_MAC_ADDR_RESP _IOWR(BCM_IOCTL, 0x812, int) + +#define IOCTL_CLASSIFICATION_RULE _IOW(BCM_IOCTL, 0x813, char) + +#define IOCTL_CLOSE_NOTIFICATION _IO(BCM_IOCTL, 0x814) + +#define IOCTL_LINK_UP _IO(BCM_IOCTL, 0x815) + +#define IOCTL_LINK_DOWN _IO(BCM_IOCTL, 0x816, IOCTL_BUFFER) + +#define IOCTL_CHIP_RESET _IO(BCM_IOCTL, 0x816) + +#define IOCTL_CINR_LEVEL_REQ _IOW(BCM_IOCTL, 0x817, char) + +#define IOCTL_WTM_CONTROL_REQ _IOW(BCM_IOCTL, 0x817,char) + +#define IOCTL_BE_BUCKET_SIZE _IOW(BCM_IOCTL, 0x818, unsigned long) + +#define IOCTL_RTPS_BUCKET_SIZE _IOW(BCM_IOCTL, 0x819, unsigned long) + +#define IOCTL_QOS_THRESHOLD _IOW(BCM_IOCTL, 0x820, unsigned long) + +#define IOCTL_DUMP_PACKET_INFO _IO(BCM_IOCTL, 0x821) + +#define IOCTL_GET_PACK_INFO _IOR(BCM_IOCTL, 0x823, int) + +#define IOCTL_BCM_GET_DRIVER_VERSION _IOR(BCM_IOCTL, 0x829, int) + +#define IOCTL_BCM_GET_CURRENT_STATUS _IOW(BCM_IOCTL, 0x828, int) + +#define IOCTL_BCM_GPIO_SET_REQUEST _IOW(BCM_IOCTL, 0x82A, int) + +#define IOCTL_BCM_GPIO_STATUS_REQUEST _IOW(BCM_IOCTL, 0x82b, int) + +#define IOCTL_BCM_GET_DSX_INDICATION _IOR(BCM_IOCTL, 0x854, int) + +#define IOCTL_BCM_BUFFER_DOWNLOAD_START _IOW(BCM_IOCTL, 0x855, int) + +#define IOCTL_BCM_BUFFER_DOWNLOAD _IOW(BCM_IOCTL, 0x856, int) + +#define IOCTL_BCM_BUFFER_DOWNLOAD_STOP _IOW(BCM_IOCTL, 0x857, int) + +#define IOCTL_BCM_REGISTER_WRITE_PRIVATE _IOW(BCM_IOCTL, 0x826, char) + +#define IOCTL_BCM_REGISTER_READ_PRIVATE _IOW(BCM_IOCTL, 0x827, char) + +#define IOCTL_BCM_SET_DEBUG _IOW(BCM_IOCTL, 0x824, IOCTL_BUFFER) + +#define IOCTL_BCM_EEPROM_REGISTER_WRITE _IOW(BCM_IOCTL, 0x858, int) + +#define IOCTL_BCM_EEPROM_REGISTER_READ _IOR(BCM_IOCTL, 0x859, int) + +#define IOCTL_BCM_WAKE_UP_DEVICE_FROM_IDLE _IOR(BCM_IOCTL, 0x860, int) + +#define IOCTL_BCM_SET_MAC_TRACING _IOW(BCM_IOCTL, 0x82c, int) + +#define IOCTL_BCM_GET_HOST_MIBS _IOW(BCM_IOCTL, 0x853, int) + +#define IOCTL_BCM_NVM_READ _IOR(BCM_IOCTL, 0x861, int) + +#define IOCTL_BCM_NVM_WRITE _IOW(BCM_IOCTL, 0x862, int) + +#define IOCTL_BCM_GET_NVM_SIZE _IOR(BCM_IOCTL, 0x863, int) + +#define IOCTL_BCM_CAL_INIT _IOR(BCM_IOCTL, 0x864, int) + +#define IOCTL_BCM_BULK_WRM _IOW(BCM_IOCTL, 0x90B, int) + +#define IOCTL_BCM_FLASH2X_SECTION_READ _IOR(BCM_IOCTL, 0x865, int) + +#define IOCTL_BCM_FLASH2X_SECTION_WRITE _IOW(BCM_IOCTL, 0x866, int) + +#define IOCTL_BCM_GET_FLASH2X_SECTION_BITMAP _IOR(BCM_IOCTL,0x867, int) + +#define IOCTL_BCM_SET_ACTIVE_SECTION _IOW(BCM_IOCTL,0x868, int) + +#define IOCTL_BCM_IDENTIFY_ACTIVE_SECTION _IO(BCM_IOCTL,0x869) + +#define IOCTL_BCM_COPY_SECTION _IOW(BCM_IOCTL, 0x870,int) + +#define IOCTL_BCM_GET_FLASH_CS_INFO _IOR(BCM_IOCTL, 0x871, int) + +#define IOCTL_BCM_SELECT_DSD _IOW(BCM_IOCTL, 0x872, int) + +#define IOCTL_BCM_NVM_RAW_READ _IOR(BCM_IOCTL, 0x875, int) + +#define IOCTL_BCM_CNTRLMSG_MASK _IOW(BCM_IOCTL, 0x874, int) + +#define IOCTL_BCM_GET_DEVICE_DRIVER_INFO _IOR(BCM_IOCTL, 0x877, int) + +#define IOCTL_BCM_TIME_SINCE_NET_ENTRY _IOR(BCM_IOCTL, 0x876, int) + +#define BCM_LED_THREAD_STATE_CHANGE_REQ _IOW(BCM_IOCTL, 0x878, int) + +#define IOCTL_BCM_GPIO_MULTI_REQUEST _IOW(BCM_IOCTL, 0x82D, IOCTL_BUFFER) +#define IOCTL_BCM_GPIO_MODE_REQUEST _IOW(BCM_IOCTL, 0x82E, IOCTL_BUFFER) + + + +typedef enum _BCM_INTERFACE_TYPE +{ + BCM_MII, + BCM_CARDBUS, + BCM_USB, + BCM_SDIO, + BCM_PCMCIA +}BCM_INTERFACE_TYPE; + +typedef struct _DEVICE_DRIVER_INFO +{ + NVM_TYPE u32NVMType; + UINT MaxRDMBufferSize; + BCM_INTERFACE_TYPE u32InterfaceType; + UINT u32DSDStartOffset; + UINT u32RxAlignmentCorrection; + UINT u32Reserved[10]; +} DEVICE_DRIVER_INFO; + +typedef struct _NVM_READWRITE +{ + + void *pBuffer; +// Data to be written from|read to. Memory should be allocated by the caller. + + uint32_t uiOffset; +// offset at which data should be written to or read from. + + uint32_t uiNumBytes; +// No. of bytes to be written or read. + + bool bVerify; +// Applicable only for write. If set verification of written data will be done. + +} NVM_READWRITE,*PNVM_READWRITE; +typedef struct bulkwrmbuffer +{ + ULONG Register; + ULONG SwapEndian; + ULONG Values[1]; + +}BULKWRM_BUFFER,*PBULKWRM_BUFFER; + + +/***********Structure used for FlashMap2.x *******************************/ + +/* +* These are Sction present inside the Flash. +* There is sectional RD/WR for flash Map 2.x. +* hence these section will be used in read/write API. +*/ + +typedef enum _FLASH2X_SECTION_VAL +{ + NO_SECTION_VAL = 0, //no section is choosen when absolute offset is given for RD/WR + ISO_IMAGE1, + ISO_IMAGE2, + DSD0, + DSD1, + DSD2, + VSA0, + VSA1, + VSA2, + SCSI, + CONTROL_SECTION, + ISO_IMAGE1_PART2, + ISO_IMAGE1_PART3, + ISO_IMAGE2_PART2, + ISO_IMAGE2_PART3, + TOTAL_SECTIONS +}FLASH2X_SECTION_VAL; + +/* +* Structure used for READ/WRITE Flash Map2.x +*/ +typedef struct _FLASH2X_READWRITE +{ + + FLASH2X_SECTION_VAL Section; //which section has to be read/written + B_UINT32 offset; //Offset within Section. + B_UINT32 numOfBytes; //NOB from the offset + B_UINT32 bVerify; + PVOID pDataBuff; //Buffer for reading/writing + +}FLASH2X_READWRITE, *PFLASH2X_READWRITE; +/* +* This structure is used for coping one section to other. +* there are two ways to copy one section to other. +* it NOB =0, complete section will be copied on to other. +* if NOB !=0, only NOB will be copied from the given offset. +*/ + +typedef struct _FLASH2X_COPY_SECTION +{ + //Src Section from which Data has to be copied to DstSection + FLASH2X_SECTION_VAL SrcSection; + + //Destination Section from where Data has to be coppied. + FLASH2X_SECTION_VAL DstSection; + + //Offset within Section. if NOB =0 it will be ignored and data will be coped from offset 0. + B_UINT32 offset; + + //NOB from the offset. if NOB = 0 complete src section will be copied to Destination section. + B_UINT32 numOfBytes; +} FLASH2X_COPY_SECTION, *PFLASH2X_COPY_SECTION; + + +typedef enum _SECTION_TYPE +{ + ISO = 0, + VSA = 1, + DSD = 2 +} SECTION_TYPE, *PSECTION_TYPE; + +/* +* This section provide the complete bitmap of the Flash. +* using this map lib/APP will isssue read/write command. + Fields are defined as : + Bit [0] = section is present //1:present, 0: Not present +* Bit [1] = section is valid //1: valid, 0: not valid +* Bit [2] = Section is R/W //0: RW, 1: RO +* Bit [3] = Section is Active or not 1 means Active, 0->inactive +* Bit [7...3] = Reserved +*/ + +typedef struct _FLASH2X_BITMAP +{ + UCHAR ISO_IMAGE1; + UCHAR ISO_IMAGE2; + UCHAR DSD0; + UCHAR DSD1; + UCHAR DSD2; + UCHAR VSA0; + UCHAR VSA1; + UCHAR VSA2; + UCHAR SCSI; + UCHAR CONTROL_SECTION; + //Reserved for future use + UCHAR Reserved0; + UCHAR Reserved1; + UCHAR Reserved2; +}FLASH2X_BITMAP, *PFLASH2X_BITMAP; + +//for net entry time check +typedef struct _ST_TIME_ELAPSED_ +{ + ULONG64 ul64TimeElapsedSinceNetEntry; + UINT32 uiReserved[4]; //By chance if required for future proofing +}ST_TIME_ELAPSED,*PST_TIME_ELAPSED; + +enum { + WIMAX_IDX=0, /*To access WiMAX chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE*/ + HOST_IDX, /*To access Host chip GPIO's for GPIO_MULTI_INFO or GPIO_MULTI_MODE*/ + MAX_IDX +}; +typedef struct stGPIOMultiInfo +{ + UINT uiGPIOCommand; /* 1 for set and 0 for get*/ + UINT uiGPIOMask; /* set the correspondig bit to 1 to access GPIO*/ + UINT uiGPIOValue; /* 0 or 1; value to be set when command is 1.*/ +}__attribute__((packed))GPIO_MULTI_INFO , *PGPIO_MULTI_INFO; + +typedef struct stGPIOMultiMode +{ + UINT uiGPIOMode; /* 1 for OUT mode, 0 for IN mode*/ + UINT uiGPIOMask; /* GPIO mask to set mode*/ +}__attribute__((packed))GPIO_MULTI_MODE, *PGPIO_MULTI_MODE; + + +#endif diff --git a/drivers/staging/bcm/Kconfig b/drivers/staging/bcm/Kconfig new file mode 100644 index 0000000..96adb10 --- /dev/null +++ b/drivers/staging/bcm/Kconfig @@ -0,0 +1,7 @@ +config BCM_WIMAX + tristate "Beceem BCS200/BCS220-3 and BCSM250 wimax support" + depends on USB && NET && EXPERIMENTAL + default N + help + This is an experimental driver for the Beceem WIMAX chipset used + by Sprint 4G. diff --git a/drivers/staging/bcm/LeakyBucket.c b/drivers/staging/bcm/LeakyBucket.c new file mode 100644 index 0000000..1875c82 --- /dev/null +++ b/drivers/staging/bcm/LeakyBucket.c @@ -0,0 +1,399 @@ +/********************************************************************** +* LEAKYBUCKET.C +* This file contains the routines related to Leaky Bucket Algorithm. +***********************************************************************/ +#include "headers.h" + +/********************************************************************* +* Function - UpdateTokenCount() +* +* Description - This function calculates the token count for each +* channel and updates the same in Adapter strucuture. +* +* Parameters - Adapter: Pointer to the Adapter structure. +* +* Returns - None +**********************************************************************/ + +VOID UpdateTokenCount(register PMINI_ADAPTER Adapter) +{ + ULONG liCurrentTime; + INT i = 0; + struct timeval tv; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "=====>\n"); + if(NULL == Adapter) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Adapter found NULL!\n"); + return; + } + + do_gettimeofday(&tv); + for(i = 0; i < NO_OF_QUEUES; i++) + { + if(TRUE == Adapter->PackInfo[i].bValid && + (1 == Adapter->PackInfo[i].ucDirection)) + { + liCurrentTime = ((tv.tv_sec- + Adapter->PackInfo[i].stLastUpdateTokenAt.tv_sec)*1000 + + (tv.tv_usec-Adapter->PackInfo[i].stLastUpdateTokenAt.tv_usec)/ + 1000); + if(0!=liCurrentTime) + { + Adapter->PackInfo[i].uiCurrentTokenCount += (ULONG) + ((Adapter->PackInfo[i].uiMaxAllowedRate) * + ((ULONG)((liCurrentTime)))/1000); + memcpy(&Adapter->PackInfo[i].stLastUpdateTokenAt, + &tv, sizeof(struct timeval)); + Adapter->PackInfo[i].liLastUpdateTokenAt = liCurrentTime; + if((Adapter->PackInfo[i].uiCurrentTokenCount) >= + Adapter->PackInfo[i].uiMaxBucketSize) + { + Adapter->PackInfo[i].uiCurrentTokenCount = + Adapter->PackInfo[i].uiMaxBucketSize; + } + } + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "<=====\n"); + return; + +} + + +/********************************************************************* +* Function - IsPacketAllowedForFlow() +* +* Description - This function checks whether the given packet from the +* specified queue can be allowed for transmission by +* checking the token count. +* +* Parameters - Adapter : Pointer to the Adpater structure. +* - iQIndex : The queue Identifier. +* - ulPacketLength: Number of bytes to be transmitted. +* +* Returns - The number of bytes allowed for transmission. +* +***********************************************************************/ +static __inline ULONG GetSFTokenCount(PMINI_ADAPTER Adapter, PacketInfo *psSF) +{ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow ===>"); + /* Validate the parameters */ + if(NULL == Adapter || (psSF < Adapter->PackInfo && + (UINT)psSF > (UINT) &Adapter->PackInfo[HiPriority])) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Got wrong Parameters:Adapter: %p, QIndex: %d\n", Adapter, (psSF-Adapter->PackInfo)); + return 0; + } + + if(FALSE != psSF->bValid && psSF->ucDirection) + { + if(0 != psSF->uiCurrentTokenCount) + { + return psSF->uiCurrentTokenCount; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "Not enough tokens in queue %d Available %u\n", + psSF-Adapter->PackInfo, psSF->uiCurrentTokenCount); + psSF->uiPendedLast = 1; + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IPAFF: Queue %d not valid\n", psSF-Adapter->PackInfo); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TOKEN_COUNTS, DBG_LVL_ALL, "IsPacketAllowedForFlow <==="); + return 0; +} + +static __inline void RemovePacketFromQueue(PacketInfo *pPackInfo , struct sk_buff *Packet) +{ + struct sk_buff *psQueueCurrent=NULL, *psLastQueueNode=NULL; + psQueueCurrent = pPackInfo->FirstTxQueue; + while(psQueueCurrent) + { + if((UINT)Packet == (UINT)psQueueCurrent) + { + if((UINT)psQueueCurrent == (UINT)pPackInfo->FirstTxQueue) + { + pPackInfo->FirstTxQueue=psQueueCurrent->next; + if((UINT)psQueueCurrent==(UINT)pPackInfo->LastTxQueue) + pPackInfo->LastTxQueue=NULL; + } + else + { + psLastQueueNode->next=psQueueCurrent->next; + } + break; + } + psLastQueueNode = psQueueCurrent; + psQueueCurrent=psQueueCurrent->next; + } +} +/** +@ingroup tx_functions +This function despatches packet from the specified queue. +@return Zero(success) or Negative value(failure) +*/ +static __inline INT SendPacketFromQueue(PMINI_ADAPTER Adapter,/**"); + if(!Adapter || !Packet || !psSF) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "Got NULL Adapter or Packet"); + return -EINVAL; + } + + if(psSF->liDrainCalculated==0) + { + psSF->liDrainCalculated = jiffies; + } + ///send the packet to the fifo.. + PktLen = Packet->len; + Status = SetupNextSend(Adapter, Packet, psSF->usVCID_Value); + if(Status == 0) + { + for(uiIndex = 0 ; uiIndex < MIBS_MAX_HIST_ENTRIES ; uiIndex++) + { if((PktLen <= MIBS_PKTSIZEHIST_RANGE*(uiIndex+1)) && (PktLen > MIBS_PKTSIZEHIST_RANGE*(uiIndex))) + Adapter->aTxPktSizeHist[uiIndex]++; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, SEND_QUEUE, DBG_LVL_ALL, "<====="); + return Status; +} + +/************************************************************************ +* Function - CheckAndSendPacketFromIndex() +* +* Description - This function dequeues the data/control packet from the +* specified queue for transmission. +* +* Parameters - Adapter : Pointer to the driver control structure. +* - iQIndex : The queue Identifier. +* +* Returns - None. +* +****************************************************************************/ +static __inline VOID CheckAndSendPacketFromIndex +(PMINI_ADAPTER Adapter, PacketInfo *psSF) +{ + struct sk_buff *QueuePacket=NULL; + char *pControlPacket = NULL; + INT Status=0; + int iPacketLen=0; + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "%d ====>", (psSF-Adapter->PackInfo)); + if(((UINT)psSF != (UINT)&Adapter->PackInfo[HiPriority]) && Adapter->LinkUpStatus && atomic_read(&psSF->uiPerSFTxResourceCount))//Get data packet + { + if(!psSF->ucDirection ) + return; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "UpdateTokenCount "); + if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle Mode..Hence blocking Data Packets..\n"); + return; + } + // Check for Free Descriptors + if(atomic_read(&Adapter->CurrNumFreeTxDesc) <= MINIMUM_PENDING_DESCRIPTORS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " No Free Tx Descriptor(%d) is available for Data pkt..",atomic_read(&Adapter->CurrNumFreeTxDesc)); + return ; + } + +#if 0 + PruneQueue(Adapter,(psSF-Adapter->PackInfo)); +#endif + spin_lock_bh(&psSF->SFQueueLock); + QueuePacket=psSF->FirstTxQueue; + + if(QueuePacket) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Dequeuing Data Packet"); + + if(psSF->bEthCSSupport) + iPacketLen = QueuePacket->len; + else + iPacketLen = QueuePacket->len-ETH_HLEN; + + iPacketLen<<=3; + if(iPacketLen <= GetSFTokenCount(Adapter, psSF)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Allowed bytes %d", + (iPacketLen >> 3)); + + DEQUEUEPACKET(psSF->FirstTxQueue,psSF->LastTxQueue); + psSF->uiCurrentBytesOnHost -= (QueuePacket->len); + psSF->uiCurrentPacketsOnHost--; + atomic_dec(&Adapter->TotalPacketCount); + spin_unlock_bh(&psSF->SFQueueLock); + + Status = SendPacketFromQueue(Adapter, psSF, QueuePacket); + psSF->uiPendedLast = FALSE; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %d\n", psSF-Adapter->PackInfo); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n", + psSF->uiCurrentTokenCount, iPacketLen); + //this part indicates that becuase of non-availability of the tokens + //pkt has not been send out hence setting the pending flag indicating the host to send it out + //first next iteration . + psSF->uiPendedLast = TRUE; + spin_unlock_bh(&psSF->SFQueueLock); + } + } + else + { + spin_unlock_bh(&psSF->SFQueueLock); + } + } + else + { + + if((atomic_read(&Adapter->CurrNumFreeTxDesc) > 0 ) && + (atomic_read(&Adapter->index_rd_txcntrlpkt) != + atomic_read(&Adapter->index_wr_txcntrlpkt)) + ) + { + pControlPacket = Adapter->txctlpacket + [(atomic_read(&Adapter->index_rd_txcntrlpkt)%MAX_CNTRL_PKTS)]; + if(pControlPacket) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Sending Control packet"); + Status = SendControlPacket(Adapter, pControlPacket); + if(STATUS_SUCCESS==Status) + { + spin_lock_bh(&psSF->SFQueueLock); + psSF->NumOfPacketsSent++; + psSF->uiSentBytes+=((PLEADER)pControlPacket)->PLength; + psSF->uiSentPackets++; + atomic_dec(&Adapter->TotalPacketCount); + psSF->uiCurrentBytesOnHost -= ((PLEADER)pControlPacket)->PLength; + psSF->uiCurrentPacketsOnHost--; + atomic_inc(&Adapter->index_rd_txcntrlpkt); + spin_unlock_bh(&psSF->SFQueueLock); + } + else + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "SendControlPacket Failed\n"); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, " Control Pkt is not available, Indexing is wrong...."); + } + } + } + + if(Status != STATUS_SUCCESS) //Tx of data packet to device Failed + { + if(Adapter->bcm_jiffies == 0) + Adapter->bcm_jiffies = jiffies; + } + else + { + Adapter->bcm_jiffies = 0; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<====="); +} + + +/******************************************************************* +* Function - transmit_packets() +* +* Description - This function transmits the packets from different +* queues, if free descriptors are available on target. +* +* Parameters - Adapter: Pointer to the Adapter structure. +* +* Returns - None. +********************************************************************/ +VOID transmit_packets(PMINI_ADAPTER Adapter) +{ + UINT uiPrevTotalCount = 0; + int iIndex = 0; + + BOOLEAN exit_flag = TRUE ; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "=====>"); + + if(NULL == Adapter) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX,TX_PACKETS, DBG_LVL_ALL, "Got NULL Adapter"); + return; + } + if(Adapter->device_removed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device removed"); + return; + } + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nUpdateTokenCount ====>\n"); + + UpdateTokenCount(Adapter); + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nPruneQueueAllSF ====>\n"); + + PruneQueueAllSF(Adapter); + + uiPrevTotalCount = atomic_read(&Adapter->TotalPacketCount); + + for(iIndex=HiPriority;iIndex>=0;iIndex--) + { + if( !uiPrevTotalCount || (TRUE == Adapter->device_removed)) + break; + + if(Adapter->PackInfo[iIndex].bValid && + Adapter->PackInfo[iIndex].uiPendedLast && + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); + CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); + uiPrevTotalCount--; + } + } + + while(uiPrevTotalCount > 0 && !Adapter->device_removed) + { + exit_flag = TRUE ; + //second iteration to parse non-pending queues + for(iIndex=HiPriority;iIndex>=0;iIndex--) + { + if( !uiPrevTotalCount || (TRUE == Adapter->device_removed)) + break; + + if(Adapter->PackInfo[iIndex].bValid && + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost && + !Adapter->PackInfo[iIndex].uiPendedLast ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling CheckAndSendPacketFromIndex.."); + CheckAndSendPacketFromIndex(Adapter, &Adapter->PackInfo[iIndex]); + uiPrevTotalCount--; + exit_flag = FALSE; + } + } + + if(Adapter->IdleMode || Adapter->bPreparingForLowPowerMode) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "In Idle Mode\n"); + break; + } + if(exit_flag == TRUE ) + break ; + }/* end of inner while loop */ + if(Adapter->bcm_jiffies == 0 && + atomic_read(&Adapter->TotalPacketCount) != 0 && + uiPrevTotalCount == atomic_read(&Adapter->TotalPacketCount)) + { + Adapter->bcm_jiffies = jiffies; + } + update_per_cid_rx (Adapter); + Adapter->txtransmit_running = 0; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "<======"); +} diff --git a/drivers/staging/bcm/Macros.h b/drivers/staging/bcm/Macros.h new file mode 100644 index 0000000..f559b59 --- /dev/null +++ b/drivers/staging/bcm/Macros.h @@ -0,0 +1,399 @@ +/************************************* +* Macros.h +**************************************/ +#ifndef __MACROS_H__ +#define __MACROS_H__ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) +#define kthread_run(threadfn,data,datafmt)(struct task_struct *)kernel_thread(threadfn,data,0) +#endif + +#define TX_TIMER_PERIOD 10 //10 msec +#define MAX_CLASSIFIERS 100 +//#define MAX_CLASSIFIERS_PER_SF 20 +#define MAX_TARGET_DSX_BUFFERS 24 + +#define MAX_CNTRL_PKTS 100 +#define MAX_DATA_PKTS 200 +#define MAX_ETH_SIZE 1536 +#define MAX_CNTL_PKT_SIZE 2048 +/* TIMER RELATED */ +#define JIFFIES_2_QUADPART() (ULONG)(jiffies * 10000) // jiffies(1msec) to Quadpart(100nsec) + +#define MTU_SIZE 1400 + +#define MAC_ADDR_REGISTER 0xbf60d000 + + +///////////Quality of Service/////////////////////////// +#define NO_OF_QUEUES 17 +#define HiPriority NO_OF_QUEUES-1 +#define LowPriority 0 +#define BE 2 +#define rtPS 4 +#define ERTPS 5 +#define UGS 6 + +#define BE_BUCKET_SIZE 1024*1024*100 //32kb +#define rtPS_BUCKET_SIZE 1024*1024*100 //8kb +#define MAX_ALLOWED_RATE 1024*1024*100 +#define TX_PACKET_THRESHOLD 10 +#define XSECONDS 1*HZ +#define DSC_ACTIVATE_REQUEST 248 +#define QUEUE_DEPTH_OFFSET 0x1fc01000 +#define MAX_DEVICE_DESC_SIZE 2040 +#define MAX_CTRL_QUEUE_LEN 100 +#define MAX_APP_QUEUE_LEN 200 +#define MAX_LATENCY_ALLOWED 0xFFFFFFFF +#define DEFAULT_UG_INTERVAL 250 +#define DEFAULT_UGI_FACTOR 4 + +#define DEFAULT_PERSFCOUNT 60 +#define MAX_CONNECTIONS 10 +#define MAX_CLASS_NAME_LENGTH 32 + +#define ETH_LENGTH_OF_ADDRESS 6 +#define MAX_MULTICAST_ADDRESSES 32 +#define IP_LENGTH_OF_ADDRESS 4 + +#define IP_PACKET_ONLY_MODE 0 +#define ETH_PACKET_TUNNELING_MODE 1 + +////////////Link Request////////////// +#define SET_MAC_ADDRESS_REQUEST 0 +#define SYNC_UP_REQUEST 1 +#define SYNCED_UP 2 +#define LINK_UP_REQUEST 3 +#define LINK_CONNECTED 4 +#define SYNC_UP_NOTIFICATION 2 +#define LINK_UP_NOTIFICATION 4 + + +#define LINK_NET_ENTRY 0x0002 +#define HMC_STATUS 0x0004 +#define LINK_UP_CONTROL_REQ 0x83 + +#define STATS_POINTER_REQ_STATUS 0x86 +#define NETWORK_ENTRY_REQ_PAYLOAD 198 +#define LINK_DOWN_REQ_PAYLOAD 226 +#define SYNC_UP_REQ_PAYLOAD 228 +#define STATISTICS_POINTER_REQ 237 +#define LINK_UP_REQ_PAYLOAD 245 +#define LINK_UP_ACK 246 + +#define STATS_MSG_SIZE 4 +#define INDEX_TO_DATA 4 + +#define GO_TO_IDLE_MODE_PAYLOAD 210 +#define COME_UP_FROM_IDLE_MODE_PAYLOAD 211 +#define IDLE_MODE_SF_UPDATE_MSG 187 + +#define SKB_RESERVE_ETHERNET_HEADER 16 +#define SKB_RESERVE_PHS_BYTES 32 + +#define IP_PACKET_ONLY_MODE 0 +#define ETH_PACKET_TUNNELING_MODE 1 + +#define ETH_CS_802_3 1 +#define ETH_CS_802_1Q_VLAN 3 +#define IPV4_CS 1 +#define IPV6_CS 2 +#define ETH_CS_MASK 0x3f + +/** \brief Validity bit maps for TLVs in packet classification rule */ + +#define PKT_CLASSIFICATION_USER_PRIORITY_VALID 0 +#define PKT_CLASSIFICATION_VLANID_VALID 1 + +#ifndef MIN +#define MIN(_a, _b) ((_a) < (_b)? (_a): (_b)) +#endif + + +/*Leader related terms */ +#define LEADER_STATUS 0x00 +#define LEADER_STATUS_TCP_ACK 0x1 +#define LEADER_SIZE sizeof(LEADER) +#define MAC_ADDR_REQ_SIZE sizeof(PACKETTOSEND) +#define SS_INFO_REQ_SIZE sizeof(PACKETTOSEND) +#define CM_REQUEST_SIZE LEADER_SIZE + sizeof(stLocalSFChangeRequest) +#define IDLE_REQ_SIZE sizeof(PACKETTOSEND) + + +#define MAX_TRANSFER_CTRL_BYTE_USB 2 * 1024 + +#define GET_MAILBOX1_REG_REQUEST 0x87 +#define GET_MAILBOX1_REG_RESPONSE 0x67 +#define VCID_CONTROL_PACKET 0x00 + +#define TRANSMIT_NETWORK_DATA 0x00 +#define RECEIVED_NETWORK_DATA 0x20 + +#define CM_RESPONSES 0xA0 +#define STATUS_RSP 0xA1 +#define LINK_CONTROL_RESP 0xA2 +#define IDLE_MODE_STATUS 0xA3 +#define STATS_POINTER_RESP 0xA6 +#define MGMT_MSG_INFO_SW_STATUS 0xA7 +#define AUTH_SS_HOST_MSG 0xA8 + +#define CM_DSA_ACK_PAYLOAD 247 +#define CM_DSC_ACK_PAYLOAD 248 +#define CM_DSD_ACK_PAYLOAD 249 +#define CM_DSDEACTVATE 250 +#define TOTAL_MASKED_ADDRESS_IN_BYTES 32 + +#define MAC_REQ 0 +#define LINK_RESP 1 +#define RSSI_INDICATION 2 + +#define SS_INFO 4 +#define STATISTICS_INFO 5 +#define CM_INDICATION 6 +#define PARAM_RESP 7 +#define BUFFER_1K 1024 +#define BUFFER_2K BUFFER_1K*2 +#define BUFFER_4K BUFFER_2K*2 +#define BUFFER_8K BUFFER_4K*2 +#define BUFFER_16K BUFFER_8K*2 +#define DOWNLINK_DIR 0 +#define UPLINK_DIR 1 + +#define BCM_SIGNATURE "BECEEM" + + +#define GPIO_OUTPUT_REGISTER 0x0F00003C +#define BCM_GPIO_OUTPUT_SET_REG 0x0F000040 +#define BCM_GPIO_OUTPUT_CLR_REG 0x0F000044 +#define GPIO_MODE_REGISTER 0x0F000034 +#define GPIO_PIN_STATE_REGISTER 0x0F000038 + + +typedef struct _LINK_STATE { + UCHAR ucLinkStatus; + UCHAR bIdleMode; + UCHAR bShutdownMode; +}LINK_STATE, *PLINK_STATE; + + +enum enLinkStatus { + WAIT_FOR_SYNC = 1, + PHY_SYNC_ACHIVED = 2, + LINKUP_IN_PROGRESS = 3, + LINKUP_DONE = 4, + DREG_RECIEVED = 5, + LINK_STATUS_RESET_RECIEVED = 6, + PERIODIC_WAKE_UP_NOTIFICATION_FRM_FW = 7, + LINK_SHUTDOWN_REQ_FROM_FIRMWARE = 8, + COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW =9 +}; + +typedef enum _E_PHS_DSC_ACTION +{ + eAddPHSRule=0, + eSetPHSRule, + eDeletePHSRule, + eDeleteAllPHSRules +}E_PHS_DSC_ACTION; + + +#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ 0x89 // Host to Mac +#define CM_CONTROL_NEWDSX_MULTICLASSIFIER_RESP 0xA9 // Mac to Host +#define MASK_DISABLE_HEADER_SUPPRESSION 0x10 //0b000010000 +#define MINIMUM_PENDING_DESCRIPTORS 5 + +#define SHUTDOWN_HOSTINITIATED_REQUESTPAYLOAD 0xCC +#define SHUTDOWN_ACK_FROM_DRIVER 0x1 +#define SHUTDOWN_NACK_FROM_DRIVER 0x2 + +#define LINK_SYNC_UP_SUBTYPE 0x0001 +#define LINK_SYNC_DOWN_SUBTYPE 0x0001 + + + +#define CONT_MODE 1 +#define SINGLE_DESCRIPTOR 1 + + +#define DESCRIPTOR_LENGTH 0x30 +#define FIRMWARE_DESCS_ADDRESS 0x1F100000 + + +#define CLOCK_RESET_CNTRL_REG_1 0x0F00000C +#define CLOCK_RESET_CNTRL_REG_2 0x0F000840 + + + +#define TX_DESCRIPTOR_HEAD_REGISTER 0x0F010034 +#define RX_DESCRIPTOR_HEAD_REGISTER 0x0F010094 + +#define STATISTICS_BEGIN_ADDR 0xbf60f02c + +#define MAX_PENDING_CTRL_PACKET (MAX_CTRL_QUEUE_LEN-10) + +#define WIMAX_MAX_MTU MTU_SIZE + ETH_HLEN +#define AUTO_LINKUP_ENABLE 0x2 +#define AUTO_SYNC_DISABLE 0x1 +#define AUTO_FIRM_DOWNLOAD 0x1 +#define SETTLE_DOWN_TIME 50 + +#define HOST_BUS_SUSPEND_BIT 16 + +#define IDLE_MESSAGE 0x81 + +#define MIPS_CLOCK_133MHz 1 + +#define TARGET_CAN_GO_TO_IDLE_MODE 2 +#define TARGET_CAN_NOT_GO_TO_IDLE_MODE 3 +#define IDLE_MODE_PAYLOAD_LENGTH 8 + +#define IP_HEADER(Buffer) ((IPHeaderFormat*)(Buffer)) +#define IPV4 4 +#define IP_VERSION(byte) (((byte&0xF0)>>4)) + +#define SET_MAC_ADDRESS 193 +#define SET_MAC_ADDRESS_RESPONSE 236 + +#define IDLE_MODE_WAKEUP_PATTERN 0xd0ea1d1e +#define IDLE_MODE_WAKEUP_NOTIFIER_ADDRESS 0x1FC02FA8 +#define IDLE_MODE_MAX_RETRY_COUNT 1000 + +#ifdef REL_4_1 +#define CONFIG_BEGIN_ADDR 0xBF60B004 +#else +#define CONFIG_BEGIN_ADDR 0xBF60B000 +#endif + +#define FIRMWARE_BEGIN_ADDR 0xBFC00000 + +#define INVALID_QUEUE_INDEX (USHORT)-1 + +#define INVALID_PID (pid_t)-1 +#define DDR_80_MHZ 0 +#define DDR_100_MHZ 1 +#define DDR_120_MHZ 2 // Additional Frequency for T3LP +#define DDR_133_MHZ 3 +#define DDR_140_MHZ 4 // Not Used (Reserved for future) +#define DDR_160_MHZ 5 // Additional Frequency for T3LP +#define DDR_180_MHZ 6 // Not Used (Reserved for future) +#define DDR_200_MHZ 7 // Not Used (Reserved for future) + +#define MIPS_200_MHZ 0 +#define MIPS_160_MHZ 1 + +#define PLL_800_MHZ 0 +#define PLL_266_MHZ 1 + +#define DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING 0 +#define DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING 1 +#define DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN 2 +#define DEVICE_POWERSAVE_MODE_AS_RESERVED 3 +#define DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE 4 + + +#define EEPROM_REJECT_REG_1 0x0f003018 +#define EEPROM_REJECT_REG_2 0x0f00301c +#define EEPROM_REJECT_REG_3 0x0f003008 +#define EEPROM_REJECT_REG_4 0x0f003020 +#define EEPROM_REJECT_MASK 0x0fffffff +#define VSG_MODE 0x3 + +/* Idle Mode Related Registers */ +#define DEBUG_INTERRUPT_GENERATOR_REGISTOR 0x0F00007C +#ifdef BCM_SHM_INTERFACE +#define SW_ABORT_IDLEMODE_LOC 0xbfc02f9c +#define CPE_VIRTUAL_MAILBOX_REG 0xBFC02E58 +#else +#define SW_ABORT_IDLEMODE_LOC 0x0FF01FFC +#endif + +#define SW_ABORT_IDLEMODE_PATTERN 0xd0ea1d1e +#define DEVICE_INT_OUT_EP_REG0 0x0F011870 +#define DEVICE_INT_OUT_EP_REG1 0x0F011874 + +#define BIN_FILE "/lib/firmware/macxvi200.bin" +#define CFG_FILE "/lib/firmware/macxvi.cfg" +#define SF_MAX_ALLOWED_PACKETS_TO_BACKUP 128 +#define MIN_VAL(x,y) ((x)<(y)?(x):(y)) +#define MAC_ADDRESS_SIZE 6 +#define EEPROM_COMMAND_Q_REG 0x0F003018 +#define EEPROM_READ_DATA_Q_REG 0x0F003020 +#define CHIP_ID_REG 0x0F000000 +#define GPIO_MODE_REG 0x0F000034 +#define GPIO_OUTPUT_REG 0x0F00003C +#define WIMAX_MAX_ALLOWED_RATE 1024*1024*50 + +#define T3 0xbece0300 +#define TARGET_SFID_TXDESC_MAP_LOC 0xBFFFF400 + +#define RWM_READ 0 +#define RWM_WRITE 1 + +#define T3LPB 0xbece3300 +#define BCS220_2 0xbece3311 +#define BCS220_2BC 0xBECE3310 +#define BCS250_BC 0xbece3301 +#define BCS220_3 0xbece3321 + + +#define HPM_CONFIG_LDO145 0x0F000D54 +#define HPM_CONFIG_MSW 0x0F000D58 + +#define T3B 0xbece0310 +typedef enum eNVM_TYPE +{ + NVM_AUTODETECT = 0, + NVM_EEPROM, + NVM_FLASH, + NVM_UNKNOWN +}NVM_TYPE; + +typedef enum ePMU_MODES +{ + HYBRID_MODE_7C = 0, + INTERNAL_MODE_6 = 1, + HYBRID_MODE_6 = 2 +}PMU_MODE; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30) +#define MAX_RDM_WRM_RETIRES 16 +#else +#define MAX_RDM_WRM_RETIRES 1 +#endif + + +enum eAbortPattern { + ABORT_SHUTDOWN_MODE = 1, + ABORT_IDLE_REG = 1, + ABORT_IDLE_MODE = 2, + ABORT_IDLE_SYNCDOWN = 3 +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) + #define GET_BCM_ADAPTER(net_dev) ({\ + PMINI_ADAPTER __Adapter = NULL; \ + if (net_dev) { \ + __Adapter = (PMINI_ADAPTER)(net_dev->priv); \ + } \ + else { \ + __Adapter = NULL; \ + }__Adapter;} ) +#else + #define GET_BCM_ADAPTER(net_dev) ({\ + PMINI_ADAPTER __Adapter = NULL; \ + if (net_dev) { \ + __Adapter = (PMINI_ADAPTER)(*((UINT *)netdev_priv(net_dev))); \ + } \ + else { \ + __Adapter = NULL; \ + }__Adapter;}) + + +#endif + +/* Offsets used by driver in skb cb variable */ +#define SKB_CB_CLASSIFICATION_OFFSET 0 +#define SKB_CB_LATENCY_OFFSET 1 +#define SKB_CB_TCPACK_OFFSET 2 + +#endif //__MACROS_H__ diff --git a/drivers/staging/bcm/Makefile b/drivers/staging/bcm/Makefile new file mode 100644 index 0000000..3fdec2e --- /dev/null +++ b/drivers/staging/bcm/Makefile @@ -0,0 +1,12 @@ +# +# Makefile for Beceem USB Wimax card +# + +obj-$(CONFIG_BCM_WIMAX) += bcm_wimax.o + +bcm_wimax-objs := InterfaceDld.o InterfaceIdleMode.o InterfaceInit.o InterfaceRx.o \ + InterfaceIsr.o InterfaceMisc.o InterfaceTx.o \ + Arp.o CmHost.o Debug.o IPv6Protocol.o Qos.o Transmit.o\ + Bcmnet.o DDRInit.o HandleControlPacket.o\ + LeakyBucket.o Misc.o sort.o Bcmchar.o hostmibs.o PHSModule.o\ + Osal_Misc.o led_control.o nvm.o vendorspecificextn.o diff --git a/drivers/staging/bcm/Misc.c b/drivers/staging/bcm/Misc.c new file mode 100644 index 0000000..5ed58a8 --- /dev/null +++ b/drivers/staging/bcm/Misc.c @@ -0,0 +1,2239 @@ +#include "headers.h" + +static VOID default_wimax_protocol_initialize(PMINI_ADAPTER Adapter) +{ + + UINT uiLoopIndex; + + for(uiLoopIndex=0; uiLoopIndex < NO_OF_QUEUES-1; uiLoopIndex++) + { + Adapter->PackInfo[uiLoopIndex].uiThreshold=TX_PACKET_THRESHOLD; + Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate=MAX_ALLOWED_RATE; + Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize=20*1024*1024; + } + + Adapter->BEBucketSize=BE_BUCKET_SIZE; + Adapter->rtPSBucketSize=rtPS_BUCKET_SIZE; + Adapter->LinkStatus=SYNC_UP_REQUEST; + Adapter->TransferMode=IP_PACKET_ONLY_MODE; + Adapter->usBestEffortQueueIndex=-1; + return; +} + + +INT +InitAdapter(PMINI_ADAPTER psAdapter) +{ + int i = 0; + INT Status = STATUS_SUCCESS ; + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Initialising Adapter = 0x%x",(unsigned int) psAdapter); + + if(psAdapter == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter is NULL"); + return -EINVAL; + } + + sema_init(&psAdapter->NVMRdmWrmLock,1); +// psAdapter->ulFlashCalStart = FLASH_AUTO_INIT_BASE_ADDR; + + sema_init(&psAdapter->rdmwrmsync, 1); + spin_lock_init(&psAdapter->control_queue_lock); + spin_lock_init(&psAdapter->txtransmitlock); + sema_init(&psAdapter->RxAppControlQueuelock, 1); +// sema_init(&psAdapter->data_packet_queue_lock, 1); + sema_init(&psAdapter->fw_download_sema, 1); + sema_init(&psAdapter->LowPowerModeSync,1); + + // spin_lock_init(&psAdapter->sleeper_lock); + + for(i=0;iPackInfo[i].SFQueueLock); + i=0; + + init_waitqueue_head(&psAdapter->process_rx_cntrlpkt); + init_waitqueue_head(&psAdapter->tx_packet_wait_queue); + init_waitqueue_head(&psAdapter->process_read_wait_queue); + init_waitqueue_head(&psAdapter->ioctl_fw_dnld_wait_queue); + init_waitqueue_head(&psAdapter->lowpower_mode_wait_queue); + psAdapter->waiting_to_fw_download_done = TRUE; + //init_waitqueue_head(&psAdapter->device_wake_queue); + psAdapter->fw_download_done=FALSE; + + psAdapter->pvOsDepData = (PLINUX_DEP_DATA) kmalloc(sizeof(LINUX_DEP_DATA), + GFP_KERNEL); + + if(psAdapter->pvOsDepData == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Linux Specific Data allocation failed"); + return -ENOMEM; + } + memset(psAdapter->pvOsDepData, 0, sizeof(LINUX_DEP_DATA)); + + default_wimax_protocol_initialize(psAdapter); + for (i=0;itxctlpacket[i] = (char *)kmalloc(MAX_CNTL_PKT_SIZE, + GFP_KERNEL); + if(!psAdapter->txctlpacket[i]) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No More Cntl pkts got, max got is %d", i); + return -ENOMEM; + } + } + if(AllocAdapterDsxBuffer(psAdapter)) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to allocate DSX buffers"); + return -EINVAL; + } + + //Initialize PHS interface + if(phs_init(&psAdapter->stBCMPhsContext,psAdapter)!=0) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%s:%d:Error PHS Init Failed=====>\n", __FILE__, __FUNCTION__, __LINE__); + return -ENOMEM; + } + + Status = BcmAllocFlashCSStructure(psAdapter); + if(Status) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Memory Allocation for Flash structure failed"); + return Status ; + } + + Status = vendorextnInit(psAdapter); + + if(STATUS_SUCCESS != Status) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Vendor Init Failed"); + return Status ; + } + + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Adapter initialised"); + + + return STATUS_SUCCESS; +} + +VOID AdapterFree(PMINI_ADAPTER Adapter) +{ + INT count = 0; + + beceem_protocol_reset(Adapter); + + vendorextnExit(Adapter); + + if(Adapter->control_packet_handler && !IS_ERR(Adapter->control_packet_handler)) + kthread_stop (Adapter->control_packet_handler); + if(Adapter->transmit_packet_thread && !IS_ERR(Adapter->transmit_packet_thread)) + kthread_stop (Adapter->transmit_packet_thread); + wake_up(&Adapter->process_read_wait_queue); + if(Adapter->LEDInfo.led_thread_running & (BCM_LED_THREAD_RUNNING_ACTIVELY | BCM_LED_THREAD_RUNNING_INACTIVELY)) + kthread_stop (Adapter->LEDInfo.led_cntrl_threadid); + bcm_unregister_networkdev(Adapter); + while(atomic_read(&Adapter->ApplicationRunning)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Waiting for Application to close.. %d\n",atomic_read(&Adapter->ApplicationRunning)); + msleep(100); + } + unregister_control_device_interface(Adapter); + if(Adapter->dev && !IS_ERR(Adapter->dev)) + free_netdev(Adapter->dev); + if(Adapter->pstargetparams != NULL) + { + bcm_kfree(Adapter->pstargetparams); + } + for (count =0;count < MAX_CNTRL_PKTS;count++) + { + if(Adapter->txctlpacket[count]) + bcm_kfree(Adapter->txctlpacket[count]); + } + FreeAdapterDsxBuffer(Adapter); + if(Adapter->pvOsDepData) + bcm_kfree (Adapter->pvOsDepData); + if(Adapter->pvInterfaceAdapter) + bcm_kfree(Adapter->pvInterfaceAdapter); + + //Free the PHS Interface + PhsCleanup(&Adapter->stBCMPhsContext); + +#ifndef BCM_SHM_INTERFACE + BcmDeAllocFlashCSStructure(Adapter); +#endif + + bcm_kfree (Adapter); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "<========\n"); +} + + +int create_worker_threads(PMINI_ADAPTER psAdapter) +{ + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Init Threads..."); + // Rx Control Packets Processing + psAdapter->control_packet_handler = kthread_run((int (*)(void *)) + control_packet_handler, psAdapter, "CtrlPktHdlr"); + if(IS_ERR(psAdapter->control_packet_handler)) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Kernel Thread, but still returning success\n"); + return PTR_ERR(psAdapter->control_packet_handler); + } + // Tx Thread + psAdapter->transmit_packet_thread = kthread_run((int (*)(void *)) + tx_pkt_handler, psAdapter, "TxPktThread"); + if(IS_ERR (psAdapter->transmit_packet_thread)) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Kernel Thread, but still returning success"); + kthread_stop(psAdapter->control_packet_handler); + return PTR_ERR(psAdapter->transmit_packet_thread); + } + return 0; +} + + +static inline struct file *open_firmware_file(PMINI_ADAPTER Adapter, char *path) +{ + struct file *flp=NULL; + mm_segment_t oldfs; + oldfs=get_fs(); + set_fs(get_ds()); + flp=filp_open(path, O_RDONLY, S_IRWXU); + set_fs(oldfs); + if(IS_ERR(flp)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable To Open File %s, err %lx", + path, PTR_ERR(flp)); + flp = NULL; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Got file descriptor pointer of %s!", + path); + } + if(Adapter->device_removed) + { + flp = NULL; + } + + return flp; +} + + +int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */ + char *path, /**< path to image file */ + unsigned int loc /**< Download Address on the chip*/ + ) +{ + int errorno=0; + struct file *flp=NULL; + mm_segment_t oldfs; + struct timeval tv={0}; + + flp=open_firmware_file(Adapter, path); + if(!flp) + { + errorno = -ENOENT; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path); + goto exit_download; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path,(unsigned long)flp->f_dentry->d_inode->i_size, loc); + do_gettimeofday(&tv); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "download start %lx", ((tv.tv_sec * 1000) + + (tv.tv_usec/1000))); + if(Adapter->bcm_file_download(Adapter->pvInterfaceAdapter, flp, loc)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to download the firmware with error\ + %x!!!", -EIO); + errorno=-EIO; + goto exit_download; + } + oldfs=get_fs();set_fs(get_ds()); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + vfs_llseek(flp, 0, 0); +#endif + set_fs(oldfs); + if(Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, + flp, loc)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!"); + errorno=-EIO; + goto exit_download; + } + +exit_download: + oldfs=get_fs();set_fs(get_ds()); + if(flp && !(IS_ERR(flp))) + filp_close(flp, current->files); + set_fs(oldfs); + do_gettimeofday(&tv); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "file download done at %lx", ((tv.tv_sec * 1000) + + (tv.tv_usec/1000))); + return errorno; +} + + +void bcm_kfree_skb(struct sk_buff *skb) +{ + if(skb) + { + kfree_skb(skb); + } + skb = NULL ; +} + +VOID bcm_kfree(VOID *ptr) +{ + if(ptr) + { + kfree(ptr); + } + ptr = NULL ; +} + +/** +@ingroup ctrl_pkt_functions +This function copies the contents of given buffer +to the control packet and queues it for transmission. +@note Do not acquire the spinock, as it it already acquired. +@return SUCCESS/FAILURE. +*/ +INT CopyBufferToControlPacket(PMINI_ADAPTER Adapter,/**"); + if(!ioBuffer) + { + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Got Null Buffer\n"); + return -EINVAL; + } + + pLinkReq = (PLINK_REQUEST)ioBuffer; + pLeader=(PLEADER)ioBuffer; //ioBuffer Contains sw_Status and Payload + + if(Adapter->bShutStatus == TRUE && + pLinkReq->szData[0] == LINK_DOWN_REQ_PAYLOAD && + pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE) + { + //Got sync down in SHUTDOWN..we could not process this. + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC DOWN Request in Shut Down Mode..\n"); + return STATUS_FAILURE; + } + + if((pLeader->Status == LINK_UP_CONTROL_REQ) && + ((pLinkReq->szData[0] == LINK_UP_REQ_PAYLOAD && + (pLinkReq->szData[1] == LINK_SYNC_UP_SUBTYPE)) ||//Sync Up Command + pLinkReq->szData[0] == NETWORK_ENTRY_REQ_PAYLOAD)) //Net Entry Command + { + if(Adapter->LinkStatus > PHY_SYNC_ACHIVED) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"LinkStatus is Greater than PHY_SYN_ACHIEVED"); + return STATUS_FAILURE; + } + if(TRUE == Adapter->bShutStatus) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "SYNC UP IN SHUTDOWN..Device WakeUp\n"); + if(Adapter->bTriedToWakeUpFromlowPowerMode == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Waking up for the First Time..\n"); + Adapter->usIdleModePattern = ABORT_SHUTDOWN_MODE; // change it to 1 for current support. + Adapter->bWakeUpDevice = TRUE; + wake_up(&Adapter->process_rx_cntrlpkt); + + Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, + !Adapter->bShutStatus, (5 * HZ)); + + if(Status == -ERESTARTSYS) + return Status; + + if(Adapter->bShutStatus) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Shutdown Mode Wake up Failed - No Wake Up Received\n"); + return STATUS_FAILURE; + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Wakeup has been tried already...\n"); + } + } + + } + if(TRUE == Adapter->IdleMode) + { + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Device is in Idle mode ... hence \n"); + if(pLeader->Status == LINK_UP_CONTROL_REQ || pLeader->Status == 0x80 || + pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ ) + + { + if((pLeader->Status == LINK_UP_CONTROL_REQ) && (pLinkReq->szData[0]==LINK_DOWN_REQ_PAYLOAD)) + { + if((pLinkReq->szData[1] == LINK_SYNC_DOWN_SUBTYPE)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Link Down Sent in Idle Mode\n"); + Adapter->usIdleModePattern = ABORT_IDLE_SYNCDOWN;//LINK DOWN sent in Idle Mode + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n"); + Adapter->usIdleModePattern = ABORT_IDLE_REG; + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL,"ABORT_IDLE_MODE pattern is being written\n"); + Adapter->usIdleModePattern = ABORT_IDLE_MODE; + } + + /*Setting bIdleMode_tx_from_host to TRUE to indicate LED control thread to represent + the wake up from idlemode is from host*/ + //Adapter->LEDInfo.bIdleMode_tx_from_host = TRUE; +#if 0 + if(STATUS_SUCCESS != InterfaceIdleModeWakeup(Adapter)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Idle Mode Wake up Failed\n"); + return STATUS_FAILURE; + } +#endif + Adapter->bWakeUpDevice = TRUE; + wake_up(&Adapter->process_rx_cntrlpkt); + + + + if(LINK_DOWN_REQ_PAYLOAD == pLinkReq->szData[0]) + { + // We should not send DREG message down while in idlemode. + return STATUS_SUCCESS; + } + + Status = wait_event_interruptible_timeout(Adapter->lowpower_mode_wait_queue, + !Adapter->IdleMode, (5 * HZ)); + + if(Status == -ERESTARTSYS) + return Status; + + if(Adapter->IdleMode) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Idle Mode Wake up Failed - No Wake Up Received\n"); + return STATUS_FAILURE; + } + } + else + return STATUS_SUCCESS; + } + //The Driver has to send control messages with a particular VCID + pLeader->Vcid = VCID_CONTROL_PACKET;//VCID for control packet. + + /* Allocate skb for Control Packet */ + pktlen = pLeader->PLength; + ctrl_buff = (char *)Adapter->txctlpacket[atomic_read(&Adapter->index_wr_txcntrlpkt)%MAX_CNTRL_PKTS]; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Control packet to be taken =%d and address is =%pincoming address is =%p and packet len=%x", + atomic_read(&Adapter->index_wr_txcntrlpkt), ctrl_buff, ioBuffer, pktlen); + if(ctrl_buff) + { + if(pLeader) + { + if((pLeader->Status == 0x80) || + (pLeader->Status == CM_CONTROL_NEWDSX_MULTICLASSIFIER_REQ)) + { + /* + //Restructure the DSX message to handle Multiple classifier Support + // Write the Service Flow param Structures directly to the target + //and embed the pointers in the DSX messages sent to target. + */ + //Lets store the current length of the control packet we are transmitting + pucAddIndication = (PUCHAR)ioBuffer + LEADER_SIZE; + pktlen = pLeader->PLength; + Status = StoreCmControlResponseMessage(Adapter,pucAddIndication, &pktlen); + if(Status != 1) + { + ClearTargetDSXBuffer(Adapter,((stLocalSFAddIndicationAlt *)pucAddIndication)->u16TID, FALSE); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, " Error Restoring The DSX Control Packet. Dsx Buffers on Target may not be Setup Properly "); + return STATUS_FAILURE; + } + /* + //update the leader to use the new length + //The length of the control packet is length of message being sent + Leader length + */ + pLeader->PLength = pktlen; + } + } + memset(ctrl_buff, 0, pktlen+LEADER_SIZE); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Copying the Control Packet Buffer with length=%d\n", pLeader->PLength); + *(PLEADER)ctrl_buff=*pLeader; + memcpy(ctrl_buff + LEADER_SIZE, ((PUCHAR)ioBuffer + LEADER_SIZE), pLeader->PLength); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Enqueuing the Control Packet"); + + /*Update the statistics counters */ + spin_lock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); + Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost+=pLeader->PLength; + Adapter->PackInfo[HiPriority].uiCurrentPacketsOnHost++; + atomic_inc(&Adapter->TotalPacketCount); + spin_unlock_bh(&Adapter->PackInfo[HiPriority].SFQueueLock); + + Adapter->PackInfo[HiPriority].bValid = TRUE; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "CurrBytesOnHost: %x bValid: %x", + Adapter->PackInfo[HiPriority].uiCurrentBytesOnHost, + Adapter->PackInfo[HiPriority].bValid); + Status=STATUS_SUCCESS; + /*Queue the packet for transmission */ + atomic_inc(&Adapter->index_wr_txcntrlpkt); + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL,DBG_LVL_ALL, "Calling transmit_packets"); + atomic_set(&Adapter->TxPktAvail, 1); +#ifdef BCM_SHM_INTERFACE + virtual_mail_box_interrupt(); +#endif + wake_up(&Adapter->tx_packet_wait_queue); + } + else + { + Status=-ENOMEM; + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "mem allocation Failed"); + } + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<===="); + return Status; +} + +/***************************************************************** +* Function - SendStatisticsPointerRequest() +* +* Description - This function builds and forwards the Statistics +* Pointer Request control Packet. +* +* Parameters - Adapter : Pointer to Adapter structure. +* - pstStatisticsPtrRequest : Pointer to link request. +* +* Returns - None. +*****************************************************************/ +VOID SendStatisticsPointerRequest(PMINI_ADAPTER Adapter, + PLINK_REQUEST pstStatisticsPtrRequest) +{ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "======>"); + pstStatisticsPtrRequest->Leader.Status = STATS_POINTER_REQ_STATUS; + pstStatisticsPtrRequest->Leader.PLength = sizeof(ULONG);//minimum 4 bytes + pstStatisticsPtrRequest->szData[0] = STATISTICS_POINTER_REQ; + + CopyBufferToControlPacket(Adapter,pstStatisticsPtrRequest); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "<====="); + return; +} + + + +void SendLinkDown(PMINI_ADAPTER Adapter) +{ + LINK_REQUEST stLinkDownRequest; + memset(&stLinkDownRequest, 0, sizeof(LINK_REQUEST)); + stLinkDownRequest.Leader.Status=LINK_UP_CONTROL_REQ; + stLinkDownRequest.Leader.PLength=sizeof(ULONG);//minimum 4 bytes + stLinkDownRequest.szData[0]=LINK_DOWN_REQ_PAYLOAD; + Adapter->bLinkDownRequested = TRUE; + + CopyBufferToControlPacket(Adapter,&stLinkDownRequest); +} + +/****************************************************************** +* Function - LinkMessage() +* +* Description - This function builds the Sync-up and Link-up request +* packet messages depending on the device Link status. +* +* Parameters - Adapter: Pointer to the Adapter structure. +* +* Returns - None. +*******************************************************************/ +__inline VOID LinkMessage(PMINI_ADAPTER Adapter) +{ + PLINK_REQUEST pstLinkRequest=NULL; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>"); + if(Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup) + { + pstLinkRequest=kmalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); + if(!pstLinkRequest) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); + return; + } + memset(pstLinkRequest,0,sizeof(LINK_REQUEST)); + //sync up request... + Adapter->LinkStatus = WAIT_FOR_SYNC;// current link status + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp..."); + pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD; + pstLinkRequest->szData[1]=LINK_SYNC_UP_SUBTYPE; + pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ; + pstLinkRequest->Leader.PLength=sizeof(ULONG); + Adapter->bSyncUpRequestSent = TRUE; + } + else if(Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp) + { + pstLinkRequest=kmalloc(sizeof(LINK_REQUEST), GFP_ATOMIC); + if(!pstLinkRequest) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!"); + return; + } + memset(pstLinkRequest,0,sizeof(LINK_REQUEST)); + //LINK_UP_REQUEST + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp..."); + pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD; + pstLinkRequest->szData[1]=LINK_NET_ENTRY; + pstLinkRequest->Leader.Status=LINK_UP_CONTROL_REQ; + pstLinkRequest->Leader.PLength=sizeof(ULONG); + } + if(pstLinkRequest) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Calling CopyBufferToControlPacket"); + CopyBufferToControlPacket(Adapter, pstLinkRequest); + bcm_kfree(pstLinkRequest); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "LinkMessage <====="); + return; +} + + +/********************************************************************** +* Function - StatisticsResponse() +* +* Description - This function handles the Statistics response packet. +* +* Parameters - Adapter : Pointer to the Adapter structure. +* - pvBuffer: Starting address of Statistic response data. +* +* Returns - None. +************************************************************************/ +VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer) +{ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s====>",__FUNCTION__); + Adapter->StatisticsPointer = ntohl(*(PULONG)pvBuffer); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Stats at %lx", Adapter->StatisticsPointer); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "%s <====",__FUNCTION__); + return; +} + + +/********************************************************************** +* Function - LinkControlResponseMessage() +* +* Description - This function handles the Link response packets. +* +* Parameters - Adapter : Pointer to the Adapter structure. +* - pucBuffer: Starting address of Link response data. +* +* Returns - None. +***********************************************************************/ +VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) +{ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "=====>"); + + if(*pucBuffer==LINK_UP_ACK) + { + switch(*(pucBuffer+1)) + { + case PHY_SYNC_ACHIVED: //SYNCed UP + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHY_SYNC_ACHIVED"); + + if(Adapter->LinkStatus == LINKUP_DONE) + { + beceem_protocol_reset(Adapter); + } + + Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ; + Adapter->LinkStatus=PHY_SYNC_ACHIVED; + + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = NO_NETWORK_ENTRY; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + + LinkMessage(Adapter); + break; + + case LINKUP_DONE: + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "LINKUP_DONE"); + Adapter->LinkStatus=LINKUP_DONE; + Adapter->bPHSEnabled = *(pucBuffer+3); + Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Recieved In LinkUp Ack : %x \n",Adapter->bPHSEnabled); + if((FALSE == Adapter->bShutStatus)&& + (FALSE == Adapter->IdleMode)) + { + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = NORMAL_OPERATION; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + } + LinkMessage(Adapter); + break; + case WAIT_FOR_SYNC: + + /* + * Driver to ignore the DREG_RECEIVED + * WiMAX Application should handle this Message + */ + //Adapter->liTimeSinceLastNetEntry = 0; + Adapter->LinkUpStatus = 0; + Adapter->LinkStatus = 0; + Adapter->usBestEffortQueueIndex=INVALID_QUEUE_INDEX ; + Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; + Adapter->IdleMode = FALSE; + beceem_protocol_reset(Adapter); + + break; + case LINK_SHUTDOWN_REQ_FROM_FIRMWARE: + case COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW: + { + HandleShutDownModeRequest(Adapter, pucBuffer); + } + break; + default: + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "default case:LinkResponse %x",*(pucBuffer+1)); + break; + } + } + else if(SET_MAC_ADDRESS_RESPONSE==*pucBuffer) + { + PUCHAR puMacAddr = (pucBuffer + 1); + Adapter->LinkStatus=SYNC_UP_REQUEST; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "MAC address response, sending SYNC_UP"); + LinkMessage(Adapter); + memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "%s <=====",__FUNCTION__); + return; +} + +void SendIdleModeResponse(PMINI_ADAPTER Adapter) +{ + INT status = 0, NVMAccess = 0,lowPwrAbortMsg = 0; + struct timeval tv; + CONTROL_MESSAGE stIdleResponse = {{0}}; + memset(&tv, 0, sizeof(tv)); + stIdleResponse.Leader.Status = IDLE_MESSAGE; + stIdleResponse.Leader.PLength = IDLE_MODE_PAYLOAD_LENGTH; + stIdleResponse.szData[0] = GO_TO_IDLE_MODE_PAYLOAD; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL," ============>"); + + /********************************* + **down_trylock - + ** if [ semaphore is available ] + ** acquire semaphone and return value 0 ; + ** else + ** return non-zero value ; + ** + ***********************************/ + + NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); + + lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync); + + + if((NVMAccess || lowPwrAbortMsg || atomic_read(&Adapter->TotalPacketCount)) && + (Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) ) + { + if(!NVMAccess) + up(&Adapter->NVMRdmWrmLock); + + if(!lowPwrAbortMsg) + up(&Adapter->LowPowerModeSync); + + stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on. + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "HOST IS NACKING Idle mode To F/W!!!!!!!!"); + Adapter->bPreparingForLowPowerMode = FALSE; + } + else + { + stIdleResponse.szData[1] = TARGET_CAN_GO_TO_IDLE_MODE; //2;//Idle ACK + Adapter->StatisticsPointer = 0; + + /* Wait for the LED to TURN OFF before sending ACK response */ + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + INT iRetVal = 0; + + /* Wake the LED Thread with IDLEMODE_ENTER State */ + Adapter->DriverState = LOWPOWER_MODE_ENTER; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"LED Thread is Running..Hence Setting LED Event as IDLEMODE_ENTER jiffies:%ld",jiffies);; + wake_up(&Adapter->LEDInfo.notify_led_event); + + /* Wait for 1 SEC for LED to OFF */ + iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent, \ + Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000)); + + + /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */ + if(iRetVal <= 0) + { + stIdleResponse.szData[1] = TARGET_CAN_NOT_GO_TO_IDLE_MODE;//NACK- device access is going on. + Adapter->DriverState = NORMAL_OPERATION; + wake_up(&Adapter->LEDInfo.notify_led_event); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "NACKING Idle mode as time out happen from LED side!!!!!!!!"); + } + } + if(stIdleResponse.szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL,"ACKING IDLE MODE !!!!!!!!!"); + down(&Adapter->rdmwrmsync); + Adapter->bPreparingForLowPowerMode = TRUE; + up(&Adapter->rdmwrmsync); +#ifndef BCM_SHM_INTERFACE + //Killing all URBS. + if(Adapter->bDoSuspend == TRUE) + Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); + +#endif + } + else + { + Adapter->bPreparingForLowPowerMode = FALSE; + } + + if(!NVMAccess) + up(&Adapter->NVMRdmWrmLock); + + if(!lowPwrAbortMsg) + up(&Adapter->LowPowerModeSync); + + } + status = CopyBufferToControlPacket(Adapter,&stIdleResponse); + if((status != STATUS_SUCCESS)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"fail to send the Idle mode Request \n"); + Adapter->bPreparingForLowPowerMode = FALSE; +#ifndef BCM_SHM_INTERFACE + StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); +#endif + } + do_gettimeofday(&tv); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_RX, RX_DPC, DBG_LVL_ALL, "IdleMode Msg submitter to Q :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); + +} + +/****************************************************************** +* Function - DumpPackInfo() +* +* Description - This function dumps the all Queue(PackInfo[]) details. +* +* Parameters - Adapter: Pointer to the Adapter structure. +* +* Returns - None. +*******************************************************************/ +VOID DumpPackInfo(PMINI_ADAPTER Adapter) +{ + + UINT uiLoopIndex = 0; + UINT uiIndex = 0; + UINT uiClsfrIndex = 0; + S_CLASSIFIER_RULE *pstClassifierEntry = NULL; + + for(uiLoopIndex=0;uiLoopIndexPackInfo[uiLoopIndex].bValid) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid is FALSE for %X index\n",uiLoopIndex); + continue; + } + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," Dumping SF Rule Entry For SFID %lX \n",Adapter->PackInfo[uiLoopIndex].ulSFID); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," ucDirection %X \n",Adapter->PackInfo[uiLoopIndex].ucDirection); + if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv6 Service Flow \n"); + } + else + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Ipv4 Service Flow \n"); + } + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," SF Traffic Priority %X \n",Adapter->PackInfo[uiLoopIndex].u8TrafficPriority); + + for(uiClsfrIndex=0;uiClsfrIndexastClassifierTable[uiClsfrIndex]; + if(!pstClassifierEntry->bUsed) + continue; + + if(pstClassifierEntry->ulSFID != Adapter->PackInfo[uiLoopIndex].ulSFID) + continue; + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X Classifier Rule ID : %X\n",uiClsfrIndex,pstClassifierEntry->uiClassifierRuleIndex); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X usVCID_Value : %X\n",uiClsfrIndex,pstClassifierEntry->usVCID_Value); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bProtocolValid : %X\n",uiClsfrIndex,pstClassifierEntry->bProtocolValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bTOSValid : %X\n",uiClsfrIndex,pstClassifierEntry->bTOSValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bDestIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bDestIpValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tDumping Classifier Rule Entry For Index: %X bSrcIpValid : %X\n",uiClsfrIndex,pstClassifierEntry->bSrcIpValid); + + + for(uiIndex=0;uiIndexusSrcPortRangeLo[uiIndex]); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusSrcPortRangeHi:%X\n",pstClassifierEntry->usSrcPortRangeHi[uiIndex]); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeLo:%X\n",pstClassifierEntry->usDestPortRangeLo[uiIndex]); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tusDestPortRangeHi:%X\n",pstClassifierEntry->usDestPortRangeHi[uiIndex]); + } + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL," \tucIPSourceAddressLength : 0x%x\n",pstClassifierEntry->ucIPSourceAddressLength); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucIPDestinationAddressLength : 0x%x\n",pstClassifierEntry->ucIPDestinationAddressLength); + for(uiIndex=0;uiIndexucIPSourceAddressLength;uiIndex++) + { + if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpAddr :\n"); + DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Addr); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulSrcIpMask :\n"); + DumpIpv6Address(pstClassifierEntry->stSrcIpAddress.ulIpv6Mask); + } + else + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpAddr:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Addr[uiIndex]); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulSrcIpMask:%lX\n",pstClassifierEntry->stSrcIpAddress.ulIpv4Mask[uiIndex]); + } + } + for(uiIndex=0;uiIndexucIPDestinationAddressLength;uiIndex++) + { + if(Adapter->PackInfo[uiLoopIndex].ucIpVersion == IPV6) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpAddr :\n"); + DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Addr); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tIpv6 ulDestIpMask :\n"); + DumpIpv6Address(pstClassifierEntry->stDestIpAddress.ulIpv6Mask); + + } + else + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpAddr:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Addr[uiIndex]); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tulDestIpMask:%lX\n",pstClassifierEntry->stDestIpAddress.ulIpv4Mask[uiIndex]); + } + } + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tucProtocol:0x%X\n",pstClassifierEntry->ucProtocol[0]); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"\tu8ClassifierRulePriority:%X\n",pstClassifierEntry->u8ClassifierRulePriority); + + + } + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ulSFID:%lX\n",Adapter->PackInfo[uiLoopIndex].ulSFID); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"usVCID_Value:%X\n",Adapter->PackInfo[uiLoopIndex].usVCID_Value); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"PhsEnabled: 0x%X\n",Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThreshold:%X\n",Adapter->PackInfo[uiLoopIndex].uiThreshold); + + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bValid:%X\n",Adapter->PackInfo[uiLoopIndex].bValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"bActive:%X\n",Adapter->PackInfo[uiLoopIndex].bActive); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"ActivateReqSent: %x", Adapter->PackInfo[uiLoopIndex].bActivateRequestSent); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"u8QueueType:%X\n",Adapter->PackInfo[uiLoopIndex].u8QueueType); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxBucketSize:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxBucketSize); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPerSFTxResourceCount:%X\n",atomic_read(&Adapter->PackInfo[uiLoopIndex].uiPerSFTxResourceCount)); + //DumpDebug(DUMP_INFO,(" bCSSupport:%X\n",Adapter->PackInfo[uiLoopIndex].bCSSupport)); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"CurrQueueDepthOnTarget: %x\n", Adapter->PackInfo[uiLoopIndex].uiCurrentQueueDepthOnTarget); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentBytesOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentBytesOnHost); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentPacketsOnHost:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentPacketsOnHost); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountBytes); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiDroppedCountPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiDroppedCountPackets); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentBytes); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiSentPackets:%X\n",Adapter->PackInfo[uiLoopIndex].uiSentPackets); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentDrainRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentDrainRate); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiThisPeriodSentBytes:%X\n",Adapter->PackInfo[uiLoopIndex].uiThisPeriodSentBytes); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liDrainCalculated:%llX\n",Adapter->PackInfo[uiLoopIndex].liDrainCalculated); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiCurrentTokenCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiCurrentTokenCount); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"liLastUpdateTokenAt:%llX\n",Adapter->PackInfo[uiLoopIndex].liLastUpdateTokenAt); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiMaxAllowedRate:%X\n",Adapter->PackInfo[uiLoopIndex].uiMaxAllowedRate); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"uiPendedLast:%X\n",Adapter->PackInfo[uiLoopIndex].uiPendedLast); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"NumOfPacketsSent:%X\n",Adapter->PackInfo[uiLoopIndex].NumOfPacketsSent); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Direction: %x\n", Adapter->PackInfo[uiLoopIndex].ucDirection); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "CID: %x\n", Adapter->PackInfo[uiLoopIndex].usCID); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ProtocolValid: %x\n", Adapter->PackInfo[uiLoopIndex].bProtocolValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "TOSValid: %x\n", Adapter->PackInfo[uiLoopIndex].bTOSValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "DestIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bDestIpValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "SrcIpValid: %x\n", Adapter->PackInfo[uiLoopIndex].bSrcIpValid); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ActiveSet: %x\n", Adapter->PackInfo[uiLoopIndex].bActiveSet); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AdmittedSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAdmittedSet); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "AuthzSet: %x\n", Adapter->PackInfo[uiLoopIndex].bAuthorizedSet); + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ClassifyPrority: %x\n", Adapter->PackInfo[uiLoopIndex].bClassifierPriority); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiMaxLatency: %x\n",Adapter->PackInfo[uiLoopIndex].uiMaxLatency); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "ServiceClassName: %x %x %x %x\n",Adapter->PackInfo[uiLoopIndex].ucServiceClassName[0],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[1],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[2],Adapter->PackInfo[uiLoopIndex].ucServiceClassName[3]); +// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "bHeaderSuppressionEnabled :%X\n", Adapter->PackInfo[uiLoopIndex].bHeaderSuppressionEnabled); +// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalTxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalTxBytes); +// BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "uiTotalRxBytes:%X\n", Adapter->PackInfo[uiLoopIndex].uiTotalRxBytes); +// DumpDebug(DUMP_INFO,(" uiRanOutOfResCount:%X\n",Adapter->PackInfo[uiLoopIndex].uiRanOutOfResCount)); + } + + for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++) + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aRxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aRxPktSizeHist[uiLoopIndex]); + + for(uiLoopIndex = 0 ; uiLoopIndex < MIBS_MAX_HIST_ENTRIES ; uiLoopIndex++) + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL,"Adapter->aTxPktSizeHist[%x] = %x\n",uiLoopIndex,Adapter->aTxPktSizeHist[uiLoopIndex]); + + + + return; + + +} + + +__inline int reset_card_proc(PMINI_ADAPTER ps_adapter) +{ + int retval = STATUS_SUCCESS; + +#ifndef BCM_SHM_INTERFACE + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + PS_INTERFACE_ADAPTER psIntfAdapter = NULL; + unsigned int value = 0, uiResetValue = 0; + + psIntfAdapter = ((PS_INTERFACE_ADAPTER)(ps_adapter->pvInterfaceAdapter)) ; + + ps_adapter->bDDRInitDone = FALSE; + + if(ps_adapter->chip_id >= T3LPB) + { + //SYS_CFG register is write protected hence for modifying this reg value, it should be read twice before + rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value)); + rdmalt(ps_adapter,SYS_CFG, &value, sizeof(value)); + + //making bit[6...5] same as was before f/w download. this setting force the h/w to + //re-populated the SP RAM area with the string descriptor . + value = value | (ps_adapter->syscfgBefFwDld & 0x00000060) ; + wrmalt(ps_adapter, SYS_CFG, &value, sizeof(value)); + } + +#ifndef BCM_SHM_INTERFACE + //killing all submitted URBs. + psIntfAdapter->psAdapter->StopAllXaction = TRUE ; + Bcm_kill_all_URBs(psIntfAdapter); +#endif + /* Reset the UMA-B Device */ + if(ps_adapter->chip_id >= T3LPB) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reseting UMA-B \n"); + retval = usb_reset_device(psIntfAdapter->udev); + + psIntfAdapter->psAdapter->StopAllXaction = FALSE ; + + if(retval != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Reset failed with ret value :%d", retval); + goto err_exit; + } + if (ps_adapter->chip_id == BCS220_2 || + ps_adapter->chip_id == BCS220_2BC || + ps_adapter->chip_id == BCS250_BC || + ps_adapter->chip_id == BCS220_3) + { + retval = rdmalt(ps_adapter,HPM_CONFIG_LDO145, &value, sizeof(value)); + if( retval < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval); + goto err_exit; + } + //setting 0th bit + value |= (1<<0); + retval = wrmalt(ps_adapter, HPM_CONFIG_LDO145, &value, sizeof(value)); + if( retval < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); + goto err_exit; + } + } + + } + else + { + retval = rdmalt(ps_adapter,0x0f007018, &value, sizeof(value)); + if( retval < 0) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"read failed with status :%d",retval); + goto err_exit; + } + value&=(~(1<<16)); + retval= wrmalt(ps_adapter, 0x0f007018, &value, sizeof(value)) ; + if( retval < 0) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); + goto err_exit; + } + + // Toggling the GPIO 8, 9 + value = 0; + retval = wrmalt(ps_adapter, GPIO_OUTPUT_REGISTER, &value, sizeof(value)); + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); + goto err_exit; + } + value = 0x300; + retval = wrmalt(ps_adapter, GPIO_MODE_REGISTER, &value, sizeof(value)) ; + if(retval < 0) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"write failed with status :%d",retval); + goto err_exit; + } + mdelay(50); + } + + //ps_adapter->downloadDDR = false; + + if(ps_adapter->bFlashBoot) + { + //In flash boot mode MIPS state register has reverse polarity. + // So just or with setting bit 30. + //Make the MIPS in Reset state. + rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue)); + + uiResetValue |=(1<<30); + wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &uiResetValue, sizeof(uiResetValue)); + } + + if(ps_adapter->chip_id >= T3LPB) + { + uiResetValue = 0; + // + // WA for SYSConfig Issue. + // Read SYSCFG Twice to make it writable. + // + rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue)); + if(uiResetValue & (1<<4)) + { + uiResetValue = 0; + rdmalt(ps_adapter, SYS_CFG, &uiResetValue, sizeof(uiResetValue));//2nd read to make it writable. + uiResetValue &= (~(1<<4)); + wrmalt(ps_adapter,SYS_CFG, &uiResetValue, sizeof(uiResetValue)); + } + + } + uiResetValue = 0; + wrmalt(ps_adapter, 0x0f01186c, &uiResetValue, sizeof(uiResetValue)); + +err_exit : + psIntfAdapter->psAdapter->StopAllXaction = FALSE ; +#endif + return retval; +} + +__inline int run_card_proc(PMINI_ADAPTER ps_adapter ) +{ + unsigned int value=0; + { + + if(rdmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__); + return STATUS_FAILURE; + } + + if(ps_adapter->bFlashBoot) + { + + value&=(~(1<<30)); + } + else + { + value |=(1<<30); + } + + if(wrmalt(ps_adapter, CLOCK_RESET_CNTRL_REG_1, &value, sizeof(value)) < 0) { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"%s:%d\n", __FUNCTION__, __LINE__); + return STATUS_FAILURE; + } + } + return STATUS_SUCCESS; +} + +int InitCardAndDownloadFirmware(PMINI_ADAPTER ps_adapter) +{ + + UINT status = STATUS_SUCCESS; + UINT value = 0; +#ifdef BCM_SHM_INTERFACE + unsigned char *pConfigFileAddr = (unsigned char *)CPE_MACXVI_CFG_ADDR; +#endif + /* + * Create the threads first and then download the + * Firm/DDR Settings.. + */ + + if((status = create_worker_threads(ps_adapter))<0) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Cannot create thread"); + return status; + } + /* + * For Downloading the Firm, parse the cfg file first. + */ + status = bcm_parse_target_params (ps_adapter); + if(status){ + return status; + } + +#ifndef BCM_SHM_INTERFACE + if(ps_adapter->chip_id >= T3LPB) + { + rdmalt(ps_adapter, SYS_CFG, &value, sizeof (value)); + ps_adapter->syscfgBefFwDld = value ; + if((value & 0x60)== 0) + { + ps_adapter->bFlashBoot = TRUE; + } + } + + reset_card_proc(ps_adapter); + + //Initializing the NVM. + BcmInitNVM(ps_adapter); + status = ddr_init(ps_adapter); + if(status) + { + BCM_DEBUG_PRINT (ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "ddr_init Failed\n"); + return status; + } + + /* Download cfg file */ + status = buffDnldVerify(ps_adapter, + (PUCHAR)ps_adapter->pstargetparams, + sizeof(STARGETPARAMS), + CONFIG_BEGIN_ADDR); + if(status) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Error downloading CFG file"); + goto OUT; + } + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "CFG file downloaded"); + + if(register_networkdev(ps_adapter)) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed."); + return -EIO; + } + + if(FALSE == ps_adapter->AutoFirmDld) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoFirmDld Disabled in CFG File..\n"); + //If Auto f/w download is disable, register the control interface, + //register the control interface after the mailbox. + if(register_control_device_interface(ps_adapter) < 0) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed."); + return -EIO; + } + + return STATUS_SUCCESS; + } + + /* + * Do the LED Settings here. It will be used by the Firmware Download + * Thread. + */ + + /* + * 1. If the LED Settings fails, do not stop and do the Firmware download. + * 2. This init would happend only if the cfg file is present, else + * call from the ioctl context. + */ + + status = InitLedSettings (ps_adapter); + + if(status) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0,"INIT LED FAILED\n"); + return status; + } + if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + ps_adapter->DriverState = DRIVER_INIT; + wake_up(&ps_adapter->LEDInfo.notify_led_event); + } + + if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + ps_adapter->DriverState = FW_DOWNLOAD; + wake_up(&ps_adapter->LEDInfo.notify_led_event); + } + + value = 0; + wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); + wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); + + if(ps_adapter->eNVMType == NVM_FLASH) + { + status = PropagateCalParamsFromFlashToMemory(ps_adapter); + if(status) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propogation of Cal param failed .." ); + goto OUT; + } + } +#if 0 + else if(psAdapter->eNVMType == NVM_EEPROM) + { + PropagateCalParamsFromEEPROMToMemory(); + } +#endif + + /* Download Firmare */ + if ((status = BcmFileDownload( ps_adapter, BIN_FILE, FIRMWARE_BEGIN_ADDR))) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "No Firmware File is present... \n"); + goto OUT; + } + + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "BIN file downloaded"); + status = run_card_proc(ps_adapter); + if(status) + { + BCM_DEBUG_PRINT (ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "run_card_proc Failed\n"); + goto OUT; + } + + + ps_adapter->fw_download_done = TRUE; + mdelay(10); + +OUT: + if(ps_adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + ps_adapter->DriverState = FW_DOWNLOAD_DONE; + wake_up(&ps_adapter->LEDInfo.notify_led_event); + } + +#else + + ps_adapter->bDDRInitDone = TRUE; + //Initializing the NVM. + BcmInitNVM(ps_adapter); + + //Propagating the cal param from Flash to DDR + value = 0; + wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); + wrmalt(ps_adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); + + if(ps_adapter->eNVMType == NVM_FLASH) + { + status = PropagateCalParamsFromFlashToMemory(ps_adapter); + if(status) + { + printk("\nPropogation of Cal param from flash to DDR failed ..\n" ); + } + } + + //Copy config file param to DDR. + memcpy(pConfigFileAddr,ps_adapter->pstargetparams, sizeof(STARGETPARAMS)); + + if(register_networkdev(ps_adapter)) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Netdevice failed. Cleanup needs to be performed."); + return -EIO; + } + + + status = InitLedSettings (ps_adapter); + if(status) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0,"INIT LED FAILED\n"); + return status; + } + + + if(register_control_device_interface(ps_adapter) < 0) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Register Control Device failed. Cleanup needs to be performed."); + return -EIO; + } + + ps_adapter->fw_download_done = TRUE; +#endif + return status; +} + + +int bcm_parse_target_params(PMINI_ADAPTER Adapter) +{ +#ifdef BCM_SHM_INTERFACE + extern void read_cfg_file(PMINI_ADAPTER Adapter); +#endif + struct file *flp=NULL; + mm_segment_t oldfs={0}; + char *buff = NULL; + int len = 0; + loff_t pos = 0; + + buff=(PCHAR)kmalloc(BUFFER_1K, GFP_KERNEL); + if(!buff) + { + return -ENOMEM; + } + if((Adapter->pstargetparams = + kmalloc(sizeof(STARGETPARAMS), GFP_KERNEL)) == NULL) + { + bcm_kfree(buff); + return -ENOMEM; + } + flp=open_firmware_file(Adapter, CFG_FILE); + if(!flp) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "NOT ABLE TO OPEN THE %s FILE \n", CFG_FILE); + bcm_kfree(buff); + bcm_kfree(Adapter->pstargetparams); + Adapter->pstargetparams = NULL; + return -ENOENT; + } + oldfs=get_fs(); set_fs(get_ds()); + len=vfs_read(flp, buff, BUFFER_1K, &pos); + set_fs(oldfs); + + if(len != sizeof(STARGETPARAMS)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Mismatch in Target Param Structure!\n"); + bcm_kfree(buff); + bcm_kfree(Adapter->pstargetparams); + Adapter->pstargetparams = NULL; + filp_close(flp, current->files); + return -ENOENT; + } + filp_close(flp, current->files); + + /* Check for autolink in config params */ + /* + * Values in Adapter->pstargetparams are in network byte order + */ + memcpy(Adapter->pstargetparams, buff, sizeof(STARGETPARAMS)); + bcm_kfree (buff); + beceem_parse_target_struct(Adapter); +#ifdef BCM_SHM_INTERFACE + read_cfg_file(Adapter); + +#endif + return STATUS_SUCCESS; +} + +void beceem_parse_target_struct(PMINI_ADAPTER Adapter) +{ + UINT uiHostDrvrCfg6 =0, uiEEPROMFlag = 0;; + + if(ntohl(Adapter->pstargetparams->m_u32PhyParameter2) & AUTO_SYNC_DISABLE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoSyncup is Disabled\n"); + Adapter->AutoSyncup = FALSE; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "AutoSyncup is Enabled\n"); + Adapter->AutoSyncup = TRUE; + } + if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_LINKUP_ENABLE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Enabling autolink up"); + Adapter->AutoLinkUp = TRUE; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Disabling autolink up"); + Adapter->AutoLinkUp = FALSE; + } + // Setting the DDR Setting.. + Adapter->DDRSetting = + (ntohl(Adapter->pstargetparams->HostDrvrConfig6) >>8)&0x0F; + Adapter->ulPowerSaveMode = + (ntohl(Adapter->pstargetparams->HostDrvrConfig6)>>12)&0x0F; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "DDR Setting: %x\n", Adapter->DDRSetting); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT,DBG_LVL_ALL, "Power Save Mode: %lx\n", + Adapter->ulPowerSaveMode); + if(ntohl(Adapter->pstargetparams->HostDrvrConfig6) & AUTO_FIRM_DOWNLOAD) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Enabling Auto Firmware Download\n"); + Adapter->AutoFirmDld = TRUE; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Disabling Auto Firmware Download\n"); + Adapter->AutoFirmDld = FALSE; + } + uiHostDrvrCfg6 = ntohl(Adapter->pstargetparams->HostDrvrConfig6); + Adapter->bMipsConfig = (uiHostDrvrCfg6>>20)&0x01; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"MIPSConfig : 0x%X\n",Adapter->bMipsConfig); + //used for backward compatibility. + Adapter->bDPLLConfig = (uiHostDrvrCfg6>>19)&0x01; + + Adapter->PmuMode= (uiHostDrvrCfg6 >> 24 ) & 0x03; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "PMU MODE: %x", Adapter->PmuMode); + + if((uiHostDrvrCfg6 >> HOST_BUS_SUSPEND_BIT ) & (0x01)) + { + Adapter->bDoSuspend = TRUE; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Making DoSuspend TRUE as per configFile"); + } + + uiEEPROMFlag = ntohl(Adapter->pstargetparams->m_u32EEPROMFlag); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "uiEEPROMFlag : 0x%X\n",uiEEPROMFlag); + Adapter->eNVMType = (NVM_TYPE)((uiEEPROMFlag>>4)&0x3); + + + Adapter->bStatusWrite = (uiEEPROMFlag>>6)&0x1; + //printk(("bStatusWrite : 0x%X\n", Adapter->bStatusWrite)); + + Adapter->uiSectorSizeInCFG = 1024*(0xFFFF & ntohl(Adapter->pstargetparams->HostDrvrConfig4)); + //printk(("uiSectorSize : 0x%X\n", Adapter->uiSectorSizeInCFG)); + + Adapter->bSectorSizeOverride =(bool) ((ntohl(Adapter->pstargetparams->HostDrvrConfig4))>>16)&0x1; + //printk(MP_INIT,("bSectorSizeOverride : 0x%X\n",Adapter->bSectorSizeOverride)); + + if(ntohl(Adapter->pstargetparams->m_u32PowerSavingModeOptions) &0x01) + Adapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE; + //autocorrection part + if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) + doPowerAutoCorrection(Adapter); + +} + +VOID doPowerAutoCorrection(PMINI_ADAPTER psAdapter) +{ + UINT reporting_mode = 0; + + reporting_mode = ntohl(psAdapter->pstargetparams->m_u32PowerSavingModeOptions) &0x02 ; + psAdapter->bIsAutoCorrectEnabled = !((char)(psAdapter->ulPowerSaveMode >> 3) & 0x1); + + if(reporting_mode == TRUE) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"can't do suspen/resume as reporting mode is enable"); + psAdapter->bDoSuspend = FALSE; + } + + if (psAdapter->bIsAutoCorrectEnabled && (psAdapter->chip_id >= T3LPB)) + { + //If reporting mode is enable, switch PMU to PMC + #if 0 + if(reporting_mode == FALSE) + { + psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN; + psAdapter->bDoSuspend = TRUE; + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"PMU selected ...."); + + } + else + #endif + { + psAdapter->ulPowerSaveMode = DEVICE_POWERSAVE_MODE_AS_PMU_CLOCK_GATING; + psAdapter->bDoSuspend =FALSE; + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"PMC selected.."); + + } + + //clearing space bit[15..12] + psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl((0xF << 12))); + //placing the power save mode option + psAdapter->pstargetparams->HostDrvrConfig6 |= htonl((psAdapter->ulPowerSaveMode << 12)); + + } + else if (psAdapter->bIsAutoCorrectEnabled == FALSE) + { + + // remove the autocorrect disable bit set before dumping. + psAdapter->ulPowerSaveMode &= ~(1 << 3); + psAdapter->pstargetparams->HostDrvrConfig6 &= ~(htonl(1 << 15)); + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL,"Using Forced User Choice: %lx\n", psAdapter->ulPowerSaveMode); + } +} +unsigned char *ReadMacAddrEEPROM(PMINI_ADAPTER Adapter, ulong dwAddress) +{ + unsigned char *pucmacaddr = NULL; + int status = 0, i=0; + unsigned int temp =0; + + + pucmacaddr = (unsigned char *)kmalloc(MAC_ADDRESS_SIZE, GFP_KERNEL); + if(!pucmacaddr) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "No Buffers to Read the EEPROM Address\n"); + return NULL; + } + + dwAddress |= 0x5b000000; + status = wrmalt(Adapter, EEPROM_COMMAND_Q_REG, + (PUINT)&dwAddress, sizeof(UINT)); + if(status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "wrm Failed..\n"); + bcm_kfree(pucmacaddr); + pucmacaddr = NULL; + goto OUT; + } + for(i=0;idev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); + for(i=0;idev->dev_addr[i]); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"\n"); + bcm_kfree(puMacAddr); + } + return STATUS_SUCCESS; +} +#endif + +void convertEndian(B_UINT8 rwFlag, PUINT puiBuffer, UINT uiByteCount) +{ + UINT uiIndex = 0; + + if(RWM_WRITE == rwFlag) { + for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) { + puiBuffer[uiIndex] = htonl(puiBuffer[uiIndex]); + } + } else { + for(uiIndex =0; uiIndex < (uiByteCount/sizeof(UINT)); uiIndex++) { + puiBuffer[uiIndex] = ntohl(puiBuffer[uiIndex]); + } + } +} + +#define CACHE_ADDRESS_MASK 0x80000000 +#define UNCACHE_ADDRESS_MASK 0xa0000000 + +int rdm(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) +{ + INT uiRetVal =0; + +#ifndef BCM_SHM_INTERFACE + uiRetVal = Adapter->interface_rdm(Adapter->pvInterfaceAdapter, + uiAddress, pucBuff, sSize); + + if(uiRetVal < 0) + return uiRetVal; + +#else + int indx; + uiRetVal = STATUS_SUCCESS; + if(uiAddress & 0x10000000) { + // DDR Memory Access + uiAddress |= CACHE_ADDRESS_MASK; + memcpy(pucBuff,(unsigned char *)uiAddress ,sSize); + } + else { + // Register, SPRAM, Flash + uiAddress |= UNCACHE_ADDRESS_MASK; + if ((uiAddress & FLASH_ADDR_MASK) == (FLASH_CONTIGIOUS_START_ADDR_BCS350 & FLASH_ADDR_MASK)) + { + #if defined(FLASH_DIRECT_ACCESS) + memcpy(pucBuff,(unsigned char *)uiAddress ,sSize); + #else + printk("\nInvalid GSPI ACCESS :Addr :%#X", uiAddress); + uiRetVal = STATUS_FAILURE; + #endif + } + else if(((unsigned int )uiAddress & 0x3) || + ((unsigned int )pucBuff & 0x3) || + ((unsigned int )sSize & 0x3)) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"rdmalt :unalligned register access uiAddress = %x,pucBuff = %x size = %x\n",(unsigned int )uiAddress,(unsigned int )pucBuff,(unsigned int )sSize); + uiRetVal = STATUS_FAILURE; + } + else { + for (indx=0;indxinterface_wrm(Adapter->pvInterfaceAdapter, + uiAddress, pucBuff, sSize); + +#else + int indx; + if(uiAddress & 0x10000000) { + // DDR Memory Access + uiAddress |= CACHE_ADDRESS_MASK; + memcpy((unsigned char *)(uiAddress),pucBuff,sSize); + } + else { + // Register, SPRAM, Flash + uiAddress |= UNCACHE_ADDRESS_MASK; + + if(((unsigned int )uiAddress & 0x3) || + ((unsigned int )pucBuff & 0x3) || + ((unsigned int )sSize & 0x3)) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"wrmalt: unalligned register access uiAddress = %x,pucBuff = %x size = %x\n",(unsigned int )uiAddress,(unsigned int )pucBuff,(unsigned int )sSize); + iRetVal = STATUS_FAILURE; + } + else { + for (indx=0;indxrdmwrmsync); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + status = -EACCES; + goto exit; + } + + status = rdm(Adapter, uiAddress, pucBuff, sSize); + +exit: + up(&Adapter->rdmwrmsync); + return status ; +} +int wrmWithLock(PMINI_ADAPTER Adapter, UINT uiAddress, PCHAR pucBuff, size_t sSize) +{ + INT status = STATUS_SUCCESS ; + down(&Adapter->rdmwrmsync); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + status = -EACCES; + goto exit; + } + + status =wrm(Adapter, uiAddress, pucBuff, sSize); + +exit: + up(&Adapter->rdmwrmsync); + return status ; +} + +int wrmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) +{ + int iRetVal = STATUS_SUCCESS; + + down(&Adapter->rdmwrmsync); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + iRetVal = -EACCES; + goto exit; + } + + iRetVal = wrmalt(Adapter,uiAddress,pucBuff,size); + +exit: + up(&Adapter->rdmwrmsync); + return iRetVal; +} + +int rdmaltWithLock (PMINI_ADAPTER Adapter, UINT uiAddress, PUINT pucBuff, size_t size) +{ + INT uiRetVal =STATUS_SUCCESS; + + down(&Adapter->rdmwrmsync); + + if((Adapter->IdleMode == TRUE) || + (Adapter->bShutStatus ==TRUE) || + (Adapter->bPreparingForLowPowerMode ==TRUE)) + { + uiRetVal = -EACCES; + goto exit; + } + + uiRetVal = rdmalt(Adapter,uiAddress, pucBuff, size); + +exit: + up(&Adapter->rdmwrmsync); + return uiRetVal; +} + + +VOID HandleShutDownModeWakeup(PMINI_ADAPTER Adapter) +{ + int clear_abort_pattern = 0,Status = 0; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n"); + //target has woken up From Shut Down + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Clearing Shut Down Software abort pattern\n"); + Status = wrmalt(Adapter,SW_ABORT_IDLEMODE_LOC, (PUINT)&clear_abort_pattern, sizeof(clear_abort_pattern)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"WRM to SW_ABORT_IDLEMODE_LOC failed with err:%d", Status); + return; + } + if(Adapter->ulPowerSaveMode != DEVICE_POWERSAVE_MODE_AS_PROTOCOL_IDLE_MODE) + { + msleep(100); + InterfaceHandleShutdownModeWakeup(Adapter); + msleep(100); + } + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + Adapter->DriverState = NO_NETWORK_ENTRY; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + + Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; + Adapter->bShutStatus = FALSE; + wake_up(&Adapter->lowpower_mode_wait_queue); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n"); +} + +VOID SendShutModeResponse(PMINI_ADAPTER Adapter) +{ + CONTROL_MESSAGE stShutdownResponse; + UINT NVMAccess = 0,lowPwrAbortMsg = 0; + UINT Status = 0; + + memset (&stShutdownResponse, 0, sizeof(CONTROL_MESSAGE)); + stShutdownResponse.Leader.Status = LINK_UP_CONTROL_REQ; + stShutdownResponse.Leader.PLength = 8;//8 bytes; + stShutdownResponse.szData[0] = LINK_UP_ACK; + stShutdownResponse.szData[1] = LINK_SHUTDOWN_REQ_FROM_FIRMWARE; + + /********************************* + **down_trylock - + ** if [ semaphore is available ] + ** acquire semaphone and return value 0 ; + ** else + ** return non-zero value ; + ** + ***********************************/ + + NVMAccess = down_trylock(&Adapter->NVMRdmWrmLock); + + lowPwrAbortMsg= down_trylock(&Adapter->LowPowerModeSync); + + + if(NVMAccess || lowPwrAbortMsg|| atomic_read(&Adapter->TotalPacketCount)) + { + if(!NVMAccess) + up(&Adapter->NVMRdmWrmLock); + + if(!lowPwrAbortMsg) + up(&Adapter->LowPowerModeSync); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Device Access is going on NACK the Shut Down MODE\n"); + stShutdownResponse.szData[2] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on. + Adapter->bPreparingForLowPowerMode = FALSE; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "Sending SHUTDOWN MODE ACK\n"); + stShutdownResponse.szData[2] = SHUTDOWN_ACK_FROM_DRIVER;//ShutDown ACK + + /* Wait for the LED to TURN OFF before sending ACK response */ + if(Adapter->LEDInfo.led_thread_running & BCM_LED_THREAD_RUNNING_ACTIVELY) + { + INT iRetVal = 0; + + /* Wake the LED Thread with LOWPOWER_MODE_ENTER State */ + Adapter->DriverState = LOWPOWER_MODE_ENTER; + wake_up(&Adapter->LEDInfo.notify_led_event); + + /* Wait for 1 SEC for LED to OFF */ + iRetVal = wait_event_timeout(Adapter->LEDInfo.idleModeSyncEvent,\ + Adapter->LEDInfo.bIdle_led_off, msecs_to_jiffies(1000)); + + /* If Timed Out to Sync IDLE MODE Enter, do IDLE mode Exit and Send NACK to device */ + if(iRetVal <= 0) + { + stShutdownResponse.szData[1] = SHUTDOWN_NACK_FROM_DRIVER;//NACK- device access is going on. + + Adapter->DriverState = NO_NETWORK_ENTRY; + wake_up(&Adapter->LEDInfo.notify_led_event); + } + } + + if(stShutdownResponse.szData[2] == SHUTDOWN_ACK_FROM_DRIVER) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ACKING SHUTDOWN MODE !!!!!!!!!"); + down(&Adapter->rdmwrmsync); + Adapter->bPreparingForLowPowerMode = TRUE; + up(&Adapter->rdmwrmsync); + //Killing all URBS. +#ifndef BCM_SHM_INTERFACE + if(Adapter->bDoSuspend == TRUE) + Bcm_kill_all_URBs((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); +#endif + } + else + { + Adapter->bPreparingForLowPowerMode = FALSE; + } + + if(!NVMAccess) + up(&Adapter->NVMRdmWrmLock); + + if(!lowPwrAbortMsg) + up(&Adapter->LowPowerModeSync); + } + Status = CopyBufferToControlPacket(Adapter,&stShutdownResponse); + if((Status != STATUS_SUCCESS)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"fail to send the Idle mode Request \n"); + Adapter->bPreparingForLowPowerMode = FALSE; + +#ifndef BCM_SHM_INTERFACE + StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); +#endif + } +} + + +void HandleShutDownModeRequest(PMINI_ADAPTER Adapter,PUCHAR pucBuffer) +{ + B_UINT32 uiResetValue = 0; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "====>\n"); + + if(*(pucBuffer+1) == COMPLETE_WAKE_UP_NOTIFICATION_FRM_FW) + { + HandleShutDownModeWakeup(Adapter); + } + else if(*(pucBuffer+1) == LINK_SHUTDOWN_REQ_FROM_FIRMWARE) + { + //Target wants to go to Shut Down Mode + //InterfacePrepareForShutdown(Adapter); + if(Adapter->chip_id == BCS220_2 || + Adapter->chip_id == BCS220_2BC || + Adapter->chip_id == BCS250_BC || + Adapter->chip_id == BCS220_3) + { + rdmalt(Adapter,HPM_CONFIG_MSW, &uiResetValue, 4); + uiResetValue |= (1<<17); + wrmalt(Adapter, HPM_CONFIG_MSW, &uiResetValue, 4); + } + + SendShutModeResponse(Adapter); + BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL,"ShutDownModeResponse:Notification received: Sending the response(Ack/Nack)\n"); + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, MP_SHUTDOWN, DBG_LVL_ALL, "<====\n"); + return; + +} + +VOID ResetCounters(PMINI_ADAPTER Adapter) +{ + + beceem_protocol_reset(Adapter); + + Adapter->CurrNumRecvDescs = 0; + Adapter->PrevNumRecvDescs = 0; + Adapter->LinkUpStatus = 0; + Adapter->LinkStatus = 0; + atomic_set(&Adapter->cntrlpktCnt,0); + atomic_set (&Adapter->TotalPacketCount,0); + Adapter->fw_download_done=FALSE; + Adapter->LinkStatus = 0; + Adapter->AutoLinkUp = FALSE; + Adapter->IdleMode = FALSE; + Adapter->bShutStatus = FALSE; + +} +S_CLASSIFIER_RULE *GetFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIP) +{ + UINT uiIndex=0; + for(uiIndex=0;uiIndexastFragmentedPktClassifierTable[uiIndex].bUsed)&& + (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&& + (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIP)&& + !Adapter->astFragmentedPktClassifierTable[uiIndex].bOutOfOrderFragment) + return Adapter->astFragmentedPktClassifierTable[uiIndex].pstMatchedClassifierEntry; + } + return NULL; +} + +void AddFragIPClsEntry(PMINI_ADAPTER Adapter,PS_FRAGMENTED_PACKET_INFO psFragPktInfo) +{ + UINT uiIndex=0; + for(uiIndex=0;uiIndexastFragmentedPktClassifierTable[uiIndex].bUsed) + { + memcpy(&Adapter->astFragmentedPktClassifierTable[uiIndex],psFragPktInfo,sizeof(S_FRAGMENTED_PACKET_INFO)); + break; + } + } + +} + +void DelFragIPClsEntry(PMINI_ADAPTER Adapter,USHORT usIpIdentification,ULONG SrcIp) +{ + UINT uiIndex=0; + for(uiIndex=0;uiIndexastFragmentedPktClassifierTable[uiIndex].bUsed)&& + (Adapter->astFragmentedPktClassifierTable[uiIndex].usIpIdentification == usIpIdentification)&& + (Adapter->astFragmentedPktClassifierTable[uiIndex].ulSrcIpAddress== SrcIp)) + memset(&Adapter->astFragmentedPktClassifierTable[uiIndex],0,sizeof(S_FRAGMENTED_PACKET_INFO)); + } +} + +void update_per_cid_rx (PMINI_ADAPTER Adapter) +{ + UINT qindex = 0; + + if((jiffies - Adapter->liDrainCalculated) < XSECONDS) + return; + + for(qindex = 0; qindex < HiPriority; qindex++) + { + if(Adapter->PackInfo[qindex].ucDirection == 0) + { + Adapter->PackInfo[qindex].uiCurrentRxRate = + (Adapter->PackInfo[qindex].uiCurrentRxRate + + Adapter->PackInfo[qindex].uiThisPeriodRxBytes)/2; + + Adapter->PackInfo[qindex].uiThisPeriodRxBytes = 0; + } + else + { + Adapter->PackInfo[qindex].uiCurrentDrainRate = + (Adapter->PackInfo[qindex].uiCurrentDrainRate + + Adapter->PackInfo[qindex].uiThisPeriodSentBytes)/2; + + Adapter->PackInfo[qindex].uiThisPeriodSentBytes=0; + } + } + Adapter->liDrainCalculated=jiffies; +} +void update_per_sf_desc_cnts( PMINI_ADAPTER Adapter) +{ + INT iIndex = 0; + u32 uibuff[MAX_TARGET_DSX_BUFFERS]; + + if(!atomic_read (&Adapter->uiMBupdate)) + return; + +#ifdef BCM_SHM_INTERFACE + if(rdmalt(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS)<0) +#else + if(rdmaltWithLock(Adapter, TARGET_SFID_TXDESC_MAP_LOC, (PUINT)uibuff, sizeof(UINT) * MAX_TARGET_DSX_BUFFERS)<0) +#endif + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "rdm failed\n"); + return; + } + for(iIndex = 0;iIndex < HiPriority; iIndex++) + { + if(Adapter->PackInfo[iIndex].bValid && Adapter->PackInfo[iIndex].ucDirection) + { + if(Adapter->PackInfo[iIndex].usVCID_Value < MAX_TARGET_DSX_BUFFERS) + { + atomic_set(&Adapter->PackInfo[iIndex].uiPerSFTxResourceCount, uibuff[Adapter->PackInfo[iIndex].usVCID_Value]); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid VCID : %x \n", + Adapter->PackInfo[iIndex].usVCID_Value); + } + } + } + atomic_set (&Adapter->uiMBupdate, FALSE); +} + +void flush_queue(PMINI_ADAPTER Adapter, UINT iQIndex) +{ + struct sk_buff* PacketToDrop=NULL; + struct net_device_stats* netstats=NULL; + + netstats = &((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats; + + spin_lock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); + + while(Adapter->PackInfo[iQIndex].FirstTxQueue && + atomic_read(&Adapter->TotalPacketCount)) + { + PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue; + if(PacketToDrop && PacketToDrop->len) + { + netstats->tx_dropped++; + DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, \ + Adapter->PackInfo[iQIndex].LastTxQueue); + + Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--; + Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= PacketToDrop->len; + + //Adding dropped statistics + Adapter->PackInfo[iQIndex].uiDroppedCountBytes += PacketToDrop->len; + Adapter->PackInfo[iQIndex].uiDroppedCountPackets++; + + bcm_kfree_skb(PacketToDrop); + atomic_dec(&Adapter->TotalPacketCount); + atomic_inc(&Adapter->TxDroppedPacketCount); + + } + } + spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); + +} + +void beceem_protocol_reset (PMINI_ADAPTER Adapter) +{ + int i =0; + + if(NULL != Adapter->dev) + { + netif_carrier_off(Adapter->dev); + netif_stop_queue(Adapter->dev); + } + + Adapter->IdleMode = FALSE; + Adapter->LinkUpStatus = FALSE; + ClearTargetDSXBuffer(Adapter,0, TRUE); + //Delete All Classifier Rules + + for(i = 0;iTimerActive == TRUE) + Adapter->TimerActive = FALSE; + + memset(Adapter->astFragmentedPktClassifierTable, 0, + sizeof(S_FRAGMENTED_PACKET_INFO) * + MAX_FRAGMENTEDIP_CLASSIFICATION_ENTRIES); + + for(i = 0;iPackInfo[i],0,sizeof(S_MIBS_SERVICEFLOW_TABLE)); + } +} + + + +#ifdef BCM_SHM_INTERFACE + + +#define GET_GTB_DIFF(start, end) \ +( (start) < (end) )? ( (end) - (start) ) : ( ~0x0 - ( (start) - (end)) +1 ) + +void usdelay ( unsigned int a) { + unsigned int start= *(unsigned int *)0xaf8051b4; + unsigned int end = start+1; + unsigned int diff = 0; + + while(1) { + end = *(unsigned int *)0xaf8051b4; + diff = (GET_GTB_DIFF(start,end))/80; + if (diff >= a) + break; + } +} +void read_cfg_file(PMINI_ADAPTER Adapter) { + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Config File Version = 0x%x \n",Adapter->pstargetparams->m_u32CfgVersion ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Center Frequency = 0x%x \n",Adapter->pstargetparams->m_u32CenterFrequency ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Band A Scan = 0x%x \n",Adapter->pstargetparams->m_u32BandAScan ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Band B Scan = 0x%x \n",Adapter->pstargetparams->m_u32BandBScan ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Band C Scan = 0x%x \n",Adapter->pstargetparams->m_u32BandCScan ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"ERTPS Options = 0x%x \n",Adapter->pstargetparams->m_u32ErtpsOptions ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PHS Enable = 0x%x \n",Adapter->pstargetparams->m_u32PHSEnable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Handoff Enable = 0x%x \n",Adapter->pstargetparams->m_u32HoEnable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HO Reserved1 = 0x%x \n",Adapter->pstargetparams->m_u32HoReserved1 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HO Reserved2 = 0x%x \n",Adapter->pstargetparams->m_u32HoReserved2 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"MIMO Enable = 0x%x \n",Adapter->pstargetparams->m_u32MimoEnable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PKMv2 Enable = 0x%x \n",Adapter->pstargetparams->m_u32SecurityEnable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Powersaving Modes Enable = 0x%x \n",Adapter->pstargetparams->m_u32PowerSavingModesEnable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Power Saving Mode Options = 0x%x \n",Adapter->pstargetparams->m_u32PowerSavingModeOptions ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"ARQ Enable = 0x%x \n",Adapter->pstargetparams->m_u32ArqEnable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Harq Enable = 0x%x \n",Adapter->pstargetparams->m_u32HarqEnable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"EEPROM Flag = 0x%x \n",Adapter->pstargetparams->m_u32EEPROMFlag ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Customize = 0x%x \n",Adapter->pstargetparams->m_u32Customize ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Bandwidth = 0x%x \n",Adapter->pstargetparams->m_u32ConfigBW ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"ShutDown Timer Value = 0x%x \n",Adapter->pstargetparams->m_u32ShutDownInitThresholdTimer ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"RadioParameter = 0x%x \n",Adapter->pstargetparams->m_u32RadioParameter ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PhyParameter1 = 0x%x \n",Adapter->pstargetparams->m_u32PhyParameter1 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PhyParameter2 = 0x%x \n",Adapter->pstargetparams->m_u32PhyParameter2 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"PhyParameter3 = 0x%x \n",Adapter->pstargetparams->m_u32PhyParameter3 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"m_u32TestOptions = 0x%x \n",Adapter->pstargetparams->m_u32TestOptions ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"MaxMACDataperDLFrame = 0x%x \n",Adapter->pstargetparams->m_u32MaxMACDataperDLFrame ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"MaxMACDataperULFrame = 0x%x \n",Adapter->pstargetparams->m_u32MaxMACDataperULFrame ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Corr2MacFlags = 0x%x \n",Adapter->pstargetparams->m_u32Corr2MacFlags ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig1 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig1 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig2 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig2 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig3 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig3 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig4 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig4 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig5 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig5 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"HostDrvrConfig6 = 0x%x \n",Adapter->pstargetparams->HostDrvrConfig6 ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Segmented PUSC Enable = 0x%x \n",Adapter->pstargetparams->m_u32SegmentedPUSCenable ); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BamcEnable = 0x%x \n",Adapter->pstargetparams->m_u32BandAMCEnable ); +} + +#endif + + diff --git a/drivers/staging/bcm/Osal_Misc.c b/drivers/staging/bcm/Osal_Misc.c new file mode 100644 index 0000000..feefd20 --- /dev/null +++ b/drivers/staging/bcm/Osal_Misc.c @@ -0,0 +1,27 @@ + /*++ + + Copyright (c) Beceem Communications Inc. + + Module Name: + WIN_Misc.c + + Abstract: + Implements the Miscelanneous OS Construts + Linked Lists + Dispatcher Objects(Events,Semaphores,Spin Locks and the like) + Files + + Revision History: + Who When What + -------- -------- ---------------------------------------------- + Name Date Created/reviewed/modified + Rajeev 24/1/08 Created + Notes: + + --*/ +#include "headers.h" + +bool OsalMemCompare(void *dest, void *src, UINT len) +{ + return (memcmp(src, dest, len)); +} diff --git a/drivers/staging/bcm/PHSDefines.h b/drivers/staging/bcm/PHSDefines.h new file mode 100644 index 0000000..9889a99 --- /dev/null +++ b/drivers/staging/bcm/PHSDefines.h @@ -0,0 +1,125 @@ +#ifndef BCM_PHS_DEFINES_H +#define BCM_PHS_DEFINES_H + +#define PHS_INVALID_TABLE_INDEX 0xffffffff + +/************************* MACROS **********************************************/ +#define PHS_MEM_TAG '_SHP' + + + +//PHS Defines +#define STATUS_PHS_COMPRESSED 0xa1 +#define STATUS_PHS_NOCOMPRESSION 0xa2 +#define APPLY_PHS 1 +#define MAX_NO_BIT 7 +#define ZERO_PHSI 0 +#define VERIFY 0 +#define SIZE_MULTIPLE_32 4 +#define UNCOMPRESSED_PACKET 0 +#define DYNAMIC 0 +#define SUPPRESS 0x80 +#define NO_CLASSIFIER_MATCH 0 +#define SEND_PACKET_UNCOMPRESSED 0 +#define PHSI_IS_ZERO 0 +#define PHSI_LEN 1 +#define ERROR_LEN 0 +#define PHS_BUFFER_SIZE 1532 + + +//#define MAX_PHS_LENGTHS 100 +#define MAX_PHSRULE_PER_SF 20 +#define MAX_SERVICEFLOWS 17 + +//PHS Error Defines +#define PHS_SUCCESS 0 +#define ERR_PHS_INVALID_DEVICE_EXETENSION 0x800 +#define ERR_PHS_INVALID_PHS_RULE 0x801 +#define ERR_PHS_RULE_ALREADY_EXISTS 0x802 +#define ERR_SF_MATCH_FAIL 0x803 +#define ERR_INVALID_CLASSIFIERTABLE_FOR_SF 0x804 +#define ERR_SFTABLE_FULL 0x805 +#define ERR_CLSASSIFIER_TABLE_FULL 0x806 +#define ERR_PHSRULE_MEMALLOC_FAIL 0x807 +#define ERR_CLSID_MATCH_FAIL 0x808 +#define ERR_PHSRULE_MATCH_FAIL 0x809 + +typedef struct _S_PHS_RULE +{ + /// brief 8bit PHSI Of The Service Flow + B_UINT8 u8PHSI; + /// brief PHSF Of The Service Flow + B_UINT8 u8PHSFLength; + B_UINT8 u8PHSF[MAX_PHS_LENGTHS]; + /// brief PHSM Of The Service Flow + B_UINT8 u8PHSMLength; + B_UINT8 u8PHSM[MAX_PHS_LENGTHS]; + /// brief 8bit PHSS Of The Service Flow + B_UINT8 u8PHSS; + /// brief 8bit PHSV Of The Service Flow + B_UINT8 u8PHSV; + //Reference Count for this PHS Rule + B_UINT8 u8RefCnt; + //Flag to Store Unclassified PHS rules only in DL + B_UINT8 bUnclassifiedPHSRule; + + B_UINT8 u8Reserved[3]; + + LONG PHSModifiedBytes; + ULONG PHSModifiedNumPackets; + ULONG PHSErrorNumPackets; +}S_PHS_RULE; + + +typedef enum _E_CLASSIFIER_ENTRY_CONTEXT +{ + eActiveClassifierRuleContext, + eOldClassifierRuleContext +}E_CLASSIFIER_ENTRY_CONTEXT; + +typedef struct _S_CLASSIFIER_ENTRY +{ + B_UINT8 bUsed; + B_UINT16 uiClassifierRuleId; + B_UINT8 u8PHSI; + S_PHS_RULE *pstPhsRule; + B_UINT8 bUnclassifiedPHSRule; + +}S_CLASSIFIER_ENTRY; + + +typedef struct _S_CLASSIFIER_TABLE +{ + B_UINT16 uiTotalClassifiers; + S_CLASSIFIER_ENTRY stActivePhsRulesList[MAX_PHSRULE_PER_SF]; + S_CLASSIFIER_ENTRY stOldPhsRulesList[MAX_PHSRULE_PER_SF]; + B_UINT16 uiOldestPhsRuleIndex; + +}S_CLASSIFIER_TABLE; + + +typedef struct _S_SERVICEFLOW_ENTRY +{ + B_UINT8 bUsed; + B_UINT16 uiVcid; + S_CLASSIFIER_TABLE *pstClassifierTable; +}S_SERVICEFLOW_ENTRY; + +typedef struct _S_SERVICEFLOW_TABLE +{ + B_UINT16 uiTotalServiceFlows; + S_SERVICEFLOW_ENTRY stSFList[MAX_SERVICEFLOWS]; + +}S_SERVICEFLOW_TABLE; + + +typedef struct _PHS_DEVICE_EXTENSION +{ + /* PHS Specific data*/ + S_SERVICEFLOW_TABLE *pstServiceFlowPhsRulesTable; + void *CompressedTxBuffer; + void *UnCompressedRxBuffer; +}PHS_DEVICE_EXTENSION,*PPHS_DEVICE_EXTENSION; + + +#endif diff --git a/drivers/staging/bcm/PHSModule.c b/drivers/staging/bcm/PHSModule.c new file mode 100644 index 0000000..8ba8489 --- /dev/null +++ b/drivers/staging/bcm/PHSModule.c @@ -0,0 +1,1641 @@ +#include "headers.h" + +#define IN +#define OUT + +void DumpDataPacketHeader(PUCHAR pPkt); + +/* +Function: PHSTransmit + +Description: This routine handle PHS(Payload Header Suppression for Tx path. + It extracts a fragment of the NDIS_PACKET containing the header + to be suppressed.It then supresses the header by invoking PHS exported compress routine. + The header data after supression is copied back to the NDIS_PACKET. + + +Input parameters: IN PMINI_ADAPTER Adapter - Miniport Adapter Context + IN Packet - NDIS packet containing data to be transmitted + IN USHORT Vcid - vcid pertaining to connection on which the packet is being sent.Used to + identify PHS rule to be applied. + B_UINT16 uiClassifierRuleID - Classifier Rule ID + BOOLEAN bHeaderSuppressionEnabled - indicates if header suprression is enabled for SF. + +Return: STATUS_SUCCESS - If the send was successful. + Other - If an error occured. +*/ + +int PHSTransmit(PMINI_ADAPTER Adapter, + struct sk_buff **pPacket, + USHORT Vcid, + B_UINT16 uiClassifierRuleID, + BOOLEAN bHeaderSuppressionEnabled, + UINT *PacketLen, + UCHAR bEthCSSupport) +{ + + //PHS Sepcific + UINT unPHSPktHdrBytesCopied = 0; + UINT unPhsOldHdrSize = 0; + UINT unPHSNewPktHeaderLen = 0; + /* Pointer to PHS IN Hdr Buffer */ + PUCHAR pucPHSPktHdrInBuf = + Adapter->stPhsTxContextInfo.ucaHdrSupressionInBuf; + /* Pointer to PHS OUT Hdr Buffer */ + PUCHAR pucPHSPktHdrOutBuf = + Adapter->stPhsTxContextInfo.ucaHdrSupressionOutBuf; + UINT usPacketType; + UINT BytesToRemove=0; + BOOLEAN bPHSI = 0; + LONG ulPhsStatus = 0; + UINT numBytesCompressed = 0; + struct sk_buff *newPacket = NULL; + struct sk_buff *Packet = *pPacket; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL, "In PHSTransmit"); + + if(!bEthCSSupport) + BytesToRemove=ETH_HLEN; + /* + Accumulate the header upto the size we support supression + from NDIS packet + */ + + usPacketType=((struct ethhdr *)(Packet->data))->h_proto; + + + pucPHSPktHdrInBuf = Packet->data + BytesToRemove; + //considering data after ethernet header + if((*PacketLen - BytesToRemove) < MAX_PHS_LENGTHS) + { + + unPHSPktHdrBytesCopied = (*PacketLen - BytesToRemove); + } + else + { + unPHSPktHdrBytesCopied = MAX_PHS_LENGTHS; + } + + if( (unPHSPktHdrBytesCopied > 0 ) && + (unPHSPktHdrBytesCopied <= MAX_PHS_LENGTHS)) + { + + + //DumpDataPacketHeader(pucPHSPktHdrInBuf); + + // Step 2 Supress Header using PHS and fill into intermediate ucaPHSPktHdrOutBuf. + // Suppress only if IP Header and PHS Enabled For the Service Flow + if(((usPacketType == ETHERNET_FRAMETYPE_IPV4) || + (usPacketType == ETHERNET_FRAMETYPE_IPV6)) && + (bHeaderSuppressionEnabled)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nTrying to PHS Compress Using Classifier rule 0x%X",uiClassifierRuleID); + + + unPHSNewPktHeaderLen = unPHSPktHdrBytesCopied; + ulPhsStatus = PhsCompress(&Adapter->stBCMPhsContext, + Vcid, + uiClassifierRuleID, + pucPHSPktHdrInBuf, + pucPHSPktHdrOutBuf, + &unPhsOldHdrSize, + &unPHSNewPktHeaderLen); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nPHS Old header Size : %d New Header Size %d\n",unPhsOldHdrSize,unPHSNewPktHeaderLen); + + if(unPHSNewPktHeaderLen == unPhsOldHdrSize) + { + if( ulPhsStatus == STATUS_PHS_COMPRESSED) + bPHSI = *pucPHSPktHdrOutBuf; + ulPhsStatus = STATUS_PHS_NOCOMPRESSION; + } + + if( ulPhsStatus == STATUS_PHS_COMPRESSED) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHS Sending packet Compressed"); + + if(skb_cloned(Packet)) + { + newPacket = skb_copy(Packet, GFP_ATOMIC); + + if(newPacket == NULL) + return STATUS_FAILURE; + + bcm_kfree_skb(Packet); + *pPacket = Packet = newPacket; + pucPHSPktHdrInBuf = Packet->data + BytesToRemove; + } + + numBytesCompressed = unPhsOldHdrSize - (unPHSNewPktHeaderLen+PHSI_LEN); + + OsalMemMove(pucPHSPktHdrInBuf + numBytesCompressed, pucPHSPktHdrOutBuf, unPHSNewPktHeaderLen + PHSI_LEN); + OsalMemMove(Packet->data + numBytesCompressed, Packet->data, BytesToRemove); + skb_pull(Packet, numBytesCompressed); + + return STATUS_SUCCESS; + } + + else + { + //if one byte headroom is not available, increase it through skb_cow + if(!(skb_headroom(Packet) > 0)) + { + if(skb_cow(Packet, 1)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "SKB Cow Failed\n"); + return STATUS_FAILURE; + } + } + skb_push(Packet, 1); + + // CAUTION: The MAC Header is getting corrupted here for IP CS - can be saved by copying 14 Bytes. not needed .... hence corrupting it. + *(Packet->data + BytesToRemove) = bPHSI; + return STATUS_SUCCESS; + } + } + else + { + if(!bHeaderSuppressionEnabled) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nHeader Suppression Disabled For SF: No PHS\n"); + } + + return STATUS_SUCCESS; + } + } + + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"PHSTransmit : Dumping data packet After PHS"); + return STATUS_SUCCESS; +} + +int PHSRecieve(PMINI_ADAPTER Adapter, + USHORT usVcid, + struct sk_buff *packet, + UINT *punPacketLen, + UCHAR *pucEthernetHdr, + UINT bHeaderSuppressionEnabled) +{ + u32 nStandardPktHdrLen = 0; + u32 nTotalsupressedPktHdrBytes = 0; + int ulPhsStatus = 0; + PUCHAR pucInBuff = NULL ; + UINT TotalBytesAdded = 0; + if(!bHeaderSuppressionEnabled) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nPhs Disabled for incoming packet"); + return ulPhsStatus; + } + + pucInBuff = packet->data; + + //Restore PHS suppressed header + nStandardPktHdrLen = packet->len; + ulPhsStatus = PhsDeCompress(&Adapter->stBCMPhsContext, + usVcid, + pucInBuff, + Adapter->ucaPHSPktRestoreBuf, + &nTotalsupressedPktHdrBytes, + &nStandardPktHdrLen); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nSupressed PktHdrLen : 0x%x Restored PktHdrLen : 0x%x", + nTotalsupressedPktHdrBytes,nStandardPktHdrLen); + + if(ulPhsStatus != STATUS_PHS_COMPRESSED) + { + skb_pull(packet, 1); + return STATUS_SUCCESS; + } + else + { + TotalBytesAdded = nStandardPktHdrLen - nTotalsupressedPktHdrBytes - PHSI_LEN; + if(TotalBytesAdded) + { + if(skb_headroom(packet) >= (SKB_RESERVE_ETHERNET_HEADER + TotalBytesAdded)) + skb_push(packet, TotalBytesAdded); + else + { + if(skb_cow(packet, skb_headroom(packet) + TotalBytesAdded)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "cow failed in receive\n"); + return STATUS_FAILURE; + } + + skb_push(packet, TotalBytesAdded); + } + } + + OsalMemMove(packet->data, Adapter->ucaPHSPktRestoreBuf, nStandardPktHdrLen); + } + + return STATUS_SUCCESS; +} + +void DumpDataPacketHeader(PUCHAR pPkt) +{ + struct iphdr *iphd = (struct iphdr*)pPkt; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Phs Send/Recieve : IP Packet Hdr \n"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"TOS : %x \n",iphd->tos); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Src IP : %x \n",iphd->saddr); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Dest IP : %x \n \n",iphd->daddr); + +} + +void DumpFullPacket(UCHAR *pBuf,UINT nPktLen) +{ + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"Dumping Data Packet"); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,pBuf,nPktLen); +} + +//----------------------------------------------------------------------------- +// Procedure: phs_init +// +// Description: This routine is responsible for allocating memory for classifier and +// PHS rules. +// +// Arguments: +// pPhsdeviceExtension - ptr to Device extension containing PHS Classifier rules and PHS Rules , RX, TX buffer etc +// +// Returns: +// TRUE(1) -If allocation of memory was success full. +// FALSE -If allocation of memory fails. +//----------------------------------------------------------------------------- +int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter) +{ + int i; + S_SERVICEFLOW_TABLE *pstServiceFlowTable; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nPHS:phs_init function "); + + if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable) + return -EINVAL; + + pPhsdeviceExtension->pstServiceFlowPhsRulesTable = + (S_SERVICEFLOW_TABLE*)OsalMemAlloc(sizeof(S_SERVICEFLOW_TABLE), + PHS_MEM_TAG); + + if(pPhsdeviceExtension->pstServiceFlowPhsRulesTable) + { + OsalZeroMemory(pPhsdeviceExtension->pstServiceFlowPhsRulesTable, + sizeof(S_SERVICEFLOW_TABLE)); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation ServiceFlowPhsRulesTable failed"); + return -ENOMEM; + } + + pstServiceFlowTable = pPhsdeviceExtension->pstServiceFlowPhsRulesTable; + for(i=0;istSFList[i]; + sServiceFlow.pstClassifierTable = (S_CLASSIFIER_TABLE*)OsalMemAlloc( + sizeof(S_CLASSIFIER_TABLE), PHS_MEM_TAG); + if(sServiceFlow.pstClassifierTable) + { + OsalZeroMemory(sServiceFlow.pstClassifierTable,sizeof(S_CLASSIFIER_TABLE)); + pstServiceFlowTable->stSFList[i].pstClassifierTable = sServiceFlow.pstClassifierTable; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed"); + free_phs_serviceflow_rules(pPhsdeviceExtension-> + pstServiceFlowPhsRulesTable); + pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL; + return -ENOMEM; + } + } + + + pPhsdeviceExtension->CompressedTxBuffer = + OsalMemAlloc(PHS_BUFFER_SIZE,PHS_MEM_TAG); + + if(pPhsdeviceExtension->CompressedTxBuffer == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed"); + free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable); + pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL; + return -ENOMEM; + } + + pPhsdeviceExtension->UnCompressedRxBuffer = + OsalMemAlloc(PHS_BUFFER_SIZE,PHS_MEM_TAG); + if(pPhsdeviceExtension->UnCompressedRxBuffer == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAllocation failed"); + OsalMemFree(pPhsdeviceExtension->CompressedTxBuffer,PHS_BUFFER_SIZE); + free_phs_serviceflow_rules(pPhsdeviceExtension->pstServiceFlowPhsRulesTable); + pPhsdeviceExtension->pstServiceFlowPhsRulesTable = NULL; + return -ENOMEM; + } + + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n phs_init Successfull"); + return STATUS_SUCCESS; +} + + +int PhsCleanup(IN PPHS_DEVICE_EXTENSION pPHSDeviceExt) +{ + if(pPHSDeviceExt->pstServiceFlowPhsRulesTable) + { + free_phs_serviceflow_rules(pPHSDeviceExt->pstServiceFlowPhsRulesTable); + pPHSDeviceExt->pstServiceFlowPhsRulesTable = NULL; + } + + if(pPHSDeviceExt->CompressedTxBuffer) + { + OsalMemFree(pPHSDeviceExt->CompressedTxBuffer,PHS_BUFFER_SIZE); + pPHSDeviceExt->CompressedTxBuffer = NULL; + } + if(pPHSDeviceExt->UnCompressedRxBuffer) + { + OsalMemFree(pPHSDeviceExt->UnCompressedRxBuffer,PHS_BUFFER_SIZE); + pPHSDeviceExt->UnCompressedRxBuffer = NULL; + } + + return 0; +} + + + +//PHS functions +/*++ +PhsUpdateClassifierRule + +Routine Description: + Exported function to add or modify a PHS Rule. + +Arguments: + IN void* pvContext - PHS Driver Specific Context + IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies + IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies. + IN S_PHS_RULE *psPhsRule - The PHS Rule strcuture to be added to the PHS Rule table. + +Return Value: + + 0 if successful, + >0 Error. + +--*/ +ULONG PhsUpdateClassifierRule(IN void* pvContext, + IN B_UINT16 uiVcid , + IN B_UINT16 uiClsId , + IN S_PHS_RULE *psPhsRule, + IN B_UINT8 u8AssociatedPHSI) +{ + ULONG lStatus =0; + UINT nSFIndex =0 ; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + + + PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS With Corr2 Changes \n"); + + if(pDeviceExtension == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Invalid Device Extension\n"); + return ERR_PHS_INVALID_DEVICE_EXETENSION; + } + + + if(u8AssociatedPHSI == 0) + { + return ERR_PHS_INVALID_PHS_RULE; + } + + /* Retrieve the SFID Entry Index for requested Service Flow */ + + nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, + uiVcid,&pstServiceFlowEntry); + + if(nSFIndex == PHS_INVALID_TABLE_INDEX) + { + /* This is a new SF. Create a mapping entry for this */ + lStatus = CreateSFToClassifierRuleMapping(uiVcid, uiClsId, + pDeviceExtension->pstServiceFlowPhsRulesTable, psPhsRule, u8AssociatedPHSI); + return lStatus; + } + + /* SF already Exists Add PHS Rule to existing SF */ + lStatus = CreateClassiferToPHSRuleMapping(uiVcid, uiClsId, + pstServiceFlowEntry, psPhsRule, u8AssociatedPHSI); + + return lStatus; +} + +/*++ +PhsDeletePHSRule + +Routine Description: + Deletes the specified phs Rule within Vcid + +Arguments: + IN void* pvContext - PHS Driver Specific Context + IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies + IN B_UINT8 u8PHSI - the PHS Index identifying PHS rule to be deleted. + +Return Value: + + 0 if successful, + >0 Error. + +--*/ + +ULONG PhsDeletePHSRule(IN void* pvContext,IN B_UINT16 uiVcid,IN B_UINT8 u8PHSI) +{ + ULONG lStatus =0; + UINT nSFIndex =0, nClsidIndex =0 ; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + + PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "======>\n"); + + if(pDeviceExtension) + { + + //Retrieve the SFID Entry Index for requested Service Flow + nSFIndex = GetServiceFlowEntry(pDeviceExtension + ->pstServiceFlowPhsRulesTable,uiVcid,&pstServiceFlowEntry); + + if(nSFIndex == PHS_INVALID_TABLE_INDEX) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n"); + return ERR_SF_MATCH_FAIL; + } + + pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable; + if(pstClassifierRulesTable) + { + for(nClsidIndex=0;nClsidIndexstActivePhsRulesList[nClsidIndex].bUsed && pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule) + { + if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] + .pstPhsRule->u8PHSI == u8PHSI) + { + if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule + ->u8RefCnt) + pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex].pstPhsRule + ->u8RefCnt--; + if(0 == pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] + .pstPhsRule->u8RefCnt) + OsalMemFree(pstClassifierRulesTable + ->stActivePhsRulesList[nClsidIndex].pstPhsRule, + sizeof(S_PHS_RULE)); + OsalZeroMemory(&pstClassifierRulesTable + ->stActivePhsRulesList[nClsidIndex], + sizeof(S_CLASSIFIER_ENTRY)); + } + } + } + } + + } + return lStatus; +} + +/*++ +PhsDeleteClassifierRule + +Routine Description: + Exported function to Delete a PHS Rule for the SFID,CLSID Pair. + +Arguments: + IN void* pvContext - PHS Driver Specific Context + IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rule applies + IN B_UINT16 uiClsId - The Classifier ID within the Service Flow for which the PHS rule applies. + +Return Value: + + 0 if successful, + >0 Error. + +--*/ +ULONG PhsDeleteClassifierRule(IN void* pvContext,IN B_UINT16 uiVcid ,IN B_UINT16 uiClsId) +{ + ULONG lStatus =0; + UINT nSFIndex =0, nClsidIndex =0 ; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; + + if(pDeviceExtension) + { + //Retrieve the SFID Entry Index for requested Service Flow + nSFIndex = GetServiceFlowEntry(pDeviceExtension + ->pstServiceFlowPhsRulesTable, uiVcid, &pstServiceFlowEntry); + if(nSFIndex == PHS_INVALID_TABLE_INDEX) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"SFID Match Failed\n"); + return ERR_SF_MATCH_FAIL; + } + + nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, + uiClsId, eActiveClassifierRuleContext, &pstClassifierEntry); + if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) + { + if(pstClassifierEntry->pstPhsRule) + { + if(pstClassifierEntry->pstPhsRule->u8RefCnt) + pstClassifierEntry->pstPhsRule->u8RefCnt--; + if(0==pstClassifierEntry->pstPhsRule->u8RefCnt) + OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE)); + + } + OsalZeroMemory(pstClassifierEntry,sizeof(S_CLASSIFIER_ENTRY)); + } + + nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, + uiClsId,eOldClassifierRuleContext,&pstClassifierEntry); + + if((nClsidIndex != PHS_INVALID_TABLE_INDEX) && (!pstClassifierEntry->bUnclassifiedPHSRule)) + { + if(pstClassifierEntry->pstPhsRule) + //Delete the classifier entry + OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE)); + OsalZeroMemory(pstClassifierEntry,sizeof(S_CLASSIFIER_ENTRY)); + } + } + return lStatus; +} + +/*++ +PhsDeleteSFRules + +Routine Description: + Exported function to Delete a all PHS Rules for the SFID. + +Arguments: + IN void* pvContext - PHS Driver Specific Context + IN B_UINT16 uiVcid - The Service Flow ID for which the PHS rules need to be deleted + +Return Value: + + 0 if successful, + >0 Error. + +--*/ +ULONG PhsDeleteSFRules(IN void* pvContext,IN B_UINT16 uiVcid) +{ + + ULONG lStatus =0; + UINT nSFIndex =0, nClsidIndex =0 ; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + S_CLASSIFIER_TABLE *pstClassifierRulesTable = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"====> \n"); + + if(pDeviceExtension) + { + //Retrieve the SFID Entry Index for requested Service Flow + nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, + uiVcid,&pstServiceFlowEntry); + if(nSFIndex == PHS_INVALID_TABLE_INDEX) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "SFID Match Failed\n"); + return ERR_SF_MATCH_FAIL; + } + + pstClassifierRulesTable=pstServiceFlowEntry->pstClassifierTable; + if(pstClassifierRulesTable) + { + for(nClsidIndex=0;nClsidIndexstActivePhsRulesList[nClsidIndex].pstPhsRule) + { + if(pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] + .pstPhsRule->u8RefCnt) + pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] + .pstPhsRule->u8RefCnt--; + if(0==pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] + .pstPhsRule->u8RefCnt) + OsalMemFree(pstClassifierRulesTable + ->stActivePhsRulesList[nClsidIndex].pstPhsRule, + sizeof(S_PHS_RULE)); + pstClassifierRulesTable->stActivePhsRulesList[nClsidIndex] + .pstPhsRule = NULL; + } + OsalZeroMemory(&pstClassifierRulesTable + ->stActivePhsRulesList[nClsidIndex],sizeof(S_CLASSIFIER_ENTRY)); + if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex].pstPhsRule) + { + if(pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] + .pstPhsRule->u8RefCnt) + pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] + .pstPhsRule->u8RefCnt--; + if(0 == pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] + .pstPhsRule->u8RefCnt) + OsalMemFree(pstClassifierRulesTable + ->stOldPhsRulesList[nClsidIndex].pstPhsRule, + sizeof(S_PHS_RULE)); + pstClassifierRulesTable->stOldPhsRulesList[nClsidIndex] + .pstPhsRule = NULL; + } + OsalZeroMemory(&pstClassifierRulesTable + ->stOldPhsRulesList[nClsidIndex], + sizeof(S_CLASSIFIER_ENTRY)); + } + } + pstServiceFlowEntry->bUsed = FALSE; + pstServiceFlowEntry->uiVcid = 0; + + } + + return lStatus; +} + + +/*++ +PhsCompress + +Routine Description: + Exported function to compress the data using PHS. + +Arguments: + IN void* pvContext - PHS Driver Specific Context. + IN B_UINT16 uiVcid - The Service Flow ID to which current packet header compression applies. + IN UINT uiClsId - The Classifier ID to which current packet header compression applies. + IN void *pvInputBuffer - The Input buffer containg packet header data + IN void *pvOutputBuffer - The output buffer returned by this function after PHS + IN UINT *pOldHeaderSize - The actual size of the header before PHS + IN UINT *pNewHeaderSize - The new size of the header after applying PHS + +Return Value: + + 0 if successful, + >0 Error. + +--*/ +ULONG PhsCompress(IN void* pvContext, + IN B_UINT16 uiVcid, + IN B_UINT16 uiClsId, + IN void *pvInputBuffer, + OUT void *pvOutputBuffer, + OUT UINT *pOldHeaderSize, + OUT UINT *pNewHeaderSize ) +{ + UINT nSFIndex =0, nClsidIndex =0 ; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; + S_PHS_RULE *pstPhsRule = NULL; + ULONG lStatus =0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + + + PPHS_DEVICE_EXTENSION pDeviceExtension= (PPHS_DEVICE_EXTENSION)pvContext; + + + if(pDeviceExtension == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Invalid Device Extension\n"); + lStatus = STATUS_PHS_NOCOMPRESSION ; + return lStatus; + + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"Suppressing header \n"); + + + //Retrieve the SFID Entry Index for requested Service Flow + nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, + uiVcid,&pstServiceFlowEntry); + if(nSFIndex == PHS_INVALID_TABLE_INDEX) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"SFID Match Failed\n"); + lStatus = STATUS_PHS_NOCOMPRESSION ; + return lStatus; + } + + nClsidIndex = GetClassifierEntry(pstServiceFlowEntry->pstClassifierTable, + uiClsId,eActiveClassifierRuleContext,&pstClassifierEntry); + + if(nClsidIndex == PHS_INVALID_TABLE_INDEX) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"No PHS Rule Defined For Classifier\n"); + lStatus = STATUS_PHS_NOCOMPRESSION ; + return lStatus; + } + + + //get rule from SF id,Cls ID pair and proceed + pstPhsRule = pstClassifierEntry->pstPhsRule; + + if(!ValidatePHSRuleComplete(pstPhsRule)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"PHS Rule Defined For Classifier But Not Complete\n"); + lStatus = STATUS_PHS_NOCOMPRESSION ; + return lStatus; + } + + //Compress Packet + lStatus = phs_compress(pstPhsRule,(PUCHAR)pvInputBuffer, + (PUCHAR)pvOutputBuffer, pOldHeaderSize,pNewHeaderSize); + + if(lStatus == STATUS_PHS_COMPRESSED) + { + pstPhsRule->PHSModifiedBytes += *pOldHeaderSize - *pNewHeaderSize - 1; + pstPhsRule->PHSModifiedNumPackets++; + } + else + pstPhsRule->PHSErrorNumPackets++; + + return lStatus; +} + +/*++ +PhsDeCompress + +Routine Description: + Exported function to restore the packet header in Rx path. + +Arguments: + IN void* pvContext - PHS Driver Specific Context. + IN B_UINT16 uiVcid - The Service Flow ID to which current packet header restoration applies. + IN void *pvInputBuffer - The Input buffer containg suppressed packet header data + OUT void *pvOutputBuffer - The output buffer returned by this function after restoration + OUT UINT *pHeaderSize - The packet header size after restoration is returned in this parameter. + +Return Value: + + 0 if successful, + >0 Error. + +--*/ +ULONG PhsDeCompress(IN void* pvContext, + IN B_UINT16 uiVcid, + IN void *pvInputBuffer, + OUT void *pvOutputBuffer, + OUT UINT *pInHeaderSize, + OUT UINT *pOutHeaderSize ) +{ + UINT nSFIndex =0, nPhsRuleIndex =0 ; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + S_PHS_RULE *pstPhsRule = NULL; + UINT phsi; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + PPHS_DEVICE_EXTENSION pDeviceExtension= + (PPHS_DEVICE_EXTENSION)pvContext; + + *pInHeaderSize = 0; + + if(pDeviceExtension == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Invalid Device Extension\n"); + return ERR_PHS_INVALID_DEVICE_EXETENSION; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"Restoring header \n"); + + phsi = *((unsigned char *)(pvInputBuffer)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"PHSI To Be Used For restore : %x \n",phsi); + if(phsi == UNCOMPRESSED_PACKET ) + { + return STATUS_PHS_NOCOMPRESSION; + } + + //Retrieve the SFID Entry Index for requested Service Flow + nSFIndex = GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, + uiVcid,&pstServiceFlowEntry); + if(nSFIndex == PHS_INVALID_TABLE_INDEX) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"SFID Match Failed During Lookup\n"); + return ERR_SF_MATCH_FAIL; + } + + nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable,phsi, + eActiveClassifierRuleContext,&pstPhsRule); + if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) + { + //Phs Rule does not exist in active rules table. Lets try in the old rules table. + nPhsRuleIndex = GetPhsRuleEntry(pstServiceFlowEntry->pstClassifierTable, + phsi,eOldClassifierRuleContext,&pstPhsRule); + if(nPhsRuleIndex == PHS_INVALID_TABLE_INDEX) + { + return ERR_PHSRULE_MATCH_FAIL; + } + + } + + *pInHeaderSize = phs_decompress((PUCHAR)pvInputBuffer, + (PUCHAR)pvOutputBuffer,pstPhsRule,pOutHeaderSize); + + pstPhsRule->PHSModifiedBytes += *pOutHeaderSize - *pInHeaderSize - 1; + + pstPhsRule->PHSModifiedNumPackets++; + return STATUS_PHS_COMPRESSED; +} + + +//----------------------------------------------------------------------------- +// Procedure: free_phs_serviceflow_rules +// +// Description: This routine is responsible for freeing memory allocated for PHS rules. +// +// Arguments: +// rules - ptr to S_SERVICEFLOW_TABLE structure. +// +// Returns: +// Does not return any value. +//----------------------------------------------------------------------------- + +void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable) +{ + int i,j; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "=======>\n"); + if(psServiceFlowRulesTable) + { + for(i=0;istSFList[i]; + S_CLASSIFIER_TABLE *pstClassifierRulesTable = + stServiceFlowEntry.pstClassifierTable; + + if(pstClassifierRulesTable) + { + for(j=0;jstActivePhsRulesList[j].pstPhsRule) + { + if(pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule + ->u8RefCnt) + pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule + ->u8RefCnt--; + if(0==pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule + ->u8RefCnt) + OsalMemFree(pstClassifierRulesTable->stActivePhsRulesList[j]. + pstPhsRule, sizeof(S_PHS_RULE)); + pstClassifierRulesTable->stActivePhsRulesList[j].pstPhsRule = NULL; + } + if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule) + { + if(pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule + ->u8RefCnt) + pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule + ->u8RefCnt--; + if(0==pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule + ->u8RefCnt) + OsalMemFree(pstClassifierRulesTable->stOldPhsRulesList[j] + .pstPhsRule,sizeof(S_PHS_RULE)); + pstClassifierRulesTable->stOldPhsRulesList[j].pstPhsRule = NULL; + } + } + OsalMemFree(pstClassifierRulesTable,sizeof(S_CLASSIFIER_TABLE)); + stServiceFlowEntry.pstClassifierTable = pstClassifierRulesTable = NULL; + } + } + } + + OsalMemFree(psServiceFlowRulesTable,sizeof(S_SERVICEFLOW_TABLE)); + psServiceFlowRulesTable = NULL; +} + + + +BOOLEAN ValidatePHSRuleComplete(IN S_PHS_RULE *psPhsRule) +{ + if(psPhsRule) + { + if(!psPhsRule->u8PHSI) + { + // PHSI is not valid + return FALSE; + } + + if(!psPhsRule->u8PHSS) + { + //PHSS Is Undefined + return FALSE; + } + + //Check if PHSF is defines for the PHS Rule + if(!psPhsRule->u8PHSFLength) // If any part of PHSF is valid then Rule contains valid PHSF + { + return FALSE; + } + return TRUE; + } + else + { + return FALSE; + } +} + +UINT GetServiceFlowEntry(IN S_SERVICEFLOW_TABLE *psServiceFlowTable, + IN B_UINT16 uiVcid,S_SERVICEFLOW_ENTRY **ppstServiceFlowEntry) +{ + int i; + for(i=0;istSFList[i].bUsed) + { + if(psServiceFlowTable->stSFList[i].uiVcid == uiVcid) + { + *ppstServiceFlowEntry = &psServiceFlowTable->stSFList[i]; + return i; + } + } + } + + *ppstServiceFlowEntry = NULL; + return PHS_INVALID_TABLE_INDEX; +} + + +UINT GetClassifierEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable, + IN B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, + OUT S_CLASSIFIER_ENTRY **ppstClassifierEntry) +{ + int i; + S_CLASSIFIER_ENTRY *psClassifierRules = NULL; + for(i=0;istActivePhsRulesList[i]; + } + else + { + psClassifierRules = &pstClassifierTable->stOldPhsRulesList[i]; + } + + if(psClassifierRules->bUsed) + { + if(psClassifierRules->uiClassifierRuleId == uiClsid) + { + *ppstClassifierEntry = psClassifierRules; + return i; + } + } + + } + + *ppstClassifierEntry = NULL; + return PHS_INVALID_TABLE_INDEX; +} + +UINT GetPhsRuleEntry(IN S_CLASSIFIER_TABLE *pstClassifierTable, + IN B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, + OUT S_PHS_RULE **ppstPhsRule) +{ + int i; + S_CLASSIFIER_ENTRY *pstClassifierRule = NULL; + for(i=0;istActivePhsRulesList[i]; + } + else + { + pstClassifierRule = &pstClassifierTable->stOldPhsRulesList[i]; + } + if(pstClassifierRule->bUsed) + { + if(pstClassifierRule->u8PHSI == uiPHSI) + { + *ppstPhsRule = pstClassifierRule->pstPhsRule; + return i; + } + } + + } + + *ppstPhsRule = NULL; + return PHS_INVALID_TABLE_INDEX; +} + +UINT CreateSFToClassifierRuleMapping(IN B_UINT16 uiVcid,IN B_UINT16 uiClsId, + IN S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule, + B_UINT8 u8AssociatedPHSI) +{ + + S_CLASSIFIER_TABLE *psaClassifiertable = NULL; + UINT uiStatus = 0; + int iSfIndex; + BOOLEAN bFreeEntryFound =FALSE; + //Check for a free entry in SFID table + for(iSfIndex=0;iSfIndex < MAX_SERVICEFLOWS;iSfIndex++) + { + if(!psServiceFlowTable->stSFList[iSfIndex].bUsed) + { + bFreeEntryFound = TRUE; + break; + } + } + + if(!bFreeEntryFound) + return ERR_SFTABLE_FULL; + + + psaClassifiertable = psServiceFlowTable->stSFList[iSfIndex].pstClassifierTable; + uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable,psPhsRule, + eActiveClassifierRuleContext,u8AssociatedPHSI); + if(uiStatus == PHS_SUCCESS) + { + //Add entry at free index to the SF + psServiceFlowTable->stSFList[iSfIndex].bUsed = TRUE; + psServiceFlowTable->stSFList[iSfIndex].uiVcid = uiVcid; + } + + return uiStatus; + +} + +UINT CreateClassiferToPHSRuleMapping(IN B_UINT16 uiVcid, + IN B_UINT16 uiClsId,IN S_SERVICEFLOW_ENTRY *pstServiceFlowEntry, + S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI) +{ + S_CLASSIFIER_ENTRY *pstClassifierEntry = NULL; + UINT uiStatus =PHS_SUCCESS; + UINT nClassifierIndex = 0; + S_CLASSIFIER_TABLE *psaClassifiertable = NULL; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + psaClassifiertable = pstServiceFlowEntry->pstClassifierTable; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "==>"); + + /* Check if the supplied Classifier already exists */ + nClassifierIndex =GetClassifierEntry( + pstServiceFlowEntry->pstClassifierTable,uiClsId, + eActiveClassifierRuleContext,&pstClassifierEntry); + if(nClassifierIndex == PHS_INVALID_TABLE_INDEX) + { + /* + The Classifier doesn't exist. So its a new classifier being added. + Add new entry to associate PHS Rule to the Classifier + */ + + uiStatus = CreateClassifierPHSRule(uiClsId,psaClassifiertable, + psPhsRule,eActiveClassifierRuleContext,u8AssociatedPHSI); + return uiStatus; + } + + /* + The Classifier exists.The PHS Rule for this classifier + is being modified + */ + if(pstClassifierEntry->u8PHSI == psPhsRule->u8PHSI) + { + if(pstClassifierEntry->pstPhsRule == NULL) + return ERR_PHS_INVALID_PHS_RULE; + + /* + This rule already exists if any fields are changed for this PHS + rule update them. + */ + /* If any part of PHSF is valid then we update PHSF */ + if(psPhsRule->u8PHSFLength) + { + //update PHSF + OsalMemMove(pstClassifierEntry->pstPhsRule->u8PHSF, + psPhsRule->u8PHSF , MAX_PHS_LENGTHS); + } + if(psPhsRule->u8PHSFLength) + { + //update PHSFLen + pstClassifierEntry->pstPhsRule->u8PHSFLength = + psPhsRule->u8PHSFLength; + } + if(psPhsRule->u8PHSMLength) + { + //update PHSM + OsalMemMove(pstClassifierEntry->pstPhsRule->u8PHSM, + psPhsRule->u8PHSM, MAX_PHS_LENGTHS); + } + if(psPhsRule->u8PHSMLength) + { + //update PHSM Len + pstClassifierEntry->pstPhsRule->u8PHSMLength = + psPhsRule->u8PHSMLength; + } + if(psPhsRule->u8PHSS) + { + //update PHSS + pstClassifierEntry->pstPhsRule->u8PHSS = psPhsRule->u8PHSS; + } + + //update PHSV + pstClassifierEntry->pstPhsRule->u8PHSV = psPhsRule->u8PHSV; + + } + else + { + /* + A new rule is being set for this classifier. + */ + uiStatus=UpdateClassifierPHSRule( uiClsId, pstClassifierEntry, + psaClassifiertable, psPhsRule, u8AssociatedPHSI); + } + + + + return uiStatus; +} + +UINT CreateClassifierPHSRule(IN B_UINT16 uiClsId, + S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule, + E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI) +{ + UINT iClassifierIndex = 0; + BOOLEAN bFreeEntryFound = FALSE; + S_CLASSIFIER_ENTRY *psClassifierRules = NULL; + UINT nStatus = PHS_SUCCESS; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL,"Inside CreateClassifierPHSRule"); + if(psaClassifiertable == NULL) + { + return ERR_INVALID_CLASSIFIERTABLE_FOR_SF; + } + + if(eClsContext == eOldClassifierRuleContext) + { + /* If An Old Entry for this classifier ID already exists in the + old rules table replace it. */ + + iClassifierIndex = + GetClassifierEntry(psaClassifiertable, uiClsId, + eClsContext,&psClassifierRules); + if(iClassifierIndex != PHS_INVALID_TABLE_INDEX) + { + /* + The Classifier already exists in the old rules table + Lets replace the old classifier with the new one. + */ + bFreeEntryFound = TRUE; + } + } + + if(!bFreeEntryFound) + { + /* + Continue to search for a free location to add the rule + */ + for(iClassifierIndex = 0; iClassifierIndex < + MAX_PHSRULE_PER_SF; iClassifierIndex++) + { + if(eClsContext == eActiveClassifierRuleContext) + { + psClassifierRules = + &psaClassifiertable->stActivePhsRulesList[iClassifierIndex]; + } + else + { + psClassifierRules = + &psaClassifiertable->stOldPhsRulesList[iClassifierIndex]; + } + + if(!psClassifierRules->bUsed) + { + bFreeEntryFound = TRUE; + break; + } + } + } + + if(!bFreeEntryFound) + { + if(eClsContext == eActiveClassifierRuleContext) + { + return ERR_CLSASSIFIER_TABLE_FULL; + } + else + { + //Lets replace the oldest rule if we are looking in old Rule table + if(psaClassifiertable->uiOldestPhsRuleIndex >= + MAX_PHSRULE_PER_SF) + { + psaClassifiertable->uiOldestPhsRuleIndex =0; + } + + iClassifierIndex = psaClassifiertable->uiOldestPhsRuleIndex; + psClassifierRules = + &psaClassifiertable->stOldPhsRulesList[iClassifierIndex]; + + (psaClassifiertable->uiOldestPhsRuleIndex)++; + } + } + + if(eClsContext == eOldClassifierRuleContext) + { + if(psClassifierRules->pstPhsRule == NULL) + { + psClassifierRules->pstPhsRule = (S_PHS_RULE*)OsalMemAlloc + (sizeof(S_PHS_RULE),PHS_MEM_TAG); + + if(NULL == psClassifierRules->pstPhsRule) + return ERR_PHSRULE_MEMALLOC_FAIL; + } + + psClassifierRules->bUsed = TRUE; + psClassifierRules->uiClassifierRuleId = uiClsId; + psClassifierRules->u8PHSI = psPhsRule->u8PHSI; + psClassifierRules->bUnclassifiedPHSRule = psPhsRule->bUnclassifiedPHSRule; + + /* Update The PHS rule */ + OsalMemMove(psClassifierRules->pstPhsRule, + psPhsRule, sizeof(S_PHS_RULE)); + } + else + { + nStatus = UpdateClassifierPHSRule(uiClsId,psClassifierRules, + psaClassifiertable,psPhsRule,u8AssociatedPHSI); + } + return nStatus; +} + + +UINT UpdateClassifierPHSRule(IN B_UINT16 uiClsId, + IN S_CLASSIFIER_ENTRY *pstClassifierEntry, + S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule, + B_UINT8 u8AssociatedPHSI) +{ + S_PHS_RULE *pstAddPhsRule = NULL; + UINT nPhsRuleIndex = 0; + BOOLEAN bPHSRuleOrphaned = FALSE; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + psPhsRule->u8RefCnt =0; + + /* Step 1 Deref Any Exisiting PHS Rule in this classifier Entry*/ + bPHSRuleOrphaned = DerefPhsRule( uiClsId, psaClassifiertable, + pstClassifierEntry->pstPhsRule); + + //Step 2 Search if there is a PHS Rule with u8AssociatedPHSI in Classifier table for this SF + nPhsRuleIndex =GetPhsRuleEntry(psaClassifiertable,u8AssociatedPHSI, + eActiveClassifierRuleContext, &pstAddPhsRule); + if(PHS_INVALID_TABLE_INDEX == nPhsRuleIndex) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nAdding New PHSRuleEntry For Classifier"); + + if(psPhsRule->u8PHSI == 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nError PHSI is Zero\n"); + return ERR_PHS_INVALID_PHS_RULE; + } + //Step 2.a PHS Rule Does Not Exist .Create New PHS Rule for uiClsId + if(FALSE == bPHSRuleOrphaned) + { + pstClassifierEntry->pstPhsRule = (S_PHS_RULE*)OsalMemAlloc(sizeof(S_PHS_RULE),PHS_MEM_TAG); + if(NULL == pstClassifierEntry->pstPhsRule) + { + return ERR_PHSRULE_MEMALLOC_FAIL; + } + } + OsalMemMove(pstClassifierEntry->pstPhsRule, psPhsRule, sizeof(S_PHS_RULE)); + + } + else + { + //Step 2.b PHS Rule Exists Tie uiClsId with the existing PHS Rule + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\nTying Classifier to Existing PHS Rule"); + if(bPHSRuleOrphaned) + { + if(pstClassifierEntry->pstPhsRule) + { + //Just Free the PHS Rule as Ref Count is Zero + OsalMemFree(pstClassifierEntry->pstPhsRule,sizeof(S_PHS_RULE)); + pstClassifierEntry->pstPhsRule = NULL; + + } + + } + pstClassifierEntry->pstPhsRule = pstAddPhsRule; + + } + pstClassifierEntry->bUsed = TRUE; + pstClassifierEntry->u8PHSI = pstClassifierEntry->pstPhsRule->u8PHSI; + pstClassifierEntry->uiClassifierRuleId = uiClsId; + pstClassifierEntry->pstPhsRule->u8RefCnt++; + pstClassifierEntry->bUnclassifiedPHSRule = pstClassifierEntry->pstPhsRule->bUnclassifiedPHSRule; + + return PHS_SUCCESS; + +} + +BOOLEAN DerefPhsRule(IN B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule) +{ + if(pstPhsRule==NULL) + return FALSE; + if(pstPhsRule->u8RefCnt) + pstPhsRule->u8RefCnt--; + if(0==pstPhsRule->u8RefCnt) + { + /*if(pstPhsRule->u8PHSI) + //Store the currently active rule into the old rules list + CreateClassifierPHSRule(uiClsId,psaClassifiertable,pstPhsRule,eOldClassifierRuleContext,pstPhsRule->u8PHSI);*/ + return TRUE; + } + else + { + return FALSE; + } +} + +void DumpBuffer(PVOID BuffVAddress, int xferSize) +{ + int i; + int iPrintLength; + PUCHAR temp=(PUCHAR)BuffVAddress; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + iPrintLength=(xferSize<32?xferSize:32); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n"); + + for (i=0;i < iPrintLength;i++) { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "%x|",temp[i]); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_DISPATCH, DBG_LVL_ALL, "\n"); +} + + +void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension) +{ + int i,j,k,l; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n Dumping PHS Rules : \n"); + for(i=0;ipstServiceFlowPhsRulesTable->stSFList[i]; + if(stServFlowEntry.bUsed) + { + for(j=0;jstActivePhsRulesList[j]; + if(stClsEntry.bUsed) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Active PHS Rule : \n"); + } + else + { + stClsEntry = stServFlowEntry.pstClassifierTable->stOldPhsRulesList[j]; + if(stClsEntry.bUsed) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n Old PHS Rule : \n"); + } + if(stClsEntry.bUsed) + { + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n VCID : %#X",stServFlowEntry.uiVcid); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n ClassifierID : %#X",stClsEntry.uiClassifierRuleId); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSRuleID : %#X",stClsEntry.u8PHSI); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n****************PHS Rule********************\n"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSI : %#X",stClsEntry.pstPhsRule->u8PHSI); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSFLength : %#X ",stClsEntry.pstPhsRule->u8PHSFLength); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSF : "); + for(k=0;ku8PHSFLength;k++) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSF[k]); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSMLength : %#X",stClsEntry.pstPhsRule->u8PHSMLength); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSM :"); + for(k=0;ku8PHSMLength;k++) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "%#X ",stClsEntry.pstPhsRule->u8PHSM[k]); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSS : %#X ",stClsEntry.pstPhsRule->u8PHSS); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, (DBG_LVL_ALL|DBG_NO_FUNC_PRINT), "\n PHSV : %#X",stClsEntry.pstPhsRule->u8PHSV); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "\n********************************************\n"); + } + } + } + } + } +} + + +//----------------------------------------------------------------------------- +// Procedure: phs_decompress +// +// Description: This routine restores the static fields within the packet. +// +// Arguments: +// in_buf - ptr to incoming packet buffer. +// out_buf - ptr to output buffer where the suppressed header is copied. +// decomp_phs_rules - ptr to PHS rule. +// header_size - ptr to field which holds the phss or phsf_length. +// +// Returns: +// size -The number of bytes of dynamic fields present with in the incoming packet +// header. +// 0 -If PHS rule is NULL.If PHSI is 0 indicateing packet as uncompressed. +//----------------------------------------------------------------------------- + +int phs_decompress(unsigned char *in_buf,unsigned char *out_buf, + S_PHS_RULE *decomp_phs_rules,UINT *header_size) +{ + int phss,size=0; + S_PHS_RULE *tmp_memb; + int bit,i=0; + unsigned char *phsf,*phsm; + int in_buf_len = *header_size-1; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + in_buf++; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"====>\n"); + *header_size = 0; + + if((decomp_phs_rules == NULL )) + return 0; + + + tmp_memb = decomp_phs_rules; + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI 1 %d",phsi)); + //*header_size = tmp_memb->u8PHSFLength; + phss = tmp_memb->u8PHSS; + phsf = tmp_memb->u8PHSF; + phsm = tmp_memb->u8PHSM; + + if(phss > MAX_PHS_LENGTHS) + phss = MAX_PHS_LENGTHS; + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phs_decompress PHSI %d phss %d index %d",phsi,phss,index)); + while((phss > 0) && (size < in_buf_len)) + { + bit = ((*phsm << i)& SUPPRESS); + + if(bit == SUPPRESS) + { + *out_buf = *phsf; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss %d phsf %d ouput %d", + phss,*phsf,*out_buf); + } + else + { + *out_buf = *in_buf; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_RECIEVE,DBG_LVL_ALL,"\nDECOMP:In phss %d input %d ouput %d", + phss,*in_buf,*out_buf); + in_buf++; + size++; + } + out_buf++; + phsf++; + phss--; + i++; + *header_size=*header_size + 1; + + if(i > MAX_NO_BIT) + { + i=0; + phsm++; + } + } + return size; +} + + + + +//----------------------------------------------------------------------------- +// Procedure: phs_compress +// +// Description: This routine suppresses the static fields within the packet.Before +// that it will verify the fields to be suppressed with the corresponding fields in the +// phsf. For verification it checks the phsv field of PHS rule. If set and verification +// succeeds it suppresses the field.If any one static field is found different none of +// the static fields are suppressed then the packet is sent as uncompressed packet with +// phsi=0. +// +// Arguments: +// phs_rule - ptr to PHS rule. +// in_buf - ptr to incoming packet buffer. +// out_buf - ptr to output buffer where the suppressed header is copied. +// header_size - ptr to field which holds the phss. +// +// Returns: +// size-The number of bytes copied into the output buffer i.e dynamic fields +// 0 -If PHS rule is NULL.If PHSV field is not set.If the verification fails. +//----------------------------------------------------------------------------- +int phs_compress(S_PHS_RULE *phs_rule,unsigned char *in_buf + ,unsigned char *out_buf,UINT *header_size,UINT *new_header_size) +{ + unsigned char *old_addr = out_buf; + int supress = 0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + if(phs_rule == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nphs_compress(): phs_rule null!"); + *out_buf = ZERO_PHSI; + return STATUS_PHS_NOCOMPRESSION; + } + + + if(phs_rule->u8PHSS <= *new_header_size) + { + *header_size = phs_rule->u8PHSS; + } + else + { + *header_size = *new_header_size; + } + //To copy PHSI + out_buf++; + supress = verify_suppress_phsf(in_buf,out_buf,phs_rule->u8PHSF, + phs_rule->u8PHSM, phs_rule->u8PHSS, phs_rule->u8PHSV,new_header_size); + + if(supress == STATUS_PHS_COMPRESSED) + { + *old_addr = (unsigned char)phs_rule->u8PHSI; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress phsi %d",phs_rule->u8PHSI); + } + else + { + *old_addr = ZERO_PHSI; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In phs_compress PHSV Verification failed"); + } + return supress; +} + + +//----------------------------------------------------------------------------- +// Procedure: verify_suppress_phsf +// +// Description: This routine verifies the fields of the packet and if all the +// static fields are equal it adds the phsi of that PHS rule.If any static +// field differs it woun't suppress any field. +// +// Arguments: +// rules_set - ptr to classifier_rules. +// in_buffer - ptr to incoming packet buffer. +// out_buffer - ptr to output buffer where the suppressed header is copied. +// phsf - ptr to phsf. +// phsm - ptr to phsm. +// phss - variable holding phss. +// +// Returns: +// size-The number of bytes copied into the output buffer i.e dynamic fields. +// 0 -Packet has failed the verification. +//----------------------------------------------------------------------------- + + int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer, + unsigned char *phsf,unsigned char *phsm,unsigned int phss, + unsigned int phsv,UINT* new_header_size) +{ + unsigned int size=0; + int bit,i=0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf PHSM - 0x%X",*phsm); + + + if(phss>(*new_header_size)) + { + phss=*new_header_size; + } + while(phss > 0) + { + bit = ((*phsm << i)& SUPPRESS); + if(bit == SUPPRESS) + { + + if(*in_buffer != *phsf) + { + if(phsv == VERIFY) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf failed for field %d buf %d phsf %d",phss,*in_buffer,*phsf); + return STATUS_PHS_NOCOMPRESSION; + } + } + else + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success for field %d buf %d phsf %d",phss,*in_buffer,*phsf); + } + else + { + *out_buffer = *in_buffer; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In copying_header input %d out %d",*in_buffer,*out_buffer); + out_buffer++; + size++; + } + in_buffer++; + phsf++; + phss--; + i++; + if(i > MAX_NO_BIT) + { + i=0; + phsm++; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, PHS_SEND, DBG_LVL_ALL,"\nCOMP:In verify_phsf success"); + *new_header_size = size; + return STATUS_PHS_COMPRESSED; +} + + + + + + diff --git a/drivers/staging/bcm/PHSModule.h b/drivers/staging/bcm/PHSModule.h new file mode 100644 index 0000000..bf2b576 --- /dev/null +++ b/drivers/staging/bcm/PHSModule.h @@ -0,0 +1,95 @@ +#ifndef BCM_MINIPORT_PHSMODULE_H +#define BCM_MINIPORT_PHSMODULE_H + +int PHSTransmit(PMINI_ADAPTER Adapter, + struct sk_buff **pPacket, + USHORT Vcid, + B_UINT16 uiClassifierRuleID, + BOOLEAN bHeaderSuppressionEnabled, + PUINT PacketLen, + UCHAR bEthCSSupport); + +int PHSRecieve(PMINI_ADAPTER Adapter, + USHORT usVcid, + struct sk_buff *packet, + UINT *punPacketLen, + UCHAR *pucEthernetHdr, + UINT + ); + + +void DumpDataPacketHeader(PUCHAR pPkt); + +void DumpFullPacket(UCHAR *pBuf,UINT nPktLen); + +void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension); + + +int phs_init(PPHS_DEVICE_EXTENSION pPhsdeviceExtension,PMINI_ADAPTER Adapter); + +void free_phs_serviceflow_rules(S_SERVICEFLOW_TABLE *psServiceFlowRulesTable); + +int phs_compress(S_PHS_RULE *phs_members,unsigned char *in_buf, + unsigned char *out_buf,unsigned int *header_size,UINT *new_header_size ); + + +int verify_suppress_phsf(unsigned char *in_buffer,unsigned char *out_buffer, + unsigned char *phsf,unsigned char *phsm,unsigned int phss,unsigned int phsv,UINT *new_header_size ); + +int phs_decompress(unsigned char *in_buf,unsigned char *out_buf,\ + S_PHS_RULE *phs_rules,UINT *header_size); + + +int PhsCleanup(PPHS_DEVICE_EXTENSION pPHSDeviceExt); + +//Utility Functions +ULONG PhsUpdateClassifierRule(void* pvContext,B_UINT16 uiVcid,B_UINT16 uiClsId,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI ); + +ULONG PhsDeletePHSRule(void* pvContext,B_UINT16 uiVcid,B_UINT8 u8PHSI); + +ULONG PhsDeleteClassifierRule(void* pvContext, B_UINT16 uiVcid ,B_UINT16 uiClsId); + +ULONG PhsDeleteSFRules(void* pvContext,B_UINT16 uiVcid) ; + + +ULONG PhsCompress(void* pvContext, + B_UINT16 uiVcid, + B_UINT16 uiClsId, + void *pvInputBuffer, + void *pvOutputBuffer, + UINT *pOldHeaderSize, + UINT *pNewHeaderSize ); + +ULONG PhsDeCompress(void* pvContext, + B_UINT16 uiVcid, + void *pvInputBuffer, + void *pvOutputBuffer, + UINT *pInHeaderSize, + UINT *pOutHeaderSize); + + +BOOLEAN ValidatePHSRule(S_PHS_RULE *psPhsRule); + +BOOLEAN ValidatePHSRuleComplete(S_PHS_RULE *psPhsRule); + +UINT GetServiceFlowEntry(S_SERVICEFLOW_TABLE *psServiceFlowTable,B_UINT16 uiVcid,S_SERVICEFLOW_ENTRY **ppstServiceFlowEntry); + +UINT GetClassifierEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiClsid,E_CLASSIFIER_ENTRY_CONTEXT eClsContext, S_CLASSIFIER_ENTRY **ppstClassifierEntry); + +UINT GetPhsRuleEntry(S_CLASSIFIER_TABLE *pstClassifierTable,B_UINT32 uiPHSI,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,S_PHS_RULE **ppstPhsRule); + + +UINT CreateSFToClassifierRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_TABLE *psServiceFlowTable,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); + +UINT CreateClassiferToPHSRuleMapping(B_UINT16 uiVcid,B_UINT16 uiClsId,S_SERVICEFLOW_ENTRY *pstServiceFlowEntry,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); + +UINT CreateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,E_CLASSIFIER_ENTRY_CONTEXT eClsContext,B_UINT8 u8AssociatedPHSI); + +UINT UpdateClassifierPHSRule(B_UINT16 uiClsId,S_CLASSIFIER_ENTRY *pstClassifierEntry,S_CLASSIFIER_TABLE *psaClassifiertable ,S_PHS_RULE *psPhsRule,B_UINT8 u8AssociatedPHSI); + +BOOLEAN DerefPhsRule(B_UINT16 uiClsId,S_CLASSIFIER_TABLE *psaClassifiertable,S_PHS_RULE *pstPhsRule); + +void DumpPhsRules(PPHS_DEVICE_EXTENSION pDeviceExtension); + + +#endif diff --git a/drivers/staging/bcm/Protocol.h b/drivers/staging/bcm/Protocol.h new file mode 100644 index 0000000..00f1cc1 --- /dev/null +++ b/drivers/staging/bcm/Protocol.h @@ -0,0 +1,151 @@ +/************************************ +* Protocol.h +*************************************/ +#ifndef __PROTOCOL_H__ +#define __PROTOCOL_H__ + + +#define IPV4 4 +#define IPV6 6 + + +struct ArpHeader { + struct arphdr arp; + unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ + unsigned char ar_sip[4]; /* sender IP address */ + unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ + unsigned char ar_tip[4]; /* target IP address */ +}/*__attribute__((packed))*/; + + +struct TransportHeaderT +{ + union + { + struct udphdr uhdr; + struct tcphdr thdr; + }; +} __attribute__((packed)); +typedef struct TransportHeaderT xporthdr; + + +typedef enum _E_NWPKT_IPFRAME_TYPE +{ + eNonIPPacket, + eIPv4Packet, + eIPv6Packet +}E_NWPKT_IPFRAME_TYPE; + +typedef enum _E_NWPKT_ETHFRAME_TYPE +{ + eEthUnsupportedFrame, + eEth802LLCFrame, + eEth802LLCSNAPFrame, + eEth802QVLANFrame, + eEthOtherFrame +} E_NWPKT_ETHFRAME_TYPE; + +typedef struct _S_ETHCS_PKT_INFO +{ + E_NWPKT_IPFRAME_TYPE eNwpktIPFrameType; + E_NWPKT_ETHFRAME_TYPE eNwpktEthFrameType; + USHORT usEtherType; + UCHAR ucDSAP; +}S_ETHCS_PKT_INFO,*PS_ETHCS_PKT_INFO; + +typedef struct _ETH_CS_802_Q_FRAME +{ + ETH_HEADER_STRUC EThHdr; + USHORT UserPriority:3; + USHORT CFI:1; + USHORT VLANID:12; + USHORT EthType; +} __attribute__((packed)) ETH_CS_802_Q_FRAME; + +typedef struct _ETH_CS_802_LLC_FRAME +{ + ETH_HEADER_STRUC EThHdr; + unsigned char DSAP; + unsigned char SSAP; + unsigned char Control; +}__attribute__((packed)) ETH_CS_802_LLC_FRAME; + +typedef struct _ETH_CS_802_LLC_SNAP_FRAME +{ + ETH_HEADER_STRUC EThHdr; + unsigned char DSAP; + unsigned char SSAP; + unsigned char Control; + unsigned char OUI[3]; + unsigned short usEtherType; +} __attribute__((packed)) ETH_CS_802_LLC_SNAP_FRAME; + +typedef struct _ETH_CS_ETH2_FRAME +{ + ETH_HEADER_STRUC EThHdr; +} __attribute__((packed)) ETH_CS_ETH2_FRAME; + + +#define ETHERNET_FRAMETYPE_IPV4 ntohs(0x0800) +#define ETHERNET_FRAMETYPE_IPV6 ntohs(0x86dd) +#define ETHERNET_FRAMETYPE_802QVLAN 0x8100 +//Per SF CS Specification Encodings +typedef enum _E_SERVICEFLOW_CS_SPEC_ +{ + eCSSpecUnspecified =0, + eCSPacketIPV4, + eCSPacketIPV6, + eCS802_3PacketEthernet, + eCS802_1QPacketVLAN, + eCSPacketIPV4Over802_3Ethernet, + eCSPacketIPV6Over802_3Ethernet, + eCSPacketIPV4Over802_1QVLAN, + eCSPacketIPV6Over802_1QVLAN, + eCSPacketUnsupported +}E_SERVICEFLOW_CS_SPEC; + + +#define IP6_HEADER_LEN 40 + +#define IP_VERSION(byte) (((byte&0xF0)>>4)) + + + +#define MAC_ADDRESS_SIZE 6 +#define ETH_AND_IP_HEADER_LEN 14 + 20 +#define L4_SRC_PORT_LEN 2 +#define L4_DEST_PORT_LEN 2 + + + +#define CTRL_PKT_LEN 8 + ETH_AND_IP_HEADER_LEN + +#define ETH_ARP_FRAME 0x806 +#define ETH_IPV4_FRAME 0x800 +#define ETH_IPV6_FRAME 0x86DD +#define UDP 0x11 +#define TCP 0x06 + +#define ARP_OP_REQUEST 0x01 +#define ARP_OP_REPLY 0x02 +#define ARP_PKT_SIZE 60 + +// This is the format for the TCP packet header +typedef struct _TCP_HEADER +{ + USHORT usSrcPort; + USHORT usDestPort; + ULONG ulSeqNumber; + ULONG ulAckNumber; + UCHAR HeaderLength; + UCHAR ucFlags; + USHORT usWindowsSize; + USHORT usChkSum; + USHORT usUrgetPtr; +} TCP_HEADER,*PTCP_HEADER; +#define TCP_HEADER_LEN sizeof(TCP_HEADER) +#define TCP_ACK 0x10 //Bit 4 in tcpflags field. +#define GET_TCP_HEADER_LEN(byte) ((byte&0xF0)>>4) + + +#endif //__PROTOCOL_H__ diff --git a/drivers/staging/bcm/Prototypes.h b/drivers/staging/bcm/Prototypes.h new file mode 100644 index 0000000..7718937 --- /dev/null +++ b/drivers/staging/bcm/Prototypes.h @@ -0,0 +1,323 @@ +#ifndef _PROTOTYPES_H_ +#define _PROTOTYPES_H_ + +int BcmFileDownload(PMINI_ADAPTER Adapter,/**< Logical Adapter */ + char *path, /**< path to image file */ + unsigned int loc /**< Download Address on the chip*/ + ); +VOID LinkControlResponseMessage(PMINI_ADAPTER Adapter, PUCHAR pucBuffer); + +VOID StatisticsResponse(PMINI_ADAPTER Adapter,PVOID pvBuffer); + +VOID IdleModeResponse(PMINI_ADAPTER Adapter,PUINT puiBuffer); + +void bcm_kfree_skb(struct sk_buff *skb); +VOID bcm_kfree(VOID *ptr); + + +VOID handle_rx_control_packet(PMINI_ADAPTER Adapter, /**ucIPSourceAddressLength) + return TRUE; + for(ucLoopIndex=0; ucLoopIndex < (pstClassifierRule->ucIPSourceAddressLength);ucLoopIndex++) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Mask:0x%x PacketIp:0x%x and Classification:0x%x", (UINT)pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)ulSrcIP, (UINT)pstClassifierRule->stSrcIpAddress.ulIpv6Addr[ucLoopIndex]); + if((pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] & ulSrcIP)== + (pstClassifierRule->stSrcIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stSrcIpAddress.ulIpv4Mask[ucLoopIndex] )) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Ip Address Not Matched"); + return FALSE; +} + + +/******************************************************************* +* Function - MatchDestIpAddress() +* +* Description - Checks whether the Destination IP address from the packet +* matches with that of Queue. +* +* Parameters - pstClassifierRule: Pointer to the packet info structure. +* - ulDestIP : Destination IP address from the packet. +* +* Returns - TRUE(If address matches) else FAIL . +*********************************************************************/ +BOOLEAN MatchDestIpAddress(S_CLASSIFIER_RULE *pstClassifierRule,ULONG ulDestIP) +{ + UCHAR ucLoopIndex=0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + ulDestIP=ntohl(ulDestIP); + if(0 == pstClassifierRule->ucIPDestinationAddressLength) + return TRUE; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address 0x%x 0x%x 0x%x ", (UINT)ulDestIP, (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex], (UINT)pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex]); + + for(ucLoopIndex=0;ucLoopIndex<(pstClassifierRule->ucIPDestinationAddressLength);ucLoopIndex++) + { + if((pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex] & ulDestIP)== + (pstClassifierRule->stDestIpAddress.ulIpv4Addr[ucLoopIndex] & pstClassifierRule->stDestIpAddress.ulIpv4Mask[ucLoopIndex])) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Ip Address Not Matched"); + return FALSE; +} + + +/************************************************************************ +* Function - MatchTos() +* +* Description - Checks the TOS from the packet matches with that of queue. +* +* Parameters - pstClassifierRule : Pointer to the packet info structure. +* - ucTypeOfService: TOS from the packet. +* +* Returns - TRUE(If address matches) else FAIL. +**************************************************************************/ +BOOLEAN MatchTos(S_CLASSIFIER_RULE *pstClassifierRule,UCHAR ucTypeOfService) +{ + + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + if( 3 != pstClassifierRule->ucIPTypeOfServiceLength ) + return TRUE; + + if(((pstClassifierRule->ucTosMask & ucTypeOfService)<=pstClassifierRule->ucTosHigh) && ((pstClassifierRule->ucTosMask & ucTypeOfService)>=pstClassifierRule->ucTosLow)) + { + return TRUE; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Type Of Service Not Matched"); + return FALSE; +} + + +/*************************************************************************** +* Function - MatchProtocol() +* +* Description - Checks the protocol from the packet matches with that of queue. +* +* Parameters - pstClassifierRule: Pointer to the packet info structure. +* - ucProtocol : Protocol from the packet. +* +* Returns - TRUE(If address matches) else FAIL. +****************************************************************************/ +BOOLEAN MatchProtocol(S_CLASSIFIER_RULE *pstClassifierRule,UCHAR ucProtocol) +{ + UCHAR ucLoopIndex=0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + if(0 == pstClassifierRule->ucProtocolLength) + return TRUE; + for(ucLoopIndex=0;ucLoopIndexucProtocolLength;ucLoopIndex++) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol:0x%X Classification Protocol:0x%X",ucProtocol,pstClassifierRule->ucProtocol[ucLoopIndex]); + if(pstClassifierRule->ucProtocol[ucLoopIndex]==ucProtocol) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Not Matched"); + return FALSE; +} + + +/*********************************************************************** +* Function - MatchSrcPort() +* +* Description - Checks, Source port from the packet matches with that of queue. +* +* Parameters - pstClassifierRule: Pointer to the packet info structure. +* - ushSrcPort : Source port from the packet. +* +* Returns - TRUE(If address matches) else FAIL. +***************************************************************************/ +BOOLEAN MatchSrcPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushSrcPort) +{ + UCHAR ucLoopIndex=0; + + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + + if(0 == pstClassifierRule->ucSrcPortRangeLength) + return TRUE; + for(ucLoopIndex=0;ucLoopIndexucSrcPortRangeLength;ucLoopIndex++) + { + if(ushSrcPort <= pstClassifierRule->usSrcPortRangeHi[ucLoopIndex] && + ushSrcPort >= pstClassifierRule->usSrcPortRangeLo[ucLoopIndex]) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port: %x Not Matched ",ushSrcPort); + return FALSE; +} + + +/*********************************************************************** +* Function - MatchDestPort() +* +* Description - Checks, Destination port from packet matches with that of queue. +* +* Parameters - pstClassifierRule: Pointer to the packet info structure. +* - ushDestPort : Destination port from the packet. +* +* Returns - TRUE(If address matches) else FAIL. +***************************************************************************/ +BOOLEAN MatchDestPort(S_CLASSIFIER_RULE *pstClassifierRule,USHORT ushDestPort) +{ + UCHAR ucLoopIndex=0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + if(0 == pstClassifierRule->ucDestPortRangeLength) + return TRUE; + + for(ucLoopIndex=0;ucLoopIndexucDestPortRangeLength;ucLoopIndex++) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Matching Port:0x%X 0x%X 0x%X",ushDestPort,pstClassifierRule->usDestPortRangeLo[ucLoopIndex],pstClassifierRule->usDestPortRangeHi[ucLoopIndex]); + + if(ushDestPort <= pstClassifierRule->usDestPortRangeHi[ucLoopIndex] && + ushDestPort >= pstClassifierRule->usDestPortRangeLo[ucLoopIndex]) + { + return TRUE; + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dest Port: %x Not Matched",ushDestPort); + return FALSE; +} +/** +@ingroup tx_functions +Compares IPV4 Ip address and port number +@return Queue Index. +*/ +USHORT IpVersion4(PMINI_ADAPTER Adapter, /**< Pointer to the driver control structure */ + struct iphdr *iphd, /**"); + + xprt_hdr=(xporthdr *)((PUCHAR)iphd + sizeof(struct iphdr)); + + do { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to see Direction = %d %d", + pstClassifierRule->ucDirection, + pstClassifierRule->usVCID_Value); + + //Checking classifier validity + if(!pstClassifierRule->bUsed || pstClassifierRule->ucDirection == DOWNLINK_DIR) + { + bClassificationSucceed = FALSE; + break; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "is IPv6 check!"); + if(pstClassifierRule->bIpv6Protocol) + break; + + //**************Checking IP header parameter**************************// + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Trying to match Source IP Address"); + if(FALSE == (bClassificationSucceed = + MatchSrcIpAddress(pstClassifierRule, iphd->saddr))) + break; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source IP Address Matched"); + + if(FALSE == (bClassificationSucceed = + MatchDestIpAddress(pstClassifierRule, iphd->daddr))) + break; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination IP Address Matched"); + + if(FALSE == (bClassificationSucceed = + MatchTos(pstClassifierRule, iphd->tos))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Match failed\n"); + break; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "TOS Matched"); + + if(FALSE == (bClassificationSucceed = + MatchProtocol(pstClassifierRule,iphd->protocol))) + break; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Protocol Matched"); + + //if protocol is not TCP or UDP then no need of comparing source port and destination port + if(iphd->protocol!=TCP && iphd->protocol!=UDP) + break; +#if 0 + //check if memory is available of src and Dest port + if(ETH_AND_IP_HEADER_LEN + L4_SRC_PORT_LEN + L4_DEST_PORT_LEN > Packet->len) + { + //This is not an erroneous condition and pkt will be checked for next classification. + bClassificationSucceed = FALSE; + break; + } +#endif + //******************Checking Transport Layer Header field if present *****************// + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Source Port %04x", + (iphd->protocol==UDP)?xprt_hdr->uhdr.source:xprt_hdr->thdr.source); + + if(FALSE == (bClassificationSucceed = + MatchSrcPort(pstClassifierRule, + ntohs((iphd->protocol == UDP)? + xprt_hdr->uhdr.source:xprt_hdr->thdr.source)))) + break; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Src Port Matched"); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Destination Port %04x", + (iphd->protocol==UDP)?xprt_hdr->uhdr.dest: + xprt_hdr->thdr.dest); + if(FALSE == (bClassificationSucceed = + MatchDestPort(pstClassifierRule, + ntohs((iphd->protocol == UDP)? + xprt_hdr->uhdr.dest:xprt_hdr->thdr.dest)))) + break; + } while(0); + + if(TRUE==bClassificationSucceed) + { + INT iMatchedSFQueueIndex = 0; + iMatchedSFQueueIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID); + if(iMatchedSFQueueIndex >= NO_OF_QUEUES) + { + bClassificationSucceed = FALSE; + } + else + { + if(FALSE == Adapter->PackInfo[iMatchedSFQueueIndex].bActive) + { + bClassificationSucceed = FALSE; + } + } + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "IpVersion4 <=========="); + + return bClassificationSucceed; +} +/** +@ingroup tx_functions +@return Queue Index based on priority. +*/ +USHORT GetPacketQueueIndex(PMINI_ADAPTER Adapter, /**"); + + if(NULL==Adapter || NULL==Packet) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, QUEUE_INDEX, DBG_LVL_ALL, "Got NULL Values<======"); + return -1; + } + + usIndex = ClassifyPacket(Adapter,Packet); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, QUEUE_INDEX, DBG_LVL_ALL, "Got Queue Index %x",usIndex); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, QUEUE_INDEX, DBG_LVL_ALL, "GetPacketQueueIndex <=============="); + return usIndex; +} + +VOID PruneQueueAllSF(PMINI_ADAPTER Adapter) +{ + UINT iIndex = 0; + + for(iIndex = 0; iIndex < HiPriority; iIndex++) + { + if(!Adapter->PackInfo[iIndex].bValid) + continue; + + PruneQueue(Adapter, iIndex); + } +} + + +/** +@ingroup tx_functions +This function checks if the max queue size for a queue +is less than number of bytes in the queue. If so - +drops packets from the Head till the number of bytes is +less than or equal to max queue size for the queue. +*/ +VOID PruneQueue(PMINI_ADAPTER Adapter,/** Index %d",iIndex); + + if(iIndex == HiPriority) + return; + + if(!Adapter || (iIndex < 0) || (iIndex > HiPriority)) + return; + + /* To Store the netdevice statistic */ + netstats = &((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats; + + spin_lock_bh(&Adapter->PackInfo[iIndex].SFQueueLock); + + while(1) +// while((UINT)Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost > +// SF_MAX_ALLOWED_PACKETS_TO_BACKUP) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "uiCurrentBytesOnHost:%x uiMaxBucketSize :%x", + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost, + Adapter->PackInfo[iIndex].uiMaxBucketSize); + + PacketToDrop = Adapter->PackInfo[iIndex].FirstTxQueue; + + if(PacketToDrop == NULL) + break; + if((Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost < SF_MAX_ALLOWED_PACKETS_TO_BACKUP) && + ((1000*(jiffies - *((B_UINT32 *)(PacketToDrop->cb)+SKB_CB_LATENCY_OFFSET))/HZ) <= Adapter->PackInfo[iIndex].uiMaxLatency)) + break; + + if(PacketToDrop) + { + if(netstats) + netstats->tx_dropped++; + atomic_inc(&Adapter->TxDroppedPacketCount); + DEQUEUEPACKET(Adapter->PackInfo[iIndex].FirstTxQueue, + Adapter->PackInfo[iIndex].LastTxQueue); + /// update current bytes and packets count + Adapter->PackInfo[iIndex].uiCurrentBytesOnHost -= + PacketToDrop->len; + Adapter->PackInfo[iIndex].uiCurrentPacketsOnHost--; + /// update dropped bytes and packets counts + Adapter->PackInfo[iIndex].uiDroppedCountBytes += PacketToDrop->len; + Adapter->PackInfo[iIndex].uiDroppedCountPackets++; + bcm_kfree_skb(PacketToDrop); + + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x", + Adapter->PackInfo[iIndex].uiDroppedCountBytes, + Adapter->PackInfo[iIndex].uiDroppedCountPackets); + + atomic_dec(&Adapter->TotalPacketCount); + Adapter->bcm_jiffies = jiffies; + } + + spin_unlock_bh(&Adapter->PackInfo[iIndex].SFQueueLock); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "TotalPacketCount:%x", + atomic_read(&Adapter->TotalPacketCount)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, PRUNE_QUEUE, DBG_LVL_ALL, "<====="); +} + +VOID flush_all_queues(PMINI_ADAPTER Adapter) +{ + INT iQIndex; + UINT uiTotalPacketLength; + struct sk_buff* PacketToDrop=NULL; + struct net_device_stats* netstats=NULL; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "=====>"); + /* To Store the netdevice statistic */ + netstats = &((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats; + +// down(&Adapter->data_packet_queue_lock); + for(iQIndex=LowPriority; iQIndexPackInfo[iQIndex].SFQueueLock); + while(Adapter->PackInfo[iQIndex].FirstTxQueue) + { + PacketToDrop = Adapter->PackInfo[iQIndex].FirstTxQueue; + if(PacketToDrop) + { + uiTotalPacketLength = PacketToDrop->len; + netstats->tx_dropped++; + atomic_inc(&Adapter->TxDroppedPacketCount); + } + else + uiTotalPacketLength = 0; + + DEQUEUEPACKET(Adapter->PackInfo[iQIndex].FirstTxQueue, + Adapter->PackInfo[iQIndex].LastTxQueue); + + /* Free the skb */ + bcm_kfree_skb(PacketToDrop); + + /// update current bytes and packets count + Adapter->PackInfo[iQIndex].uiCurrentBytesOnHost -= uiTotalPacketLength; + Adapter->PackInfo[iQIndex].uiCurrentPacketsOnHost--; + + /// update dropped bytes and packets counts + Adapter->PackInfo[iQIndex].uiDroppedCountBytes += uiTotalPacketLength; + Adapter->PackInfo[iQIndex].uiDroppedCountPackets++; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "Dropped Bytes:%x Dropped Packets:%x", + Adapter->PackInfo[iQIndex].uiDroppedCountBytes, + Adapter->PackInfo[iQIndex].uiDroppedCountPackets); + atomic_dec(&Adapter->TotalPacketCount); + } + spin_unlock_bh(&Adapter->PackInfo[iQIndex].SFQueueLock); + } +// up(&Adapter->data_packet_queue_lock); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, DUMP_INFO, DBG_LVL_ALL, "<====="); +} + +USHORT ClassifyPacket(PMINI_ADAPTER Adapter,struct sk_buff* skb) +{ + INT uiLoopIndex=0; + S_CLASSIFIER_RULE *pstClassifierRule = NULL; + S_ETHCS_PKT_INFO stEthCsPktInfo; + PVOID pvEThPayload = NULL; + struct iphdr *pIpHeader = NULL; + INT uiSfIndex=0; + USHORT usIndex=Adapter->usBestEffortQueueIndex; + BOOLEAN bFragmentedPkt=FALSE,bClassificationSucceed=FALSE; + USHORT usCurrFragment =0; + + PTCP_HEADER pTcpHeader; + UCHAR IpHeaderLength; + UCHAR TcpHeaderLength; + + pvEThPayload = skb->data; + *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = 0; + EThCSGetPktInfo(Adapter,pvEThPayload,&stEthCsPktInfo); + + switch(stEthCsPktInfo.eNwpktEthFrameType) + { + case eEth802LLCFrame: + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLCFrame\n"); + pIpHeader = pvEThPayload + sizeof(ETH_CS_802_LLC_FRAME); + break; + } + + case eEth802LLCSNAPFrame: + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802LLC SNAP Frame\n"); + pIpHeader = pvEThPayload + sizeof(ETH_CS_802_LLC_SNAP_FRAME); + break; + } + case eEth802QVLANFrame: + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : 802.1Q VLANFrame\n"); + pIpHeader = pvEThPayload + sizeof(ETH_CS_802_Q_FRAME); + break; + } + case eEthOtherFrame: + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : ETH Other Frame\n"); + pIpHeader = pvEThPayload + sizeof(ETH_CS_ETH2_FRAME); + break; + } + default: + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Unrecognized ETH Frame\n"); + pIpHeader = pvEThPayload + sizeof(ETH_CS_ETH2_FRAME); + break; + } + } + + if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) + { + usCurrFragment = (ntohs(pIpHeader->frag_off) & IP_OFFSET); + if((ntohs(pIpHeader->frag_off) & IP_MF) || usCurrFragment) + bFragmentedPkt = TRUE; + + if(bFragmentedPkt) + { + //Fragmented Packet. Get Frag Classifier Entry. + pstClassifierRule = GetFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr); + if(pstClassifierRule) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"It is next Fragmented pkt"); + bClassificationSucceed=TRUE; + } + if(!(ntohs(pIpHeader->frag_off) & IP_MF)) + { + //Fragmented Last packet . Remove Frag Classifier Entry + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,"This is the last fragmented Pkt"); + DelFragIPClsEntry(Adapter,pIpHeader->id, pIpHeader->saddr); + } + } + } + + for(uiLoopIndex = MAX_CLASSIFIERS - 1; uiLoopIndex >= 0; uiLoopIndex--) + { + if (Adapter->device_removed) + { + bClassificationSucceed = FALSE; + break; + } + + if(bClassificationSucceed) + break; + //Iterate through all classifiers which are already in order of priority + //to classify the packet until match found + do + { + if(FALSE==Adapter->astClassifierTable[uiLoopIndex].bUsed) + { + bClassificationSucceed=FALSE; + break; + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Adapter->PackInfo[%d].bvalid=True\n",uiLoopIndex); + + if(0 == Adapter->astClassifierTable[uiLoopIndex].ucDirection) + { + bClassificationSucceed=FALSE;//cannot be processed for classification. + break; // it is a down link connection + } + + pstClassifierRule = &Adapter->astClassifierTable[uiLoopIndex]; + + uiSfIndex = SearchSfid(Adapter,pstClassifierRule->ulSFID); + if(uiSfIndex > NO_OF_QUEUES) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Queue Not Valid. SearchSfid for this classifier Failed\n"); + break; + } + + if(Adapter->PackInfo[uiSfIndex].bEthCSSupport) + { + + if(eEthUnsupportedFrame==stEthCsPktInfo.eNwpktEthFrameType) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a Valid Supported Ethernet Frame \n"); + bClassificationSucceed = FALSE; + break; + } + + + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Performing ETH CS Classification on Classifier Rule ID : %x Service Flow ID : %lx\n",pstClassifierRule->uiClassifierRuleIndex,Adapter->PackInfo[uiSfIndex].ulSFID); + bClassificationSucceed = EThCSClassifyPkt(Adapter,skb,&stEthCsPktInfo,pstClassifierRule, Adapter->PackInfo[uiSfIndex].bEthCSSupport); + + if(!bClassificationSucceed) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ClassifyPacket : Ethernet CS Classification Failed\n"); + break; + } + } + + else // No ETH Supported on this SF + { + if(eEthOtherFrame != stEthCsPktInfo.eNwpktEthFrameType) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet Not a 802.3 Ethernet Frame... hence not allowed over non-ETH CS SF \n"); + bClassificationSucceed = FALSE; + break; + } + } + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Proceeding to IP CS Clasification"); + + if(Adapter->PackInfo[uiSfIndex].bIPCSSupport) + { + + if(stEthCsPktInfo.eNwpktIPFrameType == eNonIPPacket) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, " ClassifyPacket : Packet is Not an IP Packet \n"); + bClassificationSucceed = FALSE; + break; + } + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "Dump IP Header : \n"); + DumpFullPacket((PUCHAR)pIpHeader,20); + + if(stEthCsPktInfo.eNwpktIPFrameType == eIPv4Packet) + bClassificationSucceed = IpVersion4(Adapter,pIpHeader,pstClassifierRule); + else if(stEthCsPktInfo.eNwpktIPFrameType == eIPv6Packet) + bClassificationSucceed = IpVersion6(Adapter,pIpHeader,pstClassifierRule); + } + + }while(0); + } + + if(bClassificationSucceed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "CF id : %d, SF ID is =%lu",pstClassifierRule->uiClassifierRuleIndex, pstClassifierRule->ulSFID); + + //Store The matched Classifier in SKB + *((UINT32*)(skb->cb)+SKB_CB_CLASSIFICATION_OFFSET) = pstClassifierRule->uiClassifierRuleIndex; + if((TCP == pIpHeader->protocol ) && !bFragmentedPkt && (ETH_AND_IP_HEADER_LEN + TCP_HEADER_LEN <= skb->len) ) + { + IpHeaderLength = pIpHeader->ihl; + pTcpHeader = (PTCP_HEADER)(((PUCHAR)pIpHeader)+(IpHeaderLength*4)); + TcpHeaderLength = GET_TCP_HEADER_LEN(pTcpHeader->HeaderLength); + + if((pTcpHeader->ucFlags & TCP_ACK) && + (ntohs(pIpHeader->tot_len) == (IpHeaderLength*4)+(TcpHeaderLength*4))) + { + *((UINT32*) (skb->cb) +SKB_CB_TCPACK_OFFSET ) = TCP_ACK; + } + } + + usIndex = SearchSfid(Adapter, pstClassifierRule->ulSFID); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "index is =%d", usIndex); + + //If this is the first fragment of a Fragmented pkt, add this CF. Only This CF should be used for all other fragment of this Pkt. + if(bFragmentedPkt && (usCurrFragment == 0)) + { + //First Fragment of Fragmented Packet. Create Frag CLS Entry + S_FRAGMENTED_PACKET_INFO stFragPktInfo; + stFragPktInfo.bUsed = TRUE; + stFragPktInfo.ulSrcIpAddress = pIpHeader->saddr; + stFragPktInfo.usIpIdentification = pIpHeader->id; + stFragPktInfo.pstMatchedClassifierEntry = pstClassifierRule; + stFragPktInfo.bOutOfOrderFragment = FALSE; + AddFragIPClsEntry(Adapter,&stFragPktInfo); + } + + + } + + if(bClassificationSucceed) + return usIndex; + else + return INVALID_QUEUE_INDEX; +} + +BOOLEAN EthCSMatchSrcMACAddress(S_CLASSIFIER_RULE *pstClassifierRule,PUCHAR Mac) +{ + UINT i=0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + if(pstClassifierRule->ucEthCSSrcMACLen==0) + return TRUE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); + for(i=0;iau8EThCSSrcMAC[i],pstClassifierRule->au8EThCSSrcMACMask[i]); + if((pstClassifierRule->au8EThCSSrcMAC[i] & pstClassifierRule->au8EThCSSrcMACMask[i])!= + (Mac[i] & pstClassifierRule->au8EThCSSrcMACMask[i])) + return FALSE; + } + return TRUE; +} + +BOOLEAN EthCSMatchDestMACAddress(S_CLASSIFIER_RULE *pstClassifierRule,PUCHAR Mac) +{ + UINT i=0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + if(pstClassifierRule->ucEthCSDestMACLen==0) + return TRUE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s \n",__FUNCTION__); + for(i=0;iau8EThCSDestMAC[i],pstClassifierRule->au8EThCSDestMACMask[i]); + if((pstClassifierRule->au8EThCSDestMAC[i] & pstClassifierRule->au8EThCSDestMACMask[i])!= + (Mac[i] & pstClassifierRule->au8EThCSDestMACMask[i])) + return FALSE; + } + return TRUE; +} + +BOOLEAN EthCSMatchEThTypeSAP(S_CLASSIFIER_RULE *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo) +{ + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + if((pstClassifierRule->ucEtherTypeLen==0)|| + (pstClassifierRule->au8EthCSEtherType[0] == 0)) + return TRUE; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s SrcEtherType:%x CLS EtherType[0]:%x\n",__FUNCTION__,pstEthCsPktInfo->usEtherType,pstClassifierRule->au8EthCSEtherType[0]); + if(pstClassifierRule->au8EthCSEtherType[0] == 1) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS EtherType[1]:%x EtherType[2]:%x\n",__FUNCTION__,pstClassifierRule->au8EthCSEtherType[1],pstClassifierRule->au8EthCSEtherType[2]); + + if(memcmp(&pstEthCsPktInfo->usEtherType,&pstClassifierRule->au8EthCSEtherType[1],2)==0) + return TRUE; + else + return FALSE; + } + + if(pstClassifierRule->au8EthCSEtherType[0] == 2) + { + if(eEth802LLCFrame != pstEthCsPktInfo->eNwpktEthFrameType) + return FALSE; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s EthCS DSAP:%x EtherType[2]:%x\n",__FUNCTION__,pstEthCsPktInfo->ucDSAP,pstClassifierRule->au8EthCSEtherType[2]); + if(pstEthCsPktInfo->ucDSAP == pstClassifierRule->au8EthCSEtherType[2]) + return TRUE; + else + return FALSE; + + } + + return FALSE; + +} + +BOOLEAN EthCSMatchVLANRules(S_CLASSIFIER_RULE *pstClassifierRule,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo) +{ + BOOLEAN bClassificationSucceed = FALSE; + USHORT usVLANID; + B_UINT8 uPriority = 0; + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s CLS UserPrio:%x CLS VLANID:%x\n",__FUNCTION__,ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),pstClassifierRule->usVLANID); + + /* In case FW didn't recieve the TLV, the priority field should be ignored */ + if(pstClassifierRule->usValidityBitMap & (1<eNwpktEthFrameType!=eEth802QVLANFrame) + return FALSE; + + uPriority = (ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xF000) >> 13; + + if((uPriority >= pstClassifierRule->usUserPriority[0]) && (uPriority <= pstClassifierRule->usUserPriority[1])) + bClassificationSucceed = TRUE; + + if(!bClassificationSucceed) + return FALSE; + } + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 D User Priority Rule Matched\n"); + + bClassificationSucceed = FALSE; + + if(pstClassifierRule->usValidityBitMap & (1<eNwpktEthFrameType!=eEth802QVLANFrame) + return FALSE; + + usVLANID = ntohs(*(USHORT *)(skb->data + sizeof(ETH_HEADER_STRUC))) & 0xFFF; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "%s Pkt VLANID %x Priority: %d\n",__FUNCTION__,usVLANID, uPriority); + + if(usVLANID == ((pstClassifierRule->usVLANID & 0xFFF0) >> 4)) + bClassificationSucceed = TRUE; + + if(!bClassificationSucceed) + return FALSE; + } + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 Q VLAN ID Rule Matched\n"); + + return TRUE; +} + + +BOOLEAN EThCSClassifyPkt(PMINI_ADAPTER Adapter,struct sk_buff* skb,PS_ETHCS_PKT_INFO pstEthCsPktInfo,S_CLASSIFIER_RULE *pstClassifierRule, B_UINT8 EthCSCupport) +{ + BOOLEAN bClassificationSucceed = FALSE; + bClassificationSucceed = EthCSMatchSrcMACAddress(pstClassifierRule,((ETH_HEADER_STRUC *)(skb->data))->au8SourceAddress); + if(!bClassificationSucceed) + return FALSE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS SrcMAC Matched\n"); + + bClassificationSucceed = EthCSMatchDestMACAddress(pstClassifierRule,((ETH_HEADER_STRUC*)(skb->data))->au8DestinationAddress); + if(!bClassificationSucceed) + return FALSE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS DestMAC Matched\n"); + + //classify on ETHType/802.2SAP TLV + bClassificationSucceed = EthCSMatchEThTypeSAP(pstClassifierRule,skb,pstEthCsPktInfo); + if(!bClassificationSucceed) + return FALSE; + + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS EthType/802.2SAP Matched\n"); + + //classify on 802.1VLAN Header Parameters + + bClassificationSucceed = EthCSMatchVLANRules(pstClassifierRule,skb,pstEthCsPktInfo); + if(!bClassificationSucceed) + return FALSE; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "ETH CS 802.1 VLAN Rules Matched\n"); + + return bClassificationSucceed; +} + +void EThCSGetPktInfo(PMINI_ADAPTER Adapter,PVOID pvEthPayload,PS_ETHCS_PKT_INFO pstEthCsPktInfo) +{ + USHORT u16Etype = ntohs(((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : Eth Hdr Type : %X\n",u16Etype); + if(u16Etype > 0x5dc) + { + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCSGetPktInfo : ETH2 Frame \n"); + //ETH2 Frame + if(u16Etype == ETHERNET_FRAMETYPE_802QVLAN) + { + //802.1Q VLAN Header + pstEthCsPktInfo->eNwpktEthFrameType = eEth802QVLANFrame; + u16Etype = ((ETH_CS_802_Q_FRAME*)pvEthPayload)->EthType; + //((ETH_CS_802_Q_FRAME*)pvEthPayload)->UserPriority + } + else + { + pstEthCsPktInfo->eNwpktEthFrameType = eEthOtherFrame; + u16Etype = ntohs(u16Etype); + } + + } + else + { + //802.2 LLC + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "802.2 LLC Frame \n"); + pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCFrame; + pstEthCsPktInfo->ucDSAP = ((ETH_CS_802_LLC_FRAME*)pvEthPayload)->DSAP; + if(pstEthCsPktInfo->ucDSAP == 0xAA && ((ETH_CS_802_LLC_FRAME*)pvEthPayload)->SSAP == 0xAA) + { + //SNAP Frame + pstEthCsPktInfo->eNwpktEthFrameType = eEth802LLCSNAPFrame; + u16Etype = ((ETH_CS_802_LLC_SNAP_FRAME*)pvEthPayload)->usEtherType; + } + } + if(u16Etype == ETHERNET_FRAMETYPE_IPV4) + pstEthCsPktInfo->eNwpktIPFrameType = eIPv4Packet; + else if(u16Etype == ETHERNET_FRAMETYPE_IPV6) + pstEthCsPktInfo->eNwpktIPFrameType = eIPv6Packet; + else + pstEthCsPktInfo->eNwpktIPFrameType = eNonIPPacket; + + pstEthCsPktInfo->usEtherType = ((ETH_HEADER_STRUC*)pvEthPayload)->u16Etype; + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktIPFrameType : %x\n",pstEthCsPktInfo->eNwpktIPFrameType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->eNwpktEthFrameType : %x\n",pstEthCsPktInfo->eNwpktEthFrameType); + BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL, "EthCsPktInfo->usEtherType : %x\n",pstEthCsPktInfo->usEtherType); +} + + + diff --git a/drivers/staging/bcm/Queue.h b/drivers/staging/bcm/Queue.h new file mode 100644 index 0000000..e1f1da2 --- /dev/null +++ b/drivers/staging/bcm/Queue.h @@ -0,0 +1,31 @@ +/************************************* +* Queue.h +**************************************/ +#ifndef __QUEUE_H__ +#define __QUEUE_H__ + + + +#define ENQUEUEPACKET(_Head, _Tail,_Packet) \ +do \ +{ \ + if (!_Head) { \ + _Head = _Packet; \ + } \ + else { \ + (_Tail)->next = _Packet; \ + } \ + (_Packet)->next = NULL; \ + _Tail = _Packet; \ +}while(0) +#define DEQUEUEPACKET(Head, Tail ) \ +do \ +{ if(Head) \ + { \ + if (!Head->next) { \ + Tail = NULL; \ + } \ + Head = Head->next; \ + } \ +}while(0) +#endif //__QUEUE_H__ diff --git a/drivers/staging/bcm/TODO b/drivers/staging/bcm/TODO new file mode 100644 index 0000000..366634b --- /dev/null +++ b/drivers/staging/bcm/TODO @@ -0,0 +1,15 @@ +TODO: + - fix non-standard kernel style + - sparse warnings + - checkpatch warnings + - remove compatiablity code for older kernels + - remove #ifdef's + - fix bogus device nameing and reference counting (see bcm_notify_event) + - fix use of file I/O to load config + - request firmware + - update to current network device API + - merge some files together + - cleanup/eliminate debug messages + + - integrate with existing Wimax stack? + diff --git a/drivers/staging/bcm/Transmit.c b/drivers/staging/bcm/Transmit.c new file mode 100644 index 0000000..9a076b5 --- /dev/null +++ b/drivers/staging/bcm/Transmit.c @@ -0,0 +1,553 @@ +/** +@file Transmit.c +@defgroup tx_functions Transmission +@section Queueing +@dot +digraph transmit1 { +node[shape=box] +edge[weight=5;color=red] +bcm_transmit->reply_to_arp_request[label="ARP"] +bcm_transmit->GetPacketQueueIndex[label="IP Packet"] +GetPacketQueueIndex->IpVersion4[label="IPV4"] +GetPacketQueueIndex->IpVersion6[label="IPV6"] +} + +@enddot + +@section De-Queueing +@dot +digraph transmit2 { +node[shape=box] +edge[weight=5;color=red] +interrupt_service_thread->transmit_packets +tx_pkt_hdler->transmit_packets +transmit_packets->CheckAndSendPacketFromIndex +transmit_packets->UpdateTokenCount +CheckAndSendPacketFromIndex->PruneQueue +CheckAndSendPacketFromIndex->IsPacketAllowedForFlow +CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"] +SendControlPacket->bcm_cmd53 +CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"] +SendPacketFromQueue->SetupNextSend->bcm_cmd53 +} +@enddot +*/ + +#include "headers.h" + +/******************************************************************* +* Function - bcm_transmit() +* +* Description - This is the main transmit function for our virtual +* interface(veth0). It handles the ARP packets. It +* clones this packet and then Queue it to a suitable +* Queue. Then calls the transmit_packet(). +* +* Parameter - skb - Pointer to the socket buffer structure +* dev - Pointer to the virtual net device structure +* +* Returns - zero (success) or -ve value (failure) +* +*********************************************************************/ + +INT bcm_transmit(struct sk_buff *skb, /**< skb */ + struct net_device *dev /**< net device pointer */ + ) +{ + PMINI_ADAPTER Adapter = NULL; + USHORT qindex=0; + struct timeval tv; + UINT pkt_type = 0; + UINT calltransmit = 0; + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "\n%s====>\n",__FUNCTION__); + + memset(&tv, 0, sizeof(tv)); + /* Check for valid parameters */ + if(skb == NULL || dev==NULL) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL, "Got NULL skb or dev\n"); + return -EINVAL; + } + + Adapter = GET_BCM_ADAPTER(dev); + if(!Adapter) + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Got Invalid Adapter\n"); + return -EINVAL; + } + if(Adapter->device_removed == TRUE || !Adapter->LinkUpStatus) + { + if(!netif_queue_stopped(dev)) { + netif_carrier_off(dev); + netif_stop_queue(dev); + } + return STATUS_FAILURE; + } + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Packet size : %d\n", skb->len); + + /*Add Ethernet CS check here*/ + if(Adapter->TransferMode == IP_PACKET_ONLY_MODE ) + { + pkt_type = ntohs(*(PUSHORT)(skb->data + 12)); + /* Get the queue index where the packet is to be queued */ + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Getting the Queue Index....."); + + qindex = GetPacketQueueIndex(Adapter,skb); + + if((SHORT)INVALID_QUEUE_INDEX==(SHORT)qindex) + { + if(pkt_type == ETH_ARP_FRAME) + { + /* + Reply directly to ARP request packet + ARP Spoofing only if NO ETH CS rule matches for it + */ + BCM_DEBUG_PRINT (Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ARP OPCODE = %02x", + + (*(PUCHAR)(skb->data + 21))); + + reply_to_arp_request(skb); + + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n"); + + } + else + { + BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, + "Invalid queue index, dropping pkt\n"); + + bcm_kfree_skb(skb); + } + return STATUS_SUCCESS; + } + + if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP) + { + atomic_inc(&Adapter->TxDroppedPacketCount); + bcm_kfree_skb(skb); + return STATUS_SUCCESS; + } + + /* Now Enqueue the packet */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit Enqueueing the Packet To Queue %d",qindex); + spin_lock(&Adapter->PackInfo[qindex].SFQueueLock); + Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len; + Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++; + + *((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies; + ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue, + Adapter->PackInfo[qindex].LastTxQueue, skb); + atomic_inc(&Adapter->TotalPacketCount); + spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock); + do_gettimeofday(&tv); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Pkt Len = %d, sec: %ld, usec: %ld\n", + (skb->len-ETH_HLEN), tv.tv_sec, tv.tv_usec); + +#ifdef BCM_SHM_INTERFACE + spin_lock(&Adapter->txtransmitlock); + if(Adapter->txtransmit_running == 0) + { + Adapter->txtransmit_running = 1; + calltransmit = 1; + } + else + calltransmit = 0; + + spin_unlock(&Adapter->txtransmitlock); +#endif + if(calltransmit == 1) + transmit_packets(Adapter); + else + { + if(!atomic_read(&Adapter->TxPktAvail)) + { + atomic_set(&Adapter->TxPktAvail, 1); +#ifdef BCM_SHM_INTERFACE + virtual_mail_box_interrupt(); +#endif + wake_up(&Adapter->tx_packet_wait_queue); + } + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<===="); + } + else + bcm_kfree_skb(skb); + + return STATUS_SUCCESS; +} + + +/** +@ingroup ctrl_pkt_functions +This function dispatches control packet to the h/w interface +@return zero(success) or -ve value(failure) +*/ +INT SendControlPacket(PMINI_ADAPTER Adapter, /**"); + + PLeader=(PLEADER)pControlPacket; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); + if(!pControlPacket || !Adapter) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter"); + return STATUS_FAILURE; + } + if((atomic_read( &Adapter->CurrNumFreeTxDesc ) < + ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); + if(Adapter->bcm_jiffies == 0) + { + Adapter->bcm_jiffies = jiffies; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %lu", + Adapter->bcm_jiffies); + } + return STATUS_FAILURE; + } + + /* Update the netdevice statistics */ + /* Dump Packet */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength); + if(Adapter->device_removed) + return 0; +#ifndef BCM_SHM_INTERFACE + Adapter->interface_transmit(Adapter->pvInterfaceAdapter, + pControlPacket, (PLeader->PLength + LEADER_SIZE)); +#else + tx_pkts_to_firmware(pControlPacket,(PLeader->PLength + LEADER_SIZE),1); + + if(PLeader->Status==IDLE_MESSAGE) + { + if(((CONTROL_MESSAGE*)PLeader)->szData[0] == GO_TO_IDLE_MODE_PAYLOAD && + ((CONTROL_MESSAGE*)PLeader)->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Ack Sent to the Device\n"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Host Entering into Idle Mode\n"); + do_gettimeofday(&tv); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "IdleMode Msg sent to f/w at time :%ld ms", tv.tv_sec *1000 + tv.tv_usec /1000); + if(Adapter->bDoSuspend != TRUE) + { + Adapter->IdleMode = TRUE; + Adapter->bPreparingForLowPowerMode = FALSE ; + } + } + } + if((PLeader->Status == LINK_UP_CONTROL_REQ) && + ((PUCHAR)pControlPacket)[sizeof(LEADER)] == LINK_UP_ACK && + ((PUCHAR)pControlPacket)[sizeof(LEADER)+1] == + LINK_SHUTDOWN_REQ_FROM_FIRMWARE && + ((PUCHAR)pControlPacket)[sizeof(LEADER)+2] == SHUTDOWN_ACK_FROM_DRIVER) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shut Down ACK Sent and Host entering Shut State \n"); + if(Adapter->bDoSuspend != TRUE) + { + Adapter->bShutStatus = TRUE; + Adapter->bPreparingForLowPowerMode = FALSE; + Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; + } + + } +#endif + + ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++; + ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+= + PLeader->PLength; + atomic_dec(&Adapter->CurrNumFreeTxDesc); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); + return STATUS_SUCCESS; +} +static LEADER Leader={0}; +/** +@ingroup tx_functions +This function despatches the IP packets with the given vcid +to the target via the host h/w interface. +@return zero(success) or -ve value(failure) +*/ +INT SetupNextSend(PMINI_ADAPTER Adapter, /**len > MAX_DEVICE_DESC_SIZE) + { + status = STATUS_FAILURE; + goto errExit; + } + + /* Get the Classifier Rule ID */ + uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET); + QueueIndex = SearchVcid( Adapter,Vcid); + if(QueueIndex < NO_OF_QUEUES) + { + bHeaderSupressionEnabled = + Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled; + bHeaderSupressionEnabled = + bHeaderSupressionEnabled & Adapter->bPHSEnabled; + } + if(Adapter->device_removed) + { + status = STATUS_FAILURE; + goto errExit; + } + + status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, + (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); + + if(status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n"); + goto errExit; + } + + Leader.Vcid = Vcid; + + if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET )) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n"); + Leader.Status = LEADER_STATUS_TCP_ACK; + } + else + { + Leader.Status = LEADER_STATUS; + } + + if(Adapter->PackInfo[QueueIndex].bEthCSSupport) + { + Leader.PLength = Packet->len; + if(skb_headroom(Packet) < LEADER_SIZE) + { + if((status = skb_cow(Packet,LEADER_SIZE))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n"); + goto errExit; + } + } + skb_push(Packet, LEADER_SIZE); + memcpy(Packet->data, &Leader, LEADER_SIZE); + } + + else + { + Leader.PLength = Packet->len - ETH_HLEN; + memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid); + +#ifndef BCM_SHM_INTERFACE + status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, + Packet->data, (Leader.PLength + LEADER_SIZE)); +#else + status = tx_pkts_to_firmware(Packet,Packet->len,0); +#endif + if(status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n"); + } + else + { + Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; + atomic_add(Leader.PLength, &Adapter->GoodTxByteCount); + atomic_inc(&Adapter->TxTotalPacketCount); +#ifdef GDMA_INTERFACE + dontfree = 1; +#endif + } + + atomic_dec(&Adapter->CurrNumFreeTxDesc); + +errExit: + + if(STATUS_SUCCESS == status) + { + Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3; + Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len); + Adapter->PackInfo[QueueIndex].uiSentPackets++; + Adapter->PackInfo[QueueIndex].NumOfPacketsSent++; + + atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount); +#ifdef BCM_SHM_INTERFACE + if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0) + { + atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0); + } +#endif + Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; + } + + +#ifdef GDMA_INTERFACE + if(!dontfree){ + bcm_kfree_skb(Packet); + } +#else + bcm_kfree_skb(Packet); +#endif + return status; +} + +/** +@ingroup tx_functions +Transmit thread +*/ +int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/ + ) +{ +#ifndef BCM_SHM_INTERFACE + int status = 0; +#endif + + UINT calltransmit = 1; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Entring to wait for signal from the interrupt service thread!Adapter = 0x%x",(unsigned int) Adapter); + + + while(1) + { + if(Adapter->LinkUpStatus){ + wait_event_timeout(Adapter->tx_packet_wait_queue, + ((atomic_read(&Adapter->TxPktAvail) && + (MINIMUM_PENDING_DESCRIPTORS < + atomic_read(&Adapter->CurrNumFreeTxDesc)) && + (Adapter->device_removed == FALSE))) || + (1 == Adapter->downloadDDR) || kthread_should_stop() +#ifndef BCM_SHM_INTERFACE + || (TRUE == Adapter->bEndPointHalted) +#endif + , msecs_to_jiffies(10)); + } + else{ + wait_event(Adapter->tx_packet_wait_queue, + ((atomic_read(&Adapter->TxPktAvail) && + (MINIMUM_PENDING_DESCRIPTORS < + atomic_read(&Adapter->CurrNumFreeTxDesc)) && + (Adapter->device_removed == FALSE))) || + (1 == Adapter->downloadDDR) || kthread_should_stop() +#ifndef BCM_SHM_INTERFACE + || (TRUE == Adapter->bEndPointHalted) +#endif + ); + } + + if(kthread_should_stop() || Adapter->device_removed) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n"); + Adapter->transmit_packet_thread = NULL; + return 0; + } + +#ifndef BCM_SHM_INTERFACE + + if(Adapter->downloadDDR == 1) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Downloading DDR Settings\n"); + Adapter->downloadDDR +=1; + status = download_ddr_settings(Adapter); + if(status) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "DDR DOWNLOAD FAILED!\n"); + continue; + } + + //Check end point for halt/stall. + if(Adapter->bEndPointHalted == TRUE) + { + Bcm_clear_halt_of_endpoints(Adapter); + Adapter->bEndPointHalted = FALSE; + StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); + } + + if(Adapter->LinkUpStatus && !Adapter->IdleMode) + { + if(atomic_read(&Adapter->TotalPacketCount)) + { + update_per_sf_desc_cnts(Adapter); + } + } +#endif + + if( atomic_read(&Adapter->CurrNumFreeTxDesc) && + Adapter->LinkStatus == SYNC_UP_REQUEST && + !Adapter->bSyncUpRequestSent) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage"); + LinkMessage(Adapter); + } + + if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up"); + Adapter->usIdleModePattern = ABORT_IDLE_MODE; + Adapter->bWakeUpDevice = TRUE; + wake_up(&Adapter->process_rx_cntrlpkt); + } + +#ifdef BCM_SHM_INTERFACE + spin_lock_bh(&Adapter->txtransmitlock); + if(Adapter->txtransmit_running == 0) + { + Adapter->txtransmit_running = 1; + calltransmit = 1; + } + else + calltransmit = 0; + spin_unlock_bh(&Adapter->txtransmitlock); +#endif + + if(calltransmit) + transmit_packets(Adapter); + + atomic_set(&Adapter->TxPktAvail, 0); + } + return 0; +} + +#ifdef BCM_SHM_INTERFACE +extern PMINI_ADAPTER psAdaptertest; +void virtual_mail_box_interrupt(void) +{ + +#ifndef GDMA_INTERFACE + PUINT ptr = (PUINT)CPE_VIRTUAL_MAILBOX_REG; + UINT intval = (UINT)((*ptr & 0xFF00) >> 8); + if (intval != 0) + { + atomic_set(&psAdaptertest->CurrNumFreeTxDesc, intval); + atomic_set (&psAdaptertest->uiMBupdate, TRUE); + + //make it to 0 + *ptr = *ptr & 0xffff00ff; + } +#endif +} +unsigned int total_tx_pkts_pending(void) +{ + return atomic_read(&psAdaptertest->TotalPacketCount); +} + +#endif + + diff --git a/drivers/staging/bcm/Typedefs.h b/drivers/staging/bcm/Typedefs.h new file mode 100644 index 0000000..a985abf --- /dev/null +++ b/drivers/staging/bcm/Typedefs.h @@ -0,0 +1,47 @@ +/**************************** +* Typedefs.h +****************************/ +#ifndef __TYPEDEFS_H__ +#define __TYPEDEFS_H__ +#define STATUS_SUCCESS 0 +#define STATUS_FAILURE -1 + +#define FALSE 0 +#define TRUE 1 + +typedef char BOOLEAN; +typedef char CHAR; +typedef int INT; +typedef short SHORT; +typedef long LONG; +typedef void VOID; + +typedef unsigned char UCHAR; +typedef unsigned char B_UINT8; +typedef unsigned short USHORT; +typedef unsigned short B_UINT16; +typedef unsigned int UINT; +typedef unsigned int B_UINT32; +typedef unsigned long ULONG; +typedef unsigned long DWORD; + +typedef char* PCHAR; +typedef short* PSHORT; +typedef int* PINT; +typedef long* PLONG; +typedef void* PVOID; + +typedef unsigned char* PUCHAR; +typedef unsigned short* PUSHORT; +typedef unsigned int* PUINT; +typedef unsigned long* PULONG; +typedef unsigned long long ULONG64; +typedef unsigned long long LARGE_INTEGER; +typedef unsigned int UINT32; +#ifndef NULL +#define NULL 0 +#endif + + +#endif //__TYPEDEFS_H__ + diff --git a/drivers/staging/bcm/Version.h b/drivers/staging/bcm/Version.h new file mode 100644 index 0000000..a07b956 --- /dev/null +++ b/drivers/staging/bcm/Version.h @@ -0,0 +1,35 @@ + +/*Copyright (c) 2005 Beceem Communications Inc. + +Module Name: + + Version.h + +Abstract: + + +--*/ + +#ifndef VERSION_H +#define VERSION_H + + +#define VER_FILETYPE VFT_DRV +#define VER_FILESUBTYPE VFT2_DRV_NETWORK + + +#define VER_FILEVERSION 5.2.45 +#define VER_FILEVERSION_STR "5.2.45" + +#undef VER_PRODUCTVERSION +#define VER_PRODUCTVERSION VER_FILEVERSION + +#undef VER_PRODUCTVERSION_STR +#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR + + + + +//#include "common.ver" + +#endif //VERSION_H diff --git a/drivers/staging/bcm/cntrl_SignalingInterface.h b/drivers/staging/bcm/cntrl_SignalingInterface.h new file mode 100644 index 0000000..4cbe300 --- /dev/null +++ b/drivers/staging/bcm/cntrl_SignalingInterface.h @@ -0,0 +1,677 @@ +#ifndef CNTRL_SIGNALING_INTERFACE_ +#define CNTRL_SIGNALING_INTERFACE_ + + +#ifdef BECEEM_TARGET + +#include +#include +#include +#include +#include +using namespace Beceem; +#ifdef ENABLE_CORRIGENDUM2_UPDATE +extern B_UINT32 g_u32Corr2MacFlags; +#endif + +#else + + +#define DSA_REQ 11 +#define DSA_RSP 12 +#define DSA_ACK 13 +#define DSC_REQ 14 +#define DSC_RSP 15 +#define DSC_ACK 16 +#define DSD_REQ 17 +#define DSD_RSP 18 +#define DSD_ACK 19 +#define MAX_CLASSIFIERS_IN_SF 4 + +#endif + +#define MAX_STRING_LEN 20 +#define MAX_PHS_LENGTHS 255 +#define VENDOR_PHS_PARAM_LENGTH 10 +#define MAX_NUM_ACTIVE_BS 10 +#define AUTH_TOKEN_LENGTH 10 +#define NUM_HARQ_CHANNELS 16 //Changed from 10 to 16 to accomodate all HARQ channels +#define VENDOR_CLASSIFIER_PARAM_LENGTH 1 //Changed the size to 1 byte since we dnt use it +#define VENDOR_SPECIF_QOS_PARAM 1 +#define VENDOR_PHS_PARAM_LENGTH 10 +#define MBS_CONTENTS_ID_LENGTH 10 +#define GLOBAL_SF_CLASSNAME_LENGTH 6 + +#define TYPE_OF_SERVICE_LENGTH 3 +#define IP_MASKED_SRC_ADDRESS_LENGTH 32 +#define IP_MASKED_DEST_ADDRESS_LENGTH 32 +#define PROTOCOL_SRC_PORT_RANGE_LENGTH 4 +#define PROTOCOL_DEST_PORT_RANGE_LENGTH 4 +#define ETHERNET_DEST_MAC_ADDR_LENGTH 12 +#define ETHERNET_SRC_MAC_ADDR_LENGTH 12 +#define NUM_ETHERTYPE_BYTES 3 +#define NUM_IPV6_FLOWLABLE_BYTES 3 + + +//////////////////////////////////////////////////////////////////////////////// +////////////////////////structure Definitions/////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/// \brief class cCPacketClassificationRule +#ifdef BECEEM_TARGET +class CCPacketClassificationRuleSI{ + public: + /// \brief Constructor for the class + CCPacketClassificationRuleSI(): + u8ClassifierRulePriority(mClassifierRulePriority), + u8IPTypeOfServiceLength(mIPTypeOfService), + u8Protocol(mProtocol), + u8IPMaskedSourceAddressLength(0), + u8IPDestinationAddressLength(0), + u8ProtocolSourcePortRangeLength(0), + u8ProtocolDestPortRangeLength(0), + u8EthernetDestMacAddressLength(0), + u8EthernetSourceMACAddressLength(0), + u8EthertypeLength(0), + u16UserPriority(mUserPriority), + u16VLANID(mVLANID), + u8AssociatedPHSI(mAssociatedPHSI), + u16PacketClassificationRuleIndex(mPacketClassifierRuleIndex), + u8VendorSpecificClassifierParamLength(mVendorSpecificClassifierParamLength), + u8IPv6FlowLableLength(mIPv6FlowLableLength), + u8ClassifierActionRule(mClassifierActionRule) + + {} + void Reset() + { + CCPacketClassificationRuleSI(); + } +#else +struct _stCPacketClassificationRuleSI{ +#endif + + /** 16bit UserPriority Of The Service Flow*/ + B_UINT16 u16UserPriority; + /** 16bit VLANID Of The Service Flow*/ + B_UINT16 u16VLANID; + /** 16bit Packet Classification RuleIndex Of The Service Flow*/ + B_UINT16 u16PacketClassificationRuleIndex; + /** 8bit Classifier Rule Priority Of The Service Flow*/ + B_UINT8 u8ClassifierRulePriority; + /** Length of IP TypeOfService field*/ + B_UINT8 u8IPTypeOfServiceLength; + /** 3bytes IP TypeOfService */ + B_UINT8 u8IPTypeOfService[TYPE_OF_SERVICE_LENGTH]; + /** Protocol used in classification of Service Flow*/ + B_UINT8 u8Protocol; + /** Length of IP Masked Source Address */ + B_UINT8 u8IPMaskedSourceAddressLength; + /** IP Masked Source Address used in classification for the Service Flow*/ + B_UINT8 u8IPMaskedSourceAddress[IP_MASKED_SRC_ADDRESS_LENGTH]; + /** Length of IP Destination Address */ + B_UINT8 u8IPDestinationAddressLength; + /** IP Destination Address used in classification for the Service Flow*/ + B_UINT8 u8IPDestinationAddress[IP_MASKED_DEST_ADDRESS_LENGTH]; + /** Length of Protocol Source Port Range */ + B_UINT8 u8ProtocolSourcePortRangeLength; + /** Protocol Source Port Range used in the Service Flow*/ + B_UINT8 u8ProtocolSourcePortRange[PROTOCOL_SRC_PORT_RANGE_LENGTH]; + /** Length of Protocol Dest Port Range */ + B_UINT8 u8ProtocolDestPortRangeLength; + /** Protocol Dest Port Range used in the Service Flow*/ + B_UINT8 u8ProtocolDestPortRange[PROTOCOL_DEST_PORT_RANGE_LENGTH]; + /** Length of Ethernet Destination MAC Address */ + B_UINT8 u8EthernetDestMacAddressLength; + /** Ethernet Destination MAC Address used in classification of the Service Flow*/ + B_UINT8 u8EthernetDestMacAddress[ETHERNET_DEST_MAC_ADDR_LENGTH]; + /** Length of Ethernet Source MAC Address */ + B_UINT8 u8EthernetSourceMACAddressLength; + /** Ethernet Source MAC Address used in classification of the Service Flow*/ + B_UINT8 u8EthernetSourceMACAddress[ETHERNET_SRC_MAC_ADDR_LENGTH]; + /** Length of Ethertype */ + B_UINT8 u8EthertypeLength; + /** 3bytes Ethertype Of The Service Flow*/ + B_UINT8 u8Ethertype[NUM_ETHERTYPE_BYTES]; + /** 8bit Associated PHSI Of The Service Flow*/ + B_UINT8 u8AssociatedPHSI; + /** Length of Vendor Specific Classifier Param length Of The Service Flow*/ + B_UINT8 u8VendorSpecificClassifierParamLength; + /** Vendor Specific Classifier Param Of The Service Flow*/ + B_UINT8 u8VendorSpecificClassifierParam[VENDOR_CLASSIFIER_PARAM_LENGTH]; + /** Length Of IPv6 Flow Lable of the Service Flow*/ + B_UINT8 u8IPv6FlowLableLength; + /** IPv6 Flow Lable Of The Service Flow*/ + B_UINT8 u8IPv6FlowLable[NUM_IPV6_FLOWLABLE_BYTES]; + /** Action associated with the classifier rule*/ + B_UINT8 u8ClassifierActionRule; + B_UINT16 u16ValidityBitMap; +}; +#ifndef BECEEM_TARGET +typedef struct _stCPacketClassificationRuleSI CCPacketClassificationRuleSI,stCPacketClassificationRuleSI, *pstCPacketClassificationRuleSI; +#endif + +/// \brief class CPhsRuleSI +#ifdef BECEEM_TARGET +class CPhsRuleSI{ + public: + /// \brief Constructor for the class + CPhsRuleSI(): + u8PHSI(mPHSI), + u8PHSFLength(0), + u8PHSMLength(0), + u8PHSS(mPHSS), + u8PHSV(mPHSV), + u8VendorSpecificPHSParamsLength(mVendorSpecificPHSParamLength){} + void Reset() + { + CPhsRuleSI(); + } +#else +typedef struct _stPhsRuleSI { +#endif + /** 8bit PHS Index Of The Service Flow*/ + B_UINT8 u8PHSI; + /** PHSF Length Of The Service Flow*/ + B_UINT8 u8PHSFLength; + /** String of bytes containing header information to be supressed by the sending CS and reconstructed by the receiving CS*/ + B_UINT8 u8PHSF[MAX_PHS_LENGTHS]; + /** PHSM Length Of The Service Flow*/ + B_UINT8 u8PHSMLength; + /** PHS Mask for the SF*/ + B_UINT8 u8PHSM[MAX_PHS_LENGTHS]; + /** 8bit Total number of bytes to be supressed for the Service Flow*/ + B_UINT8 u8PHSS; + /** 8bit Indicates whether or not Packet Header contents need to be verified prior to supression */ + B_UINT8 u8PHSV; + /** Vendor Specific PHS param Length Of The Service Flow*/ + B_UINT8 u8VendorSpecificPHSParamsLength; + /** Vendor Specific PHS param Of The Service Flow*/ + B_UINT8 u8VendorSpecificPHSParams[VENDOR_PHS_PARAM_LENGTH]; + + B_UINT8 u8Padding[2]; +#ifdef BECEEM_TARGET +}; +#else +}stPhsRuleSI,*pstPhsRuleSI; +typedef stPhsRuleSI CPhsRuleSI; +#endif + +/// \brief structure cConvergenceSLTypes +#ifdef BECEEM_TARGET +class CConvergenceSLTypes{ + public: + /// \brief Constructor for the class + CConvergenceSLTypes(): + u8ClassfierDSCAction(mClassifierDSCAction), + u8PhsDSCAction (mPhsDSCAction) + {} + void Reset() + { + CConvergenceSLTypes(); + cCPacketClassificationRule.Reset(); + cPhsRule.Reset(); + } +#else +struct _stConvergenceSLTypes{ +#endif + /** 8bit Phs Classfier Action Of The Service Flow*/ + B_UINT8 u8ClassfierDSCAction; + /** 8bit Phs DSC Action Of The Service Flow*/ + B_UINT8 u8PhsDSCAction; + /** 16bit Padding */ + B_UINT8 u8Padding[2]; + /// \brief class cCPacketClassificationRule +#ifdef BECEEM_TARGET + CCPacketClassificationRuleSI cCPacketClassificationRule; +#else + stCPacketClassificationRuleSI cCPacketClassificationRule; +#endif + /// \brief class CPhsRuleSI +#ifdef BECEEM_TARGET + CPhsRuleSI cPhsRule; +#else + struct _stPhsRuleSI cPhsRule; +#endif +}; +#ifndef BECEEM_TARGET +typedef struct _stConvergenceSLTypes stConvergenceSLTypes,CConvergenceSLTypes, *pstConvergenceSLTypes; +#endif + + +/// \brief structure CServiceFlowParamSI +#ifdef BECEEM_TARGET +class CServiceFlowParamSI{ + public: + /// \brief Constructor for the class + CServiceFlowParamSI(): + u32SFID(mSFid), + u16CID(mCid), + u8ServiceClassNameLength(mServiceClassNameLength), + u8MBSService(mMBSService), + u8QosParamSet(mQosParamSetType), + u8TrafficPriority(mTrafficPriority), + u32MaxSustainedTrafficRate(mMaximumSustainedTrafficRate), + u32MaxTrafficBurst(mMaximumTrafficBurst), + u32MinReservedTrafficRate(mMinimumReservedTrafficRate), + u8ServiceFlowSchedulingType(mServiceFlowSchedulingType), + u8RequesttransmissionPolicy(mRequestTransmissionPolicy), + u32ToleratedJitter(mToleratedJitter), + u32MaximumLatency(mMaximumLatency), + u8FixedLengthVSVariableLengthSDUIndicator + (mFixedLengthVSVariableLength), + u8SDUSize(mSDUSize), + u16TargetSAID(mTargetSAID), + u8ARQEnable(mARQEnable), + u16ARQWindowSize(mARQWindowSize), + u16ARQBlockLifeTime(mARQBlockLifeTime), + u16ARQSyncLossTimeOut(mARQSyncLossTimeOut), + u8ARQDeliverInOrder(mARQDeliverInOrder), + u16ARQRxPurgeTimeOut(mARQRXPurgeTimeOut), + //Add ARQ BLOCK SIZE, ARQ TX and RX delay initializations here + //after we move to only CORR2 + u8RxARQAckProcessingTime(mRxARQAckProcessingTime), + u8CSSpecification(mCSSpecification), + u8TypeOfDataDeliveryService(mTypeOfDataDeliveryService), + u16SDUInterArrivalTime(mSDUInterArrivalTime), + u16TimeBase(mTimeBase), + u8PagingPreference(mPagingPreference), + u8MBSZoneIdentifierassignment(mMBSZoneIdentifierassignmentLength), + u8TrafficIndicationPreference(mTrafficIndicationPreference), + u8GlobalServicesClassNameLength(mGlobalServicesClassNameLength), + u8SNFeedbackEnabled(mSNFeedbackEnabled), + u8FSNSize(mFSNSize), + u8CIDAllocation4activeBSsLength(mCIDAllocation4activeBSsLength), + u16UnsolicitedGrantInterval(mUnsolicitedGrantInterval), + u16UnsolicitedPollingInterval(mUnsolicitedPollingInterval), + u8PDUSNExtendedSubheader4HarqReordering(mPDUSNExtendedSubheader4HarqReordering), + u8MBSContentsIDLength(mMBSContentsIDLength), + u8HARQServiceFlows(mHARQServiceFlows), + u8AuthTokenLength(mAuthTokenLength), + u8HarqChannelMappingLength(mHarqChannelMappingLength), + u8VendorSpecificQoSParamLength(mVendorSpecificQoSParamLength), + bValid(FALSE), + u8TotalClassifiers() +{ +//Remove the bolck after we move to Corr2 only code +#ifdef ENABLE_CORRIGENDUM2_UPDATE + if((g_u32Corr2MacFlags & CORR_2_DSX) || (g_u32Corr2MacFlags & CORR_2_ARQ)) + { + /* IEEE Comment #627 / MTG Comment #426 */ + u16ARQBlockSize = mARQBlockSize; + if(g_u32Corr2MacFlags & CORR_2_ARQ) { + u16ARQRetryTxTimeOut = mARQRetryTimeOutTxDelay; + if(g_u32VENDOR_TYPE == VENDOR_ALCATEL) { + u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelay_ALU; + } else { + u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelay; + } + } + else + { + u16ARQRetryTxTimeOut = mARQRetryTimeOutTxDelayCorr1; + u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelayCorr1; + } + } + else +#endif + { + u16ARQBlockSize = mARQBlockSizeCorr1; + u16ARQRetryTxTimeOut = mARQRetryTimeOutTxDelayCorr1; + u16ARQRetryRxTimeOut = mARQRetryTimeOutRxDelayCorr1; + } +} + + void ComputeMacOverhead(B_UINT8 u8SecOvrhead); + B_UINT16 GetMacOverhead() { return u16MacOverhead; } +#else +typedef struct _stServiceFlowParamSI{ +#endif //end of ifdef BECEEM_TARGET + + /** 32bitSFID Of The Service Flow*/ + B_UINT32 u32SFID; + + /** 32bit Maximum Sustained Traffic Rate of the Service Flow*/ + B_UINT32 u32MaxSustainedTrafficRate; + + /** 32bit Maximum Traffic Burst allowed for the Service Flow*/ + B_UINT32 u32MaxTrafficBurst; + + /** 32bit Minimum Reserved Traffic Rate of the Service Flow*/ + B_UINT32 u32MinReservedTrafficRate; + + /** 32bit Tolerated Jitter of the Service Flow*/ + B_UINT32 u32ToleratedJitter; + + /** 32bit Maximum Latency of the Service Flow*/ + B_UINT32 u32MaximumLatency; + + /** 16bitCID Of The Service Flow*/ + B_UINT16 u16CID; + + /** 16bit SAID on which the service flow being set up shall be mapped*/ + B_UINT16 u16TargetSAID; + + /** 16bit ARQ window size negotiated*/ + B_UINT16 u16ARQWindowSize; + + /** 16bit Total Tx delay incl sending, receiving & processing delays */ + B_UINT16 u16ARQRetryTxTimeOut; + + /** 16bit Total Rx delay incl sending, receiving & processing delays */ + B_UINT16 u16ARQRetryRxTimeOut; + + /** 16bit ARQ block lifetime */ + B_UINT16 u16ARQBlockLifeTime; + + /** 16bit ARQ Sync loss timeout*/ + B_UINT16 u16ARQSyncLossTimeOut; + + /** 16bit ARQ Purge timeout */ + B_UINT16 u16ARQRxPurgeTimeOut; +#if 0 //def ENABLE_CORRIGENDUM2_UPDATE +/* IEEE Comment #627 / MTG Comment #426 */ + /// \brief Size of an ARQ block, changed from 2 bytes to 1 + B_UINT8 u8ARQBlockSize; +#endif +//TODO::Remove this once we move to a new CORR2 driver + /// \brief Size of an ARQ block + B_UINT16 u16ARQBlockSize; + +//#endif + /** 16bit Nominal interval b/w consecutive SDU arrivals at MAC SAP*/ + B_UINT16 u16SDUInterArrivalTime; + + /** 16bit Specifies the time base for rate measurement */ + B_UINT16 u16TimeBase; + + /** 16bit Interval b/w Successive Grant oppurtunities*/ + B_UINT16 u16UnsolicitedGrantInterval; + + /** 16bit Interval b/w Successive Polling grant oppurtunities*/ + B_UINT16 u16UnsolicitedPollingInterval; + + /** internal var to get the overhead */ + B_UINT16 u16MacOverhead; + + /** MBS contents Identifier*/ + B_UINT16 u16MBSContentsID[MBS_CONTENTS_ID_LENGTH]; + + /** MBS contents Identifier length*/ + B_UINT8 u8MBSContentsIDLength; + + /** ServiceClassName Length Of The Service Flow*/ + B_UINT8 u8ServiceClassNameLength; + + /** 32bytes ServiceClassName Of The Service Flow*/ + B_UINT8 u8ServiceClassName[32]; + + /** 8bit Indicates whether or not MBS service is requested for this Serivce Flow*/ + B_UINT8 u8MBSService; + + /** 8bit QOS Parameter Set specifies proper application of QoS paramters to Provisioned, Admitted and Active sets*/ + B_UINT8 u8QosParamSet; + + /** 8bit Traffic Priority Of the Service Flow */ + B_UINT8 u8TrafficPriority; + + /** 8bit Uplink Grant Scheduling Type of The Service Flow */ + B_UINT8 u8ServiceFlowSchedulingType; + + /** 8bit Request transmission Policy of the Service Flow*/ + B_UINT8 u8RequesttransmissionPolicy; + + /** 8bit Specifies whether SDUs for this Service flow are of FixedLength or Variable length */ + B_UINT8 u8FixedLengthVSVariableLengthSDUIndicator; + + /** 8bit Length of the SDU for a fixed length SDU service flow*/ + B_UINT8 u8SDUSize; + + /** 8bit Indicates whether or not ARQ is requested for this connection*/ + B_UINT8 u8ARQEnable; + + /**< 8bit Indicates whether or not data has tobe delivered in order to higher layer*/ + B_UINT8 u8ARQDeliverInOrder; + + /** 8bit Receiver ARQ ACK processing time */ + B_UINT8 u8RxARQAckProcessingTime; + + /** 8bit Convergence Sublayer Specification Of The Service Flow*/ + B_UINT8 u8CSSpecification; + + /** 8 bit Type of data delivery service*/ + B_UINT8 u8TypeOfDataDeliveryService; + + /** 8bit Specifies whether a service flow may generate Paging */ + B_UINT8 u8PagingPreference; + + /** 8bit Indicates the MBS Zone through which the connection or virtual connection is valid */ + B_UINT8 u8MBSZoneIdentifierassignment; + + /** 8bit Specifies whether traffic on SF should generate MOB_TRF_IND to MS in sleep mode*/ + B_UINT8 u8TrafficIndicationPreference; + + /** 8bit Speciifes the length of predefined Global QoS parameter set encoding for this SF */ + B_UINT8 u8GlobalServicesClassNameLength; + + /** 6 byte Speciifes the predefined Global QoS parameter set encoding for this SF */ + B_UINT8 u8GlobalServicesClassName[GLOBAL_SF_CLASSNAME_LENGTH]; + + /** 8bit Indicates whether or not SN feedback is enabled for the conn */ + B_UINT8 u8SNFeedbackEnabled; + + /** Indicates the size of the Fragment Sequence Number for the connection */ + B_UINT8 u8FSNSize; + + /** 8bit Number of CIDs in active BS list */ + B_UINT8 u8CIDAllocation4activeBSsLength; + + /** CIDs of BS in the active list */ + B_UINT8 u8CIDAllocation4activeBSs[MAX_NUM_ACTIVE_BS]; + + /** Specifies if PDU extended subheader should be applied on every PDU on this conn*/ + B_UINT8 u8PDUSNExtendedSubheader4HarqReordering; + + /** 8bit Specifies whether the connection uses HARQ or not */ + B_UINT8 u8HARQServiceFlows; + + /** Specifies the length of Authorization token*/ + B_UINT8 u8AuthTokenLength; + + /** Specifies the Authorization token*/ + B_UINT8 u8AuthToken[AUTH_TOKEN_LENGTH]; + + /** specifes Number of HARQ channels used to carry data length*/ + B_UINT8 u8HarqChannelMappingLength; + + /** specifes HARQ channels used to carry data*/ + B_UINT8 u8HARQChannelMapping[NUM_HARQ_CHANNELS]; + + /** 8bit Length of Vendor Specific QoS Params */ + B_UINT8 u8VendorSpecificQoSParamLength; + + /** 1byte Vendor Specific QoS Param Of The Service Flow*/ + B_UINT8 u8VendorSpecificQoSParam[VENDOR_SPECIF_QOS_PARAM]; + + // indicates total classifiers in the SF + B_UINT8 u8TotalClassifiers; /**< Total number of valid classifiers*/ + B_UINT8 bValid; /**< Validity flag */ + B_UINT8 u8Padding; /**< Padding byte*/ + +#ifdef BECEEM_TARGET +/** +Structure for Convergence SubLayer Types with a maximum of 4 classifiers +*/ + CConvergenceSLTypes cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF]; +#else +/** +Structure for Convergence SubLayer Types with a maximum of 4 classifiers +*/ + stConvergenceSLTypes cConvergenceSLTypes[MAX_CLASSIFIERS_IN_SF]; +#endif + +#ifdef BECEEM_TARGET +}; +#else +} stServiceFlowParamSI, *pstServiceFlowParamSI; +typedef stServiceFlowParamSI CServiceFlowParamSI; +#endif + +/** +structure stLocalSFAddRequest +*/ +typedef struct _stLocalSFAddRequest{ +#ifdef BECEEM_TARGET + _stLocalSFAddRequest( ) : + u8Type(0x00), eConnectionDir(0x00), + u16TID(0x0000), u16CID(0x0000), u16VCID(0x0000) + {} +#endif + + B_UINT8 u8Type; /**< Type*/ + B_UINT8 eConnectionDir; /**< Connection direction*/ + /// \brief 16 bit TID + B_UINT16 u16TID; /**< 16bit TID*/ + /// \brief 16bitCID + B_UINT16 u16CID; /**< 16bit CID*/ + /// \brief 16bitVCID + B_UINT16 u16VCID; /**< 16bit VCID*/ + /// \brief structure ParameterSet +#ifdef BECEEM_SIGNALLING_INTERFACE_API + CServiceFlowParamSI sfParameterSet; +#endif + +#ifdef BECEEM_TARGET + CServiceFlowParamSI *psfParameterSet; +#else + stServiceFlowParamSI *psfParameterSet; /**< structure ParameterSet*/ +#endif + +#ifdef USING_VXWORKS + USE_DATA_MEMORY_MANAGER(); +#endif +}stLocalSFAddRequest, *pstLocalSFAddRequest; + + +/** +structure stLocalSFAddIndication +*/ +typedef struct _stLocalSFAddIndication{ +#ifdef BECEEM_TARGET + _stLocalSFAddIndication( ) : + u8Type(0x00), eConnectionDir(0x00), + u16TID(0x0000), u16CID(0x0000), u16VCID(0x0000) + {} +#endif + + B_UINT8 u8Type; /**< Type*/ + B_UINT8 eConnectionDir; /**< Connection Direction*/ + /// \brief 16 bit TID + B_UINT16 u16TID; /**< TID*/ + /// \brief 16bitCID + B_UINT16 u16CID; /**< 16bitCID*/ + /// \brief 16bitVCID + B_UINT16 u16VCID; /**< 16bitVCID*/ + +#ifdef BECEEM_SIGNALLING_INTERFACE_API + CServiceFlowParamSI sfAuthorizedSet; + /// \brief structure AdmittedSet + CServiceFlowParamSI sfAdmittedSet; + /// \brief structure ActiveSet + CServiceFlowParamSI sfActiveSet; +#endif + + /// \brief structure AuthorizedSet +#ifdef BECEEM_TARGET + CServiceFlowParamSI *psfAuthorizedSet; + /// \brief structure AdmittedSet + CServiceFlowParamSI *psfAdmittedSet; + /// \brief structure ActiveSet + CServiceFlowParamSI *psfActiveSet; +#else + /// \brief structure AuthorizedSet + stServiceFlowParamSI *psfAuthorizedSet; /**< AuthorizedSet of type stServiceFlowParamSI*/ + /// \brief structure AdmittedSet + stServiceFlowParamSI *psfAdmittedSet; /**< AdmittedSet of type stServiceFlowParamSI*/ + /// \brief structure ActiveSet + stServiceFlowParamSI *psfActiveSet; /**< sfActiveSet of type stServiceFlowParamSI*/ +#endif + B_UINT8 u8CC; /**< Confirmation Code*/ + B_UINT8 u8Padd; /**< 8-bit Padding */ + + B_UINT16 u16Padd; /**< 16 bit Padding */ + +#ifdef USING_VXWORKS + USE_DATA_MEMORY_MANAGER(); +#endif +}stLocalSFAddIndication; + + +typedef struct _stLocalSFAddIndication *pstLocalSFAddIndication; +/** +structure stLocalSFChangeRequest is same as structure stLocalSFAddIndication +*/ +typedef struct _stLocalSFAddIndication stLocalSFChangeRequest, *pstLocalSFChangeRequest; +/** +structure stLocalSFChangeIndication is same as structure stLocalSFAddIndication +*/ +typedef struct _stLocalSFAddIndication stLocalSFChangeIndication, *pstLocalSFChangeIndication; + +/** +structure stLocalSFDeleteRequest +*/ +typedef struct _stLocalSFDeleteRequest{ +#ifdef BECEEM_TARGET + _stLocalSFDeleteRequest( ) : + u8Type(0x00), u8Padding(0x00), + u16TID(0x0000), u32SFID (0x00000000) + {} +#endif + B_UINT8 u8Type; /**< Type*/ + B_UINT8 u8Padding; /**< Padding byte*/ + B_UINT16 u16TID; /**< TID*/ + /// \brief 32bitSFID + B_UINT32 u32SFID; /**< SFID*/ +#ifdef USING_VXWORKS + USE_DATA_MEMORY_MANAGER(); +#endif +}stLocalSFDeleteRequest, *pstLocalSFDeleteRequest; + +/** +structure stLocalSFDeleteIndication +*/ +typedef struct stLocalSFDeleteIndication{ +#ifdef BECEEM_TARGET + stLocalSFDeleteIndication( ) : + u8Type(0x00), u8Padding(0x00), + u16TID(0x0000), u16CID(0x0000), + u16VCID(0x0000),u32SFID (0x00000000) + {} +#endif + B_UINT8 u8Type; /**< Type */ + B_UINT8 u8Padding; /**< Padding */ + B_UINT16 u16TID; /**< TID */ + /// \brief 16bitCID + B_UINT16 u16CID; /**< CID */ + /// \brief 16bitVCID + B_UINT16 u16VCID; /**< VCID */ + /// \brief 32bitSFID + B_UINT32 u32SFID; /**< SFID */ + /// \brief 8bit Confirmation code + B_UINT8 u8ConfirmationCode; /**< Confirmation code */ + B_UINT8 u8Padding1[3]; /**< 3 byte Padding */ +#ifdef USING_VXWORKS + USE_DATA_MEMORY_MANAGER(); +#endif +}stLocalSFDeleteIndication; + +typedef struct _stIM_SFHostNotify +{ + B_UINT32 SFID; //SFID of the service flow + B_UINT16 newCID; //the new/changed CID + B_UINT16 VCID; //Get new Vcid if the flow has been made active in CID update TLV, but was inactive earlier or the orig vcid + B_UINT8 RetainSF; //Indication to Host if the SF is to be retained or deleted; if TRUE-retain else delete + B_UINT8 QoSParamSet; //QoS paramset of the retained SF + B_UINT16 u16reserved; //For byte alignment + +} stIM_SFHostNotify; + +#endif diff --git a/drivers/staging/bcm/headers.h b/drivers/staging/bcm/headers.h new file mode 100644 index 0000000..9d4e3ac --- /dev/null +++ b/drivers/staging/bcm/headers.h @@ -0,0 +1,109 @@ + +/******************************************************************* +* Headers.h +*******************************************************************/ +#ifndef __HEADERS_H__ +#define __HEADERS_H__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) +#include +#endif +#include +#include +#ifndef BCM_SHM_INTERFACE +#include +#endif +#ifdef BECEEM_TARGET + +#include +#include +#include +#include +#include +using namespace Beceem; +#ifdef ENABLE_CORRIGENDUM2_UPDATE +extern B_UINT32 g_u32Corr2MacFlags; +#endif +#endif + +#include "Typedefs.h" +#include "Version.h" +#include "Macros.h" +#include "HostMIBSInterface.h" +#include "cntrl_SignalingInterface.h" +#include "PHSDefines.h" +#include "led_control.h" +#include "Ioctl.h" +#include "nvm.h" +#include "target_params.h" +#include "Adapter.h" +#include "CmHost.h" +#include "DDRInit.h" +#include "Debug.h" +#include "HostMibs.h" +#include "IPv6ProtocolHdr.h" +#include "osal_misc.h" +#include "PHSModule.h" +#include "Protocol.h" +#include "Prototypes.h" +#include "Queue.h" +#include "vendorspecificextn.h" + +#ifndef BCM_SHM_INTERFACE + +#include "InterfaceMacros.h" +#include "InterfaceAdapter.h" +#include "InterfaceIsr.h" +#include "Interfacemain.h" +#include "InterfaceMisc.h" +#include "InterfaceRx.h" +#include "InterfaceTx.h" +#endif +#include "InterfaceIdleMode.h" +#include "InterfaceInit.h" + +#ifdef BCM_SHM_INTERFACE +#include + +#ifdef GDMA_INTERFACE +#include "GdmaInterface.h" +#include "symphony.h" +#else +#include "virtual_interface.h" + +#endif + +#endif + +#endif diff --git a/drivers/staging/bcm/hostmibs.c b/drivers/staging/bcm/hostmibs.c new file mode 100644 index 0000000..e9da513 --- /dev/null +++ b/drivers/staging/bcm/hostmibs.c @@ -0,0 +1,164 @@ + +/* + * File Name: hostmibs.c + * + * Author: Beceem Communications Pvt. Ltd + * + * Abstract: This file contains the routines to copy the statistics used by + * the driver to the Host MIBS structure and giving the same to Application. + * + */ +#include "headers.h" + +INT ProcessGetHostMibs(PMINI_ADAPTER Adapter, + PVOID ioBuffer, + ULONG inputBufferLength) +{ + + S_MIBS_HOST_STATS_MIBS *pstHostMibs = NULL; + S_SERVICEFLOW_ENTRY *pstServiceFlowEntry = NULL; + S_PHS_RULE *pstPhsRule = NULL; + S_CLASSIFIER_TABLE *pstClassifierTable = NULL; + S_CLASSIFIER_ENTRY *pstClassifierRule = NULL; + PPHS_DEVICE_EXTENSION pDeviceExtension = (PPHS_DEVICE_EXTENSION)&Adapter->stBCMPhsContext; + + UINT nClassifierIndex = 0, nPhsTableIndex = 0,nSfIndex = 0, uiIndex = 0; + + if(pDeviceExtension == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, HOST_MIBS, DBG_LVL_ALL, "Invalid Device Extension\n"); + return STATUS_FAILURE; + } + + if(ioBuffer == NULL) + { + return -EINVAL; + } + memset(ioBuffer,0,sizeof(S_MIBS_HOST_STATS_MIBS)); + + pstHostMibs = (S_MIBS_HOST_STATS_MIBS *)ioBuffer; + + + //Copy the classifier Table + for(nClassifierIndex=0; nClassifierIndex < MAX_CLASSIFIERS; + nClassifierIndex++) + { + if(Adapter->astClassifierTable[nClassifierIndex].bUsed == TRUE) + memcpy((PVOID)&pstHostMibs->astClassifierTable[nClassifierIndex], + (PVOID)&Adapter->astClassifierTable[nClassifierIndex], + sizeof(S_MIBS_CLASSIFIER_RULE)); + } + + //Copy the SF Table + for(nSfIndex=0; nSfIndex < NO_OF_QUEUES ; nSfIndex++) + { + if(Adapter->PackInfo[nSfIndex].bValid) + { + OsalMemMove((PVOID)&pstHostMibs->astSFtable[nSfIndex],(PVOID)&Adapter->PackInfo[nSfIndex],sizeof(S_MIBS_SERVICEFLOW_TABLE)); + } + else + { + //if index in not valid, don't process this for the PHS table. Go For the next entry. + continue ; + } + + //Retrieve the SFID Entry Index for requested Service Flow + if(PHS_INVALID_TABLE_INDEX == GetServiceFlowEntry(pDeviceExtension->pstServiceFlowPhsRulesTable, + Adapter->PackInfo[nSfIndex].usVCID_Value ,&pstServiceFlowEntry)) + { + + continue; + } + + pstClassifierTable = pstServiceFlowEntry->pstClassifierTable; + + + for(uiIndex = 0; uiIndex < MAX_PHSRULE_PER_SF; uiIndex++) + { + pstClassifierRule = &pstClassifierTable->stActivePhsRulesList[uiIndex]; + + if(pstClassifierRule->bUsed) + { + pstPhsRule = pstClassifierRule->pstPhsRule; + + pstHostMibs->astPhsRulesTable[nPhsTableIndex].ulSFID = Adapter->PackInfo[nSfIndex].ulSFID; + + OsalMemMove(&pstHostMibs->astPhsRulesTable[nPhsTableIndex].u8PHSI, + &pstPhsRule->u8PHSI, + sizeof(S_PHS_RULE)); + nPhsTableIndex++; + + } + + } + + } + + + + //copy other Host Statistics parameters + pstHostMibs->stHostInfo.GoodTransmits = + atomic_read(&Adapter->TxTotalPacketCount); + pstHostMibs->stHostInfo.GoodReceives = + atomic_read(&Adapter->GoodRxPktCount); + pstHostMibs->stHostInfo.CurrNumFreeDesc = + atomic_read(&Adapter->CurrNumFreeTxDesc); + pstHostMibs->stHostInfo.BEBucketSize = Adapter->BEBucketSize; + pstHostMibs->stHostInfo.rtPSBucketSize = Adapter->rtPSBucketSize; + pstHostMibs->stHostInfo.TimerActive = Adapter->TimerActive; + pstHostMibs->stHostInfo.u32TotalDSD = Adapter->u32TotalDSD; + + memcpy(pstHostMibs->stHostInfo.aTxPktSizeHist,Adapter->aTxPktSizeHist,sizeof(UINT32)*MIBS_MAX_HIST_ENTRIES); + memcpy(pstHostMibs->stHostInfo.aRxPktSizeHist,Adapter->aRxPktSizeHist,sizeof(UINT32)*MIBS_MAX_HIST_ENTRIES); + + return STATUS_SUCCESS; +} + + +INT GetDroppedAppCntrlPktMibs(PVOID ioBuffer, PPER_TARANG_DATA pTarang) +{ + S_MIBS_HOST_STATS_MIBS *pstHostMibs = (S_MIBS_HOST_STATS_MIBS *)ioBuffer; + + memcpy((PVOID)&(pstHostMibs->stDroppedAppCntrlMsgs),(PVOID)&(pTarang->stDroppedAppCntrlMsgs),sizeof(S_MIBS_DROPPED_APP_CNTRL_MESSAGES)); + + return STATUS_SUCCESS ; +} + + +VOID CopyMIBSExtendedSFParameters(PMINI_ADAPTER Adapter, + CServiceFlowParamSI *psfLocalSet, UINT uiSearchRuleIndex) +{ + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfSfid = psfLocalSet->u32SFID; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxSustainedRate = psfLocalSet->u32MaxSustainedTrafficRate; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxTrafficBurst = psfLocalSet->u32MaxTrafficBurst; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMinReservedRate = psfLocalSet->u32MinReservedTrafficRate; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsToleratedJitter = psfLocalSet->u32ToleratedJitter; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsMaxLatency = psfLocalSet->u32MaximumLatency; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd = psfLocalSet->u8FixedLengthVSVariableLengthSDUIndicator; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsFixedVsVariableSduInd); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize = psfLocalSet->u8SDUSize; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSduSize); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType = psfLocalSet->u8ServiceFlowSchedulingType; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsSfSchedulingType); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable = psfLocalSet->u8ARQEnable; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqEnable); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize = ntohs(psfLocalSet->u16ARQWindowSize); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqWindowSize); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime = ntohs(psfLocalSet->u16ARQBlockLifeTime); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockLifetime); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout = ntohs(psfLocalSet->u16ARQSyncLossTimeOut); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqSyncLossTimeout); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder = psfLocalSet->u8ARQDeliverInOrder; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqDeliverInOrder); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout = ntohs(psfLocalSet->u16ARQRxPurgeTimeOut); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqRxPurgeTimeout); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize = ntohs(psfLocalSet->u16ARQBlockSize); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsArqBlockSize); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy = psfLocalSet->u8RequesttransmissionPolicy; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsReqTxPolicy); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification = psfLocalSet->u8CSSpecification; + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnSfCsSpecification); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid = ntohs(psfLocalSet->u16TargetSAID); + Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid = ntohl(Adapter->PackInfo[uiSearchRuleIndex].stMibsExtServiceFlowTable.wmanIfCmnCpsTargetSaid); + +} diff --git a/drivers/staging/bcm/led_control.c b/drivers/staging/bcm/led_control.c new file mode 100644 index 0000000..0d07664 --- /dev/null +++ b/drivers/staging/bcm/led_control.c @@ -0,0 +1,1006 @@ +#include "headers.h" + +#define STATUS_IMAGE_CHECKSUM_MISMATCH -199 +#define EVENT_SIGNALED 1 + +static B_UINT16 CFG_CalculateChecksum(B_UINT8 *pu8Buffer, B_UINT32 u32Size) +{ + B_UINT16 u16CheckSum=0; + while(u32Size--) { + u16CheckSum += (B_UINT8)~(*pu8Buffer); + pu8Buffer++; + } + return u16CheckSum; +} +BOOLEAN IsReqGpioIsLedInNVM(PMINI_ADAPTER Adapter, UINT gpios) +{ + INT Status ; + Status = (Adapter->gpioBitMap & gpios) ^ gpios ; + if(Status) + return FALSE; + else + return TRUE; +} + +INT LED_Blink(PMINI_ADAPTER Adapter, UINT GPIO_Num, UCHAR uiLedIndex, ULONG timeout, INT num_of_time, LedEventInfo_t currdriverstate) +{ + int Status = STATUS_SUCCESS; + BOOLEAN bInfinite = FALSE; + + /*Check if num_of_time is -ve. If yes, blink led in infinite loop*/ + if(num_of_time < 0) + { + bInfinite = TRUE; + num_of_time = 1; + } + while(num_of_time) + { + + if(currdriverstate == Adapter->DriverState) + TURN_ON_LED(GPIO_Num, uiLedIndex); + + /*Wait for timeout after setting on the LED*/ + Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event, + currdriverstate != Adapter->DriverState || kthread_should_stop(), + msecs_to_jiffies(timeout)); + + if(kthread_should_stop()) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting"); + Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED; + TURN_OFF_LED(GPIO_Num, uiLedIndex); + Status=EVENT_SIGNALED; + break; + } + if(Status) + { + TURN_OFF_LED(GPIO_Num, uiLedIndex); + Status=EVENT_SIGNALED; + break; + } + + TURN_OFF_LED(GPIO_Num, uiLedIndex); + Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event, + currdriverstate!= Adapter->DriverState || kthread_should_stop(), + msecs_to_jiffies(timeout)); + if(bInfinite == FALSE) + num_of_time--; + } + return Status; +} + +INT ScaleRateofTransfer(ULONG rate) +{ + if(rate <= 3) + return rate; + else if((rate > 3) && (rate <= 100)) + return 5; + else if((rate > 100) && (rate <= 200)) + return 6; + else if((rate > 200) && (rate <= 300)) + return 7; + else if((rate > 300) && (rate <= 400)) + return 8; + else if((rate > 400) && (rate <= 500)) + return 9; + else if((rate > 500) && (rate <= 600)) + return 10; + else + return MAX_NUM_OF_BLINKS; +} + + + +INT LED_Proportional_Blink(PMINI_ADAPTER Adapter, UCHAR GPIO_Num_tx, + UCHAR uiTxLedIndex, UCHAR GPIO_Num_rx, UCHAR uiRxLedIndex, LedEventInfo_t currdriverstate) +{ + /* Initial values of TX and RX packets*/ + ULONG64 Initial_num_of_packts_tx = 0, Initial_num_of_packts_rx = 0; + /*values of TX and RX packets after 1 sec*/ + ULONG64 Final_num_of_packts_tx = 0, Final_num_of_packts_rx = 0; + /*Rate of transfer of Tx and Rx in 1 sec*/ + ULONG64 rate_of_transfer_tx = 0, rate_of_transfer_rx = 0; + int Status = STATUS_SUCCESS; + INT num_of_time = 0, num_of_time_tx = 0, num_of_time_rx = 0; + UINT remDelay = 0; + BOOLEAN bBlinkBothLED = TRUE; + //UINT GPIO_num = DISABLE_GPIO_NUM; + ulong timeout = 0; + + /*Read initial value of packets sent/received */ + Initial_num_of_packts_tx = atomic_read(&Adapter->TxTotalPacketCount); + Initial_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount); + /*Scale the rate of transfer to no of blinks.*/ + num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx); + num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx); + + while((Adapter->device_removed == FALSE)) + { + #if 0 + if(0 == num_of_time_tx && 0 == num_of_time_rx) + { + timeout = 1000; + Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event, + currdriverstate!= Adapter->DriverState || kthread_should_stop(), + msecs_to_jiffies (timeout)); + if(kthread_should_stop()) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting"); + Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED; + return EVENT_SIGNALED; + } + if(Status) + return EVENT_SIGNALED; + + } + #endif + + timeout = 50; + #if 0 + /*Turn on LED if Tx is high bandwidth*/ + if(num_of_time_tx > MAX_NUM_OF_BLINKS) + { + TURN_ON_LED(1< MAX_NUM_OF_BLINKS) + { + TURN_ON_LED(1< num_of_time_rx) + num_of_time = num_of_time_rx; + else + num_of_time = num_of_time_tx; + if(num_of_time > 0) + { + /*Blink both Tx and Rx LEDs*/ + if(LED_Blink(Adapter, 1< 0) + { + timeout= 100 * remDelay; + Status = wait_event_interruptible_timeout(Adapter->LEDInfo.notify_led_event, + currdriverstate!= Adapter->DriverState ||kthread_should_stop() , + msecs_to_jiffies (timeout)); + + if(kthread_should_stop()) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting"); + Adapter->LEDInfo.led_thread_running= BCM_LED_THREAD_DISABLED; + return EVENT_SIGNALED; + } + if(Status) + return EVENT_SIGNALED; + } + + /*Turn off both Tx and Rx LEDs before next second*/ + TURN_OFF_LED(1<TxTotalPacketCount); + rate_of_transfer_tx = Final_num_of_packts_tx - Initial_num_of_packts_tx; + Final_num_of_packts_rx = atomic_read(&Adapter->GoodRxPktCount); + rate_of_transfer_rx = Final_num_of_packts_rx - Initial_num_of_packts_rx; + + /*Read initial value of packets sent/received */ + Initial_num_of_packts_tx = Final_num_of_packts_tx; + Initial_num_of_packts_rx = Final_num_of_packts_rx ; + + /*Scale the rate of transfer to no of blinks.*/ + num_of_time_tx= ScaleRateofTransfer((ULONG)rate_of_transfer_tx); + num_of_time_rx= ScaleRateofTransfer((ULONG)rate_of_transfer_rx); + + } + return Status; +} + + +//----------------------------------------------------------------------------- +// Procedure: ValidateDSDParamsChecksum +// +// Description: Reads DSD Params and validates checkusm. +// +// Arguments: +// Adapter - Pointer to Adapter structure. +// ulParamOffset - Start offset of the DSD parameter to be read and validated. +// usParamLen - Length of the DSD Parameter. +// +// Returns: +// +//----------------------------------------------------------------------------- + +INT ValidateDSDParamsChecksum( + PMINI_ADAPTER Adapter, + ULONG ulParamOffset, + USHORT usParamLen ) +{ + INT Status = STATUS_SUCCESS; + PUCHAR puBuffer = NULL; + USHORT usChksmOrg = 0; + USHORT usChecksumCalculated = 0; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread:ValidateDSDParamsChecksum: 0x%lx 0x%X",ulParamOffset, usParamLen); + + puBuffer = OsalMemAlloc(usParamLen,'!MEM'); + if(!puBuffer) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum Allocation failed"); + return -ENOMEM; + + } + + // + // Read the DSD data from the parameter offset. + // + if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)puBuffer,ulParamOffset,usParamLen)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed"); + Status=STATUS_IMAGE_CHECKSUM_MISMATCH; + goto exit; + } + + // + // Calculate the checksum of the data read from the DSD parameter. + // + usChecksumCalculated = CFG_CalculateChecksum(puBuffer,usParamLen); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usCheckSumCalculated = 0x%x\n", usChecksumCalculated); + + // + // End of the DSD parameter will have a TWO bytes checksum stored in it. Read it and compare with the calculated + // Checksum. + // + if(STATUS_SUCCESS != BeceemNVMRead(Adapter,(PUINT)&usChksmOrg,ulParamOffset+usParamLen,2)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum BeceemNVMRead failed"); + Status=STATUS_IMAGE_CHECKSUM_MISMATCH; + goto exit; + } + usChksmOrg = ntohs(usChksmOrg); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: usChksmOrg = 0x%x", usChksmOrg); + + // + // Compare the checksum calculated with the checksum read from DSD section + // + if(usChecksumCalculated ^ usChksmOrg) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: ValidateDSDParamsChecksum: Checksums don't match"); + Status = STATUS_IMAGE_CHECKSUM_MISMATCH; + goto exit; + } + +exit: + if(puBuffer) + { + OsalMemFree(puBuffer, usParamLen); + } + return Status; +} + + +//----------------------------------------------------------------------------- +// Procedure: ValidateHWParmStructure +// +// Description: Validates HW Parameters. +// +// Arguments: +// Adapter - Pointer to Adapter structure. +// ulHwParamOffset - Start offset of the HW parameter Section to be read and validated. +// +// Returns: +// +//----------------------------------------------------------------------------- + +INT ValidateHWParmStructure(PMINI_ADAPTER Adapter, ULONG ulHwParamOffset) +{ + + INT Status = STATUS_SUCCESS ; + USHORT HwParamLen = 0; + // Add DSD start offset to the hwParamOffset to get the actual address. + ulHwParamOffset += DSD_START_OFFSET; + + /*Read the Length of HW_PARAM structure*/ + BeceemNVMRead(Adapter,(PUINT)&HwParamLen,ulHwParamOffset,2); + HwParamLen = ntohs(HwParamLen); + if(0==HwParamLen || HwParamLen > Adapter->uiNVMDSDSize) + { + return STATUS_IMAGE_CHECKSUM_MISMATCH; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "LED Thread:HwParamLen = 0x%x", HwParamLen); + Status =ValidateDSDParamsChecksum(Adapter,ulHwParamOffset,HwParamLen); + return Status; +} /* ValidateHWParmStructure() */ + +int ReadLEDInformationFromEEPROM(PMINI_ADAPTER Adapter, UCHAR GPIO_Array[]) +{ + int Status = STATUS_SUCCESS; + + ULONG dwReadValue = 0; + USHORT usHwParamData = 0; + USHORT usEEPROMVersion = 0; + UCHAR ucIndex = 0; + UCHAR ucGPIOInfo[32] = {0}; + + BeceemNVMRead(Adapter,(PUINT)&usEEPROMVersion,EEPROM_VERSION_OFFSET,2); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"usEEPROMVersion: Minor:0x%X Major:0x%x",usEEPROMVersion&0xFF, ((usEEPROMVersion>>8)&0xFF)); + + + if(((usEEPROMVersion>>8)&0xFF) < EEPROM_MAP5_MAJORVERSION) + { + BeceemNVMRead(Adapter,(PUINT)&usHwParamData,EEPROM_HW_PARAM_POINTER_ADDRESS,2); + usHwParamData = ntohs(usHwParamData); + dwReadValue = usHwParamData; + } + else + { + // + // Validate Compatibility section and then read HW param if compatibility section is valid. + // + Status = ValidateDSDParamsChecksum(Adapter, + DSD_START_OFFSET, + COMPATIBILITY_SECTION_LENGTH_MAP5); + + if(Status != STATUS_SUCCESS) + { + return Status; + } + BeceemNVMRead(Adapter,(PUINT)&dwReadValue,EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5,4); + dwReadValue = ntohl(dwReadValue); + } + + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Start address of HW_PARAM structure = 0x%lx",dwReadValue); + + // + // Validate if the address read out is within the DSD. + // Adapter->uiNVMDSDSize gives whole DSD size inclusive of Autoinit. + // lower limit should be above DSD_START_OFFSET and + // upper limit should be below (Adapter->uiNVMDSDSize-DSD_START_OFFSET) + // + if(dwReadValue < DSD_START_OFFSET || + dwReadValue > (Adapter->uiNVMDSDSize-DSD_START_OFFSET)) + { + return STATUS_IMAGE_CHECKSUM_MISMATCH; + } + + Status = ValidateHWParmStructure(Adapter, dwReadValue); + if(Status){ + return Status; + } + + /* + Add DSD_START_OFFSET to the offset read from the EEPROM. + This will give the actual start HW Parameters start address. + To read GPIO section, add GPIO offset further. + */ + + dwReadValue += DSD_START_OFFSET; // = start address of hw param section. + dwReadValue += GPIO_SECTION_START_OFFSET; // = GPIO start offset within HW Param section. + + /* Read the GPIO values for 32 GPIOs from EEPROM and map the function + * number to GPIO pin number to GPIO_Array + */ + BeceemNVMRead(Adapter, (UINT *)ucGPIOInfo,dwReadValue,32); + for(ucIndex = 0; ucIndex < 32; ucIndex++) + { + + switch(ucGPIOInfo[ucIndex]) + { + case RED_LED: + { + GPIO_Array[RED_LED] = ucIndex; + Adapter->gpioBitMap |= (1<gpioBitMap |= (1<gpioBitMap |= (1<gpioBitMap |= (1<gpioBitMap); + return Status; +} + + +int ReadConfigFileStructure(PMINI_ADAPTER Adapter, BOOLEAN *bEnableThread) +{ + int Status = STATUS_SUCCESS; + UCHAR GPIO_Array[NUM_OF_LEDS+1]; /*Array to store GPIO numbers from EEPROM*/ +#ifndef BCM_SHM_INTERFACE + UINT uiIndex = 0; + UINT uiNum_of_LED_Type = 0; + PUCHAR puCFGData = NULL; + UCHAR bData = 0; +#endif + memset(GPIO_Array, DISABLE_GPIO_NUM, NUM_OF_LEDS+1); + + if(!Adapter->pstargetparams || IS_ERR(Adapter->pstargetparams)) + { + BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Target Params not Avail.\n"); + return -ENOENT; + } + + /*Populate GPIO_Array with GPIO numbers for LED functions*/ + /*Read the GPIO numbers from EEPROM*/ + Status = ReadLEDInformationFromEEPROM(Adapter, GPIO_Array); + if(Status == STATUS_IMAGE_CHECKSUM_MISMATCH) + { + *bEnableThread = FALSE; + return STATUS_SUCCESS; + } + else if(Status) + { + *bEnableThread = FALSE; + return Status; + } +#ifdef BCM_SHM_INTERFACE + *bEnableThread = FALSE; + return Status ; +#else + /* + * CONFIG file read successfully. Deallocate the memory of + * uiFileNameBufferSize + */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Config file read successfully\n"); + puCFGData = (PUCHAR) &Adapter->pstargetparams->HostDrvrConfig1; + + /* + * Offset for HostDrvConfig1, HostDrvConfig2, HostDrvConfig3 which + * will have the information of LED type, LED on state for different + * driver state and LED blink state. + */ + + for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) + { + bData = *puCFGData; + + /*Check Bit 8 for polarity. If it is set, polarity is reverse polarity*/ + if(bData & 0x80) + { + Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 0; + /*unset the bit 8*/ + bData = bData & 0x7f; + } + + Adapter->LEDInfo.LEDState[uiIndex].LED_Type = bData; + if(bData <= NUM_OF_LEDS) + Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = GPIO_Array[bData]; + else + Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num = DISABLE_GPIO_NUM; + + puCFGData++; + bData = *puCFGData; + Adapter->LEDInfo.LEDState[uiIndex].LED_On_State = bData; + puCFGData++; + bData = *puCFGData; + Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State= bData; + puCFGData++; + } + + /*Check if all the LED settings are disabled. If it is disabled, dont launch the LED control thread.*/ + for(uiIndex = 0; uiIndexLEDInfo.LEDState[uiIndex].LED_Type == DISABLE_GPIO_NUM) || + (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0x7f) || + (Adapter->LEDInfo.LEDState[uiIndex].LED_Type == 0)) + uiNum_of_LED_Type++; + } + if(uiNum_of_LED_Type >= NUM_OF_LEDS) + *bEnableThread = FALSE; +#endif + +#if 0 + for(uiIndex=0; uiIndexLEDInfo.LEDState[uiIndex].LED_Type); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_On_State = %x\n", uiIndex, + Adapter->LEDInfo.LEDState[uiIndex].LED_On_State); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].LED_Blink_State = %x\n", uiIndex, + Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LEDState[%d].GPIO_Num = %x\n", uiIndex, + Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num); + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: Polarity = %d\n", + Adapter->LEDInfo.BitPolarty); +#endif + return Status; +} +//-------------------------------------------------------------------------- +// Procedure: LedGpioInit +// +// Description: Initializes LED GPIOs. Makes the LED GPIOs to OUTPUT mode and make the +// initial state to be OFF. +// +// Arguments: +// Adapter - Pointer to MINI_ADAPTER structure. +// +// Returns: VOID +// +//----------------------------------------------------------------------------- + +VOID LedGpioInit(PMINI_ADAPTER Adapter) +{ + UINT uiResetValue = 0; + UINT uiIndex = 0; + + /* Set all LED GPIO Mode to output mode */ + if(rdmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) <0) + BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: RDM Failed\n"); + for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) + { + if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM) + uiResetValue |= (1 << Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num); + TURN_OFF_LED(1<LEDInfo.LEDState[uiIndex].GPIO_Num,uiIndex); + } + if(wrmalt(Adapter, GPIO_MODE_REGISTER, &uiResetValue, sizeof(uiResetValue)) < 0) + BCM_DEBUG_PRINT (Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: WRM Failed\n"); + + Adapter->LEDInfo.bIdle_led_off = FALSE; +} +//----------------------------------------------------------------------------- + +INT BcmGetGPIOPinInfo(PMINI_ADAPTER Adapter, UCHAR *GPIO_num_tx, UCHAR *GPIO_num_rx ,UCHAR *uiLedTxIndex, UCHAR *uiLedRxIndex,LedEventInfo_t currdriverstate) +{ + UINT uiIndex = 0; + + *GPIO_num_tx = DISABLE_GPIO_NUM; + *GPIO_num_rx = DISABLE_GPIO_NUM; + + for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) + { + + if((currdriverstate == NORMAL_OPERATION)|| + (currdriverstate == IDLEMODE_EXIT)|| + (currdriverstate == FW_DOWNLOAD)) + { + if(Adapter->LEDInfo.LEDState[uiIndex].LED_Blink_State & currdriverstate) + { + if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM) + { + if(*GPIO_num_tx == DISABLE_GPIO_NUM) + { + *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num; + *uiLedTxIndex = uiIndex; + } + else + { + *GPIO_num_rx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num; + *uiLedRxIndex = uiIndex; + } + } + } + } + else + { + if(Adapter->LEDInfo.LEDState[uiIndex].LED_On_State & currdriverstate) + { + if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM) + { + *GPIO_num_tx = Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num; + *uiLedTxIndex = uiIndex; + } + } + } + } + return STATUS_SUCCESS ; +} +VOID LEDControlThread(PMINI_ADAPTER Adapter) +{ + UINT uiIndex = 0; + UCHAR GPIO_num = 0; + UCHAR uiLedIndex = 0 ; + UINT uiResetValue = 0; + LedEventInfo_t currdriverstate = 0; + ulong timeout = 0; + + INT Status = 0; + + UCHAR dummyGPIONum = 0; + UCHAR dummyIndex = 0; + + //currdriverstate = Adapter->DriverState; + Adapter->LEDInfo.bIdleMode_tx_from_host = FALSE; + + /*Wait till event is triggered*/ + //wait_event(Adapter->LEDInfo.notify_led_event, + // currdriverstate!= Adapter->DriverState); + + GPIO_num = DISABLE_GPIO_NUM ; + + while(TRUE) + { + /*Wait till event is triggered*/ + if( (GPIO_num == DISABLE_GPIO_NUM) + || + ((currdriverstate != FW_DOWNLOAD) && + (currdriverstate != NORMAL_OPERATION) && + (currdriverstate != LOWPOWER_MODE_ENTER)) + || + (currdriverstate == LED_THREAD_INACTIVE) ) + { + Status = wait_event_interruptible(Adapter->LEDInfo.notify_led_event, + currdriverstate != Adapter->DriverState || kthread_should_stop()); + } + + if(kthread_should_stop() || Adapter->device_removed ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Led thread got signal to exit..hence exiting"); + Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED; + TURN_OFF_LED(1<device_removed) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Device removed hence exiting from Led Thread.."); + return ; //-ENODEV; + } + #endif + #if 0 + if((GPIO_num != DISABLE_GPIO_NUM) && + ((currdriverstate != FW_DOWNLOAD) && + (currdriverstate != NORMAL_OPERATION) && + (currdriverstate != IDLEMODE_EXIT))) + TURN_OFF_LED(1<LEDInfo.bLedInitDone == FALSE) + { + LedGpioInit(Adapter); + Adapter->LEDInfo.bLedInitDone = TRUE; + } + + switch(Adapter->DriverState) + { + case DRIVER_INIT: + { + currdriverstate = DRIVER_INIT;//Adapter->DriverState; + #if 0 + LedGpioInit(Adapter); + Adapter->LEDInfo.bLedInitDone = TRUE; + #endif + BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate); + + if(GPIO_num != DISABLE_GPIO_NUM) + { + TURN_ON_LED(1<LEDInfo.bLedInitDone == FALSE) + { + LedGpioInit(Adapter); + Adapter->LEDInfo.bLedInitDone = TRUE; + } + #endif + BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex, &dummyIndex, currdriverstate); + + if(GPIO_num != DISABLE_GPIO_NUM) + { + timeout = 50; + LED_Blink(Adapter, 1<ulPowerSaveMode == DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN) + { + LedGpioInit(Adapter); + } + #endif + //no break, continue to NO_NETWORK_ENTRY state as well. + + case NO_NETWORK_ENTRY: + { + currdriverstate = NO_NETWORK_ENTRY; + BcmGetGPIOPinInfo(Adapter, &GPIO_num, &dummyGPIONum, &uiLedIndex,&dummyGPIONum,currdriverstate); + if(GPIO_num != DISABLE_GPIO_NUM) + { + TURN_ON_LED(1<LEDInfo.bIdle_led_off = FALSE; + + BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiLEDTx,&uiLEDRx,currdriverstate); + if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM)) + { + GPIO_num = DISABLE_GPIO_NUM ; + } + else + { + /*If single LED is selected, use same for both Tx and Rx*/ + if(GPIO_num_tx == DISABLE_GPIO_NUM) + { + GPIO_num_tx = GPIO_num_rx; + uiLEDTx = uiLEDRx; + } + else if(GPIO_num_rx == DISABLE_GPIO_NUM) + { + GPIO_num_rx = GPIO_num_tx; + uiLEDRx = uiLEDTx; + } + /*Blink the LED in proportionate to Tx and Rx transmissions.*/ + LED_Proportional_Blink(Adapter, GPIO_num_tx, uiLEDTx, GPIO_num_rx, uiLEDRx,currdriverstate); + } + } + break; + case LOWPOWER_MODE_ENTER: + { + currdriverstate = LOWPOWER_MODE_ENTER; + if( DEVICE_POWERSAVE_MODE_AS_MANUAL_CLOCK_GATING == Adapter->ulPowerSaveMode) + { + /* Turn OFF all the LED */ + uiResetValue = 0; + for(uiIndex =0; uiIndex < NUM_OF_LEDS; uiIndex++) + { + if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != DISABLE_GPIO_NUM) + TURN_OFF_LED((1<LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex); + } + + } + /* Turn off LED And WAKE-UP for Sendinf IDLE mode ACK */ + Adapter->LEDInfo.bLedInitDone = FALSE; + Adapter->LEDInfo.bIdle_led_off = TRUE; + wake_up(&Adapter->LEDInfo.idleModeSyncEvent); + GPIO_num = DISABLE_GPIO_NUM; + break; + } + case IDLEMODE_CONTINUE: + { + currdriverstate = IDLEMODE_CONTINUE; + GPIO_num = DISABLE_GPIO_NUM; + } + break; + case IDLEMODE_EXIT: + { +#if 0 + UCHAR GPIO_num_tx = DISABLE_GPIO_NUM; + UCHAR GPIO_num_rx = DISABLE_GPIO_NUM; + UCHAR uiTxLedIndex = 0; + UCHAR uiRxLedIndex = 0; + + currdriverstate = IDLEMODE_EXIT; + if(DEVICE_POWERSAVE_MODE_AS_PMU_SHUTDOWN == Adapter->ulPowerSaveMode) + { + LedGpioInit(Adapter); + } + BcmGetGPIOPinInfo(Adapter, &GPIO_num_tx, &GPIO_num_rx, &uiTxLedIndex,&uiRxLedIndex,currdriverstate); + + Adapter->LEDInfo.bIdle_led_off = FALSE; + + if((GPIO_num_tx == DISABLE_GPIO_NUM) && (GPIO_num_rx == DISABLE_GPIO_NUM)) + { + GPIO_num = DISABLE_GPIO_NUM ; + } + else + { + timeout = 50; + if(Adapter->LEDInfo.bIdleMode_tx_from_host) + LED_Blink(Adapter, 1<LEDInfo.LEDState[uiIndex].GPIO_Num != + DISABLE_GPIO_NUM) + TURN_OFF_LED((1<LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex); + } + //Adapter->DriverState = DRIVER_INIT; + } + break; + case LED_THREAD_INACTIVE : + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"InActivating LED thread..."); + currdriverstate = LED_THREAD_INACTIVE; + Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_INACTIVELY ; + Adapter->LEDInfo.bLedInitDone = FALSE ; + //disable ALL LED + for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) + { + if(Adapter->LEDInfo.LEDState[uiIndex].GPIO_Num != + DISABLE_GPIO_NUM) + TURN_OFF_LED((1<LEDInfo.LEDState[uiIndex].GPIO_Num),uiIndex); + } + } + break; + case LED_THREAD_ACTIVE : + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"Activating LED thread again..."); + if(Adapter->LinkUpStatus == FALSE) + Adapter->DriverState = NO_NETWORK_ENTRY; + else + Adapter->DriverState = NORMAL_OPERATION; + + Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY ; + } + break; + //return; + default: + break; + } + } + Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED; +} + +int InitLedSettings(PMINI_ADAPTER Adapter) +{ + int Status = STATUS_SUCCESS; + BOOLEAN bEnableThread = TRUE; + UCHAR uiIndex = 0; + + /*Initially set BitPolarity to normal polarity. The bit 8 of LED type + * is used to change the polarity of the LED.*/ + + for(uiIndex = 0; uiIndex < NUM_OF_LEDS; uiIndex++) { + Adapter->LEDInfo.LEDState[uiIndex].BitPolarity = 1; + } + + /*Read the LED settings of CONFIG file and map it to GPIO numbers in EEPROM*/ + Status = ReadConfigFileStructure(Adapter, &bEnableThread); + if(STATUS_SUCCESS != Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL,"LED Thread: FAILED in ReadConfigFileStructure\n"); + return Status; + } + + if(Adapter->LEDInfo.led_thread_running) + { + if(bEnableThread) + ; + else + { + Adapter->DriverState = DRIVER_HALT; + wake_up(&Adapter->LEDInfo.notify_led_event); + Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED; + } + + } + + else if(bEnableThread) + { + /*Create secondary thread to handle the LEDs*/ + init_waitqueue_head(&Adapter->LEDInfo.notify_led_event); + init_waitqueue_head(&Adapter->LEDInfo.idleModeSyncEvent); + Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_RUNNING_ACTIVELY; + Adapter->LEDInfo.bIdle_led_off = FALSE; + Adapter->LEDInfo.led_cntrl_threadid = kthread_run((int (*)(void *)) + LEDControlThread, Adapter, "led_control_thread"); + if(IS_ERR(Adapter->LEDInfo.led_cntrl_threadid)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LED_DUMP_INFO, DBG_LVL_ALL, "Not able to spawn Kernel Thread\n"); + Adapter->LEDInfo.led_thread_running = BCM_LED_THREAD_DISABLED; + return PTR_ERR(Adapter->LEDInfo.led_cntrl_threadid); + } + } + return Status; +} diff --git a/drivers/staging/bcm/led_control.h b/drivers/staging/bcm/led_control.h new file mode 100644 index 0000000..0711ac2 --- /dev/null +++ b/drivers/staging/bcm/led_control.h @@ -0,0 +1,106 @@ +#ifndef _LED_CONTROL_H +#define _LED_CONTROL_H + +/*************************TYPE DEF**********************/ +#define NUM_OF_LEDS 4 + +#define DSD_START_OFFSET 0x0200 +#define EEPROM_VERSION_OFFSET 0x020E +#define EEPROM_HW_PARAM_POINTER_ADDRESS 0x0218 +#define EEPROM_HW_PARAM_POINTER_ADDRRES_MAP5 0x0220 +#define GPIO_SECTION_START_OFFSET 0x03 + +#define COMPATIBILITY_SECTION_LENGTH 42 +#define COMPATIBILITY_SECTION_LENGTH_MAP5 84 + + +#define EEPROM_MAP5_MAJORVERSION 5 +#define EEPROM_MAP5_MINORVERSION 0 + + +#define MAX_NUM_OF_BLINKS 10 +#define NUM_OF_GPIO_PINS 16 + +#define DISABLE_GPIO_NUM 0xFF +#define EVENT_SIGNALED 1 + +#define MAX_FILE_NAME_BUFFER_SIZE 100 + +#define TURN_ON_LED(GPIO, index) do{ \ + UINT gpio_val = GPIO; \ + (Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ? \ + wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG, &gpio_val ,sizeof(gpio_val)) : \ + wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG, &gpio_val, sizeof(gpio_val)); \ + }while(0); + +#define TURN_OFF_LED(GPIO, index) do { \ + UINT gpio_val = GPIO; \ + (Adapter->LEDInfo.LEDState[index].BitPolarity == 1) ? \ + wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_CLR_REG,&gpio_val ,sizeof(gpio_val)) : \ + wrmaltWithLock(Adapter,BCM_GPIO_OUTPUT_SET_REG,&gpio_val ,sizeof(gpio_val)); \ + }while(0); + +#define B_ULONG32 unsigned long + +/*******************************************************/ + + +typedef enum _LEDColors{ + RED_LED = 1, + BLUE_LED = 2, + YELLOW_LED = 3, + GREEN_LED = 4 +} LEDColors; /*Enumerated values of different LED types*/ + +typedef enum LedEvents { + SHUTDOWN_EXIT = 0x00, + DRIVER_INIT = 0x1, + FW_DOWNLOAD = 0x2, + FW_DOWNLOAD_DONE = 0x4, + NO_NETWORK_ENTRY = 0x8, + NORMAL_OPERATION = 0x10, + LOWPOWER_MODE_ENTER = 0x20, + IDLEMODE_CONTINUE = 0x40, + IDLEMODE_EXIT = 0x80, + LED_THREAD_INACTIVE = 0x100, //Makes the LED thread Inactivce. It wil be equivallent to putting the thread on hold. + LED_THREAD_ACTIVE = 0x200 //Makes the LED Thread Active back. +} LedEventInfo_t; /*Enumerated values of different driver states*/ + +#define DRIVER_HALT 0xff + + +/*Structure which stores the information of different LED types + * and corresponding LED state information of driver states*/ +typedef struct LedStateInfo_t +{ + UCHAR LED_Type; /* specify GPIO number - use 0xFF if not used */ + UCHAR LED_On_State; /* Bits set or reset for different states */ + UCHAR LED_Blink_State; /* Bits set or reset for blinking LEDs for different states */ + UCHAR GPIO_Num; + UCHAR BitPolarity; /*To represent whether H/W is normal polarity or reverse + polarity*/ +}LEDStateInfo, *pLEDStateInfo; + + +typedef struct _LED_INFO_STRUCT +{ + LEDStateInfo LEDState[NUM_OF_LEDS]; + BOOLEAN bIdleMode_tx_from_host; /*Variable to notify whether driver came out + from idlemode due to Host or target*/ + BOOLEAN bIdle_led_off; + wait_queue_head_t notify_led_event; + wait_queue_head_t idleModeSyncEvent; + struct task_struct *led_cntrl_threadid; + int led_thread_running; + BOOLEAN bLedInitDone; + +} LED_INFO_STRUCT, *PLED_INFO_STRUCT; +//LED Thread state. +#define BCM_LED_THREAD_DISABLED 0 //LED Thread is not running. +#define BCM_LED_THREAD_RUNNING_ACTIVELY 1 //LED thread is running. +#define BCM_LED_THREAD_RUNNING_INACTIVELY 2 //LED thread has been put on hold + + + +#endif + diff --git a/drivers/staging/bcm/nvm.c b/drivers/staging/bcm/nvm.c new file mode 100644 index 0000000..35ff4e7 --- /dev/null +++ b/drivers/staging/bcm/nvm.c @@ -0,0 +1,5614 @@ +#include "headers.h" + +#define DWORD unsigned int +// Procedure: ReadEEPROMStatusRegister +// +// Description: Reads the standard EEPROM Status Register. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +UCHAR ReadEEPROMStatusRegister( PMINI_ADAPTER Adapter ) +{ + UCHAR uiData = 0; + DWORD dwRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + UINT uiStatus = 0; + UINT value = 0; + UINT value1 = 0; + + /* Read the EEPROM status register */ + value = EEPROM_READ_STATUS_REGISTER ; + wrmalt( Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); + + while ( dwRetries != 0 ) + { + value=0; + uiStatus = 0 ; + rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&uiStatus, sizeof(uiStatus)); + if(Adapter->device_removed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got removed hence exiting...."); + break; + } + + /* Wait for Avail bit to be set. */ + if ( ( uiStatus & EEPROM_READ_DATA_AVAIL) != 0 ) + { + /* Clear the Avail/Full bits - which ever is set. */ + value = uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL); + wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + + value =0; + rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + uiData = (UCHAR)value; + + break; + } + + dwRetries-- ; + if ( dwRetries == 0 ) + { + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG,&value1, sizeof(value1)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"0x3004 = %x 0x3008 = %x, retries = %d failed.\n",value,value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY); + return uiData; + } + if( !(dwRetries%RETRIES_PER_DELAY) ) + msleep(1); + uiStatus = 0 ; + } + return uiData; +} /* ReadEEPROMStatusRegister */ + +//----------------------------------------------------------------------------- +// Procedure: ReadBeceemEEPROMBulk +// +// Description: This routine reads 16Byte data from EEPROM +// +// Arguments: +// Adapter - ptr to Adapter object instance +// dwAddress - EEPROM Offset to read the data from. +// pdwData - Pointer to double word where data needs to be stored in. // dwNumWords - Number of words. Valid values are 4 ONLY. +// +// Returns: +// OSAL_STATUS_CODE: +//----------------------------------------------------------------------------- + +INT ReadBeceemEEPROMBulk( PMINI_ADAPTER Adapter, + DWORD dwAddress, + DWORD *pdwData, + DWORD dwNumWords + ) +{ + DWORD dwIndex = 0; + DWORD dwRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + UINT uiStatus = 0; + UINT value= 0; + UINT value1 = 0; + UCHAR *pvalue; + + /* Flush the read and cmd queue. */ + value=( EEPROM_READ_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH ); + wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value) ); + value=0; + wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value)); + + /* Clear the Avail/Full bits. */ + value=( EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL ); + wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + + value= dwAddress | ( (dwNumWords == 4) ? EEPROM_16_BYTE_PAGE_READ : EEPROM_4_BYTE_PAGE_READ ); + wrmalt( Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value)); + + while ( dwRetries != 0 ) + { + + uiStatus = 0; + rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &uiStatus, sizeof(uiStatus)); + if(Adapter->device_removed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem has got Removed.hence exiting from loop..."); + return -ENODEV; + } + + /* If we are reading 16 bytes we want to be sure that the queue + * is full before we read. In the other cases we are ok if the + * queue has data available */ + if ( dwNumWords == 4 ) + { + if ( ( uiStatus & EEPROM_READ_DATA_FULL ) != 0 ) + { + /* Clear the Avail/Full bits - which ever is set. */ + value = ( uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL) ) ; + wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + break; + } + } + else if ( dwNumWords == 1 ) + { + + if ( ( uiStatus & EEPROM_READ_DATA_AVAIL ) != 0 ) + { + /* We just got Avail and we have to read 32bits so we + * need this sleep for Cardbus kind of devices. */ + if (Adapter->chip_id == 0xBECE0210 ) + udelay(800); + + /* Clear the Avail/Full bits - which ever is set. */ + value=( uiStatus & (EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL) ); + wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + break; + } + } + + uiStatus = 0; + + dwRetries--; + if(dwRetries == 0) + { + value=0; + value1=0; + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + rdmalt(Adapter, EEPROM_SPI_Q_STATUS_REG,&value1, sizeof(value1)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "dwNumWords %d 0x3004 = %x 0x3008 = %x retries = %d failed.\n", dwNumWords, value, value1, MAX_EEPROM_RETRIES*RETRIES_PER_DELAY); + return STATUS_FAILURE; + } + if( !(dwRetries%RETRIES_PER_DELAY) ) + msleep(1); + } + + for ( dwIndex = 0; dwIndex < dwNumWords ; dwIndex++ ) + { + /* We get only a byte at a time - from LSB to MSB. We shift it into an integer. */ + pvalue = (PUCHAR)(pdwData + dwIndex); + + value =0; + rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + + pvalue[0] = value; + + value = 0; + rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + + pvalue[1] = value; + + value =0; + rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + + pvalue[2] = value; + + value = 0; + rdmalt(Adapter, EEPROM_READ_DATAQ_REG,&value, sizeof(value)); + + pvalue[3] = value; + } + + return STATUS_SUCCESS; +} /* ReadBeceemEEPROMBulk() */ + +//----------------------------------------------------------------------------- +// Procedure: ReadBeceemEEPROM +// +// Description: This routine reads 4 data from EEPROM. It uses 1 or 2 page +// reads to do this operation. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiOffset - EEPROM Offset to read the data from. +// pBuffer - Pointer to word where data needs to be stored in. +// +// Returns: +// OSAL_STATUS_CODE: +//----------------------------------------------------------------------------- + +INT ReadBeceemEEPROM( PMINI_ADAPTER Adapter, + DWORD uiOffset, + DWORD *pBuffer + ) +{ + UINT uiData[8] = {0}; + UINT uiByteOffset = 0; + UINT uiTempOffset = 0; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL," ====> "); + + uiTempOffset = uiOffset - (uiOffset % MAX_RW_SIZE); + uiByteOffset = uiOffset - uiTempOffset; + + ReadBeceemEEPROMBulk(Adapter, uiTempOffset, (PUINT)&uiData[0], 4); + + /* A word can overlap at most over 2 pages. In that case we read the + * next page too. */ + if ( uiByteOffset > 12 ) + { + ReadBeceemEEPROMBulk(Adapter, uiTempOffset + MAX_RW_SIZE, (PUINT)&uiData[4], 4); + } + + OsalMemMove( (PUCHAR) pBuffer, ( ((PUCHAR)&uiData[0]) + uiByteOffset ), 4); + + return STATUS_SUCCESS; +} /* ReadBeceemEEPROM() */ + + +#if 0 +//----------------------------------------------------------------------------- +// Procedure: IsEEPROMWriteDone +// +// Description: Reads the SPI status to see the status of previous write. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// BOOLEAN - TRUE - write went through +// - FALSE - Write Failed. +//----------------------------------------------------------------------------- + +BOOLEAN IsEEPROMWriteDone(PMINI_ADAPTER Adapter) +{ + UINT uiRetries = 16; + //UINT uiStatus = 0; + UINT value; + + //sleep for 1.2ms ..worst case EEPROM write can take up to 1.2ms. + mdelay(2); + + value = 0; + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + + while(((value >> 14) & 1) == 1) + { + // EEPROM_SPI_Q_STATUS1_REG will be cleared only if write back to that. + value = (0x1 << 14); + wrmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + udelay(1000); + uiRetries--; + if(uiRetries == 0) + { + return FALSE; + } + value = 0; + rdmalt(Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + } + return TRUE; + + +} + + +//----------------------------------------------------------------------------- +// Procedure: ReadBeceemEEPROMBulk +// +// Description: This routine reads 16Byte data from EEPROM +// +// Arguments: +// Adapter - ptr to Adapter object instance +// dwAddress - EEPROM Offset to read the data from. +// pdwData - Pointer to double word where data needs to be stored in. +// +// Returns: +// OSAL_STATUS_CODE: +//----------------------------------------------------------------------------- + +INT ReadBeceemEEPROMBulk(PMINI_ADAPTER Adapter,DWORD dwAddress, DWORD *pdwData) +{ + DWORD dwRetries = 16; + DWORD dwIndex = 0; + UINT value, tmpVal; + + + value = 0; + rdmalt (Adapter, 0x0f003008, &value, sizeof(value)); + + //read 0x0f003020 untill bit 1 of 0x0f003008 is set. + while(((value >> 1) & 1) == 0) + { + + rdmalt (Adapter, 0x0f003020, &tmpVal, sizeof(tmpVal)); + dwRetries--; + if(dwRetries == 0) + { + return -1; + } + value = 0; + rdmalt (Adapter, 0x0f003008, &value, sizeof(value)); + } + + value = dwAddress | 0xfb000000; + wrmalt (Adapter, 0x0f003018, &value, sizeof(value)); + + udelay(1000); + value = 0; + for(dwIndex = 0;dwIndex < 4 ; dwIndex++) + { + value = 0; + rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); + pdwData[dwIndex] = value; + + value = 0; + rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); + pdwData[dwIndex] |= (value << 8); + + value = 0; + rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); + pdwData[dwIndex] |= (value << 16); + + value = 0; + rdmalt (Adapter, 0x0f003020, &value, sizeof(value)); + pdwData[dwIndex] |= (value << 24); + + } + return 0; +} + +//----------------------------------------------------------------------------- +// Procedure: ReadBeceemEEPROM +// +// Description: This routine reads 4Byte data from EEPROM +// +// Arguments: +// Adapter - ptr to Adapter object instance +// dwAddress - EEPROM Offset to read the data from. +// pdwData - Pointer to double word where data needs to be stored in. +// +// Returns: +// OSAL_STATUS_CODE: +//----------------------------------------------------------------------------- + +INT ReadBeceemEEPROM(PMINI_ADAPTER Adapter,DWORD dwAddress, DWORD *pdwData) +{ + + DWORD dwReadValue = 0; + DWORD dwRetries = 16, dwCompleteWord = 0; + UINT value, tmpVal; + + rdmalt(Adapter, 0x0f003008, &value, sizeof(value)); + while (((value >> 1) & 1) == 0) { + rdmalt(Adapter, 0x0f003020, &tmpVal, sizeof(tmpVal)); + + if (dwRetries == 0) { + return -1; + } + rdmalt(Adapter, 0x0f003008, &value, sizeof(value)); + } + + + //wrm (0x0f003018, 0xNbXXXXXX) // N is the number of bytes u want to read (0 means 1, f means 16, b is the opcode for page read) + // Follow it up by N executions of rdm(0x0f003020) to read the rxed bytes from rx queue. + dwAddress |= 0x3b000000; + wrmalt(Adapter, 0x0f003018,&dwAddress,4); + mdelay(10); + rdmalt(Adapter, 0x0f003020,&dwReadValue,4); + dwCompleteWord=dwReadValue; + rdmalt(Adapter, 0x0f003020,&dwReadValue,4); + dwCompleteWord|=(dwReadValue<<8); + rdmalt(Adapter, 0x0f003020,&dwReadValue,4); + dwCompleteWord|=(dwReadValue<<16); + rdmalt(Adapter, 0x0f003020,&dwReadValue,4); + dwCompleteWord|=(dwReadValue<<24); + + *pdwData = dwCompleteWord; + + return 0; +} +#endif + +INT ReadMacAddressFromNVM(PMINI_ADAPTER Adapter) +{ + INT Status=0, i; + unsigned char puMacAddr[6] = {0}; + INT AllZeroMac = 0; + INT AllFFMac = 0; + + Status = BeceemNVMRead(Adapter, + (PUINT)&puMacAddr[0], + INIT_PARAMS_1_MACADDRESS_ADDRESS, + MAC_ADDRESS_SIZE); + + if(Status != STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Error in Reading the mac Addres with status :%d", Status); + return Status; + } + + memcpy(Adapter->dev->dev_addr, puMacAddr, MAC_ADDRESS_SIZE); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Modem MAC Addr :"); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_PRINTK, 0, DBG_LVL_ALL,&Adapter->dev->dev_addr[0],MAC_ADDRESS_SIZE); + for(i=0;idev->dev_addr[i] == 0x00) + AllZeroMac++; + if(Adapter->dev->dev_addr[i] == 0xFF) + AllFFMac++; + + } + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\n"); + if(AllZeroMac == MAC_ADDRESS_SIZE) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Warning :: MAC Address has all 00's"); + if(AllFFMac == MAC_ADDRESS_SIZE) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Warning :: MAC Address has all FF's"); + + return Status; + +} + +//----------------------------------------------------------------------------- +// Procedure: BeceemEEPROMBulkRead +// +// Description: Reads the EEPROM and returns the Data. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Buffer to store the data read from EEPROM +// uiOffset - Offset of EEPROM from where data should be read +// uiNumBytes - Number of bytes to be read from the EEPROM. +// +// Returns: +// OSAL_STATUS_SUCCESS - if EEPROM read is successfull. +// - if failed. +//----------------------------------------------------------------------------- + +INT BeceemEEPROMBulkRead( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) +{ + UINT uiData[4] = {0}; + //UINT uiAddress = 0; + UINT uiBytesRemaining = uiNumBytes; + UINT uiIndex = 0; + UINT uiTempOffset = 0; + UINT uiExtraBytes = 0; + UINT uiFailureRetries = 0; + PUCHAR pcBuff = (PUCHAR)pBuffer; + + + if(uiOffset%MAX_RW_SIZE&& uiBytesRemaining) + { + uiTempOffset = uiOffset - (uiOffset%MAX_RW_SIZE); + uiExtraBytes = uiOffset-uiTempOffset; + ReadBeceemEEPROMBulk(Adapter,uiTempOffset,(PUINT)&uiData[0],4); + if(uiBytesRemaining >= (MAX_RW_SIZE - uiExtraBytes)) + { + OsalMemMove(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),MAX_RW_SIZE - uiExtraBytes); + + uiBytesRemaining -= (MAX_RW_SIZE - uiExtraBytes); + uiIndex += (MAX_RW_SIZE - uiExtraBytes); + uiOffset += (MAX_RW_SIZE - uiExtraBytes); + } + else + { + OsalMemMove(pBuffer,(((PUCHAR)&uiData[0])+uiExtraBytes),uiBytesRemaining); + uiIndex += uiBytesRemaining; + uiOffset += uiBytesRemaining; + uiBytesRemaining = 0; + } + + + } + + + while(uiBytesRemaining && uiFailureRetries != 128) + { + if(Adapter->device_removed ) + { + return -1; + } + + if(uiBytesRemaining >= MAX_RW_SIZE) + { + /* For the requests more than or equal to 16 bytes, use bulk + * read function to make the access faster. + * We read 4 Dwords of data */ + if(0 == ReadBeceemEEPROMBulk(Adapter,uiOffset,&uiData[0],4)) + { + OsalMemMove(pcBuff+uiIndex,&uiData[0],MAX_RW_SIZE); + uiOffset += MAX_RW_SIZE; + uiBytesRemaining -= MAX_RW_SIZE; + uiIndex += MAX_RW_SIZE; + } + else + { + uiFailureRetries++; + mdelay(3);//sleep for a while before retry... + } + } + else if(uiBytesRemaining >= 4) + { + if(0 == ReadBeceemEEPROM(Adapter,uiOffset,&uiData[0])) + { + OsalMemMove(pcBuff+uiIndex,&uiData[0],4); + uiOffset += 4; + uiBytesRemaining -= 4; + uiIndex +=4; + } + else + { + uiFailureRetries++; + mdelay(3);//sleep for a while before retry... + } + } + else + { // Handle the reads less than 4 bytes... + PUCHAR pCharBuff = (PUCHAR)pBuffer; + pCharBuff += uiIndex; + if(0 == ReadBeceemEEPROM(Adapter,uiOffset,&uiData[0])) + { + OsalMemMove(pCharBuff,&uiData[0],uiBytesRemaining);//copy only bytes requested. + uiBytesRemaining = 0; + } + else + { + uiFailureRetries++; + mdelay(3);//sleep for a while before retry... + } + } + + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Procedure: BeceemFlashBulkRead +// +// Description: Reads the FLASH and returns the Data. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Buffer to store the data read from FLASH +// uiOffset - Offset of FLASH from where data should be read +// uiNumBytes - Number of bytes to be read from the FLASH. +// +// Returns: +// OSAL_STATUS_SUCCESS - if FLASH read is successfull. +// - if failed. +//----------------------------------------------------------------------------- + +INT BeceemFlashBulkRead( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) +{ + UINT uiIndex = 0; + UINT uiBytesToRead = uiNumBytes; + INT Status = 0; + UINT uiPartOffset = 0; + + if(Adapter->device_removed ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device Got Removed "); + return -ENODEV; + } + + //Adding flash Base address +// uiOffset = uiOffset + GetFlashBaseAddr(Adapter); +#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE),( unsigned char *)pBuffer,uiNumBytes); + return Status; +#endif + + Adapter->SelectedChip = RESET_CHIP_SELECT; + + if(uiOffset % MAX_RW_SIZE) + { + BcmDoChipSelect(Adapter,uiOffset); + uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); + + uiBytesToRead = MAX_RW_SIZE - (uiOffset%MAX_RW_SIZE); + uiBytesToRead = MIN(uiNumBytes,uiBytesToRead); + + if(rdm(Adapter,uiPartOffset, (PCHAR)pBuffer+uiIndex,uiBytesToRead)) + { + Status = -1; + Adapter->SelectedChip = RESET_CHIP_SELECT; + return Status; + } + + uiIndex += uiBytesToRead; + uiOffset += uiBytesToRead; + uiNumBytes -= uiBytesToRead; + } + + while(uiNumBytes) + { + BcmDoChipSelect(Adapter,uiOffset); + uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); + + uiBytesToRead = MIN(uiNumBytes,MAX_RW_SIZE); + + if(rdm(Adapter,uiPartOffset, (PCHAR)pBuffer+uiIndex,uiBytesToRead)) + { + Status = -1; + break; + } + + + uiIndex += uiBytesToRead; + uiOffset += uiBytesToRead; + uiNumBytes -= uiBytesToRead; + + } + Adapter->SelectedChip = RESET_CHIP_SELECT; + return Status; +} + +//----------------------------------------------------------------------------- +// Procedure: BcmGetFlashSize +// +// Description: Finds the size of FLASH. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// UINT - size of the FLASH Storage. +// +//----------------------------------------------------------------------------- + +UINT BcmGetFlashSize(PMINI_ADAPTER Adapter) +{ +#if 0 + if(Adapter->bDDRInitDone) + { + return rdm(Adapter,FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT|FLASH_SIZE_ADDR); + } + + return rdm(Adapter,FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT|FLASH_SIZE_ADDR); +#endif + if(IsFlash2x(Adapter)) + return (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER)); + else + return 32*1024; + + +} + +//----------------------------------------------------------------------------- +// Procedure: BcmGetEEPROMSize +// +// Description: Finds the size of EEPROM. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// UINT - size of the EEPROM Storage. +// +//----------------------------------------------------------------------------- + +UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter) +{ + UINT uiData = 0; + UINT uiIndex = 0; + +// +// if EEPROM is present and already Calibrated,it will have +// 'BECM' string at 0th offset. +// To find the EEPROM size read the possible boundaries of the +// EEPROM like 4K,8K etc..accessing the EEPROM beyond its size will +// result in wrap around. So when we get the End of the EEPROM we will +// get 'BECM' string which is indeed at offset 0. +// + BeceemEEPROMBulkRead(Adapter,&uiData,0x0,4); + if(uiData == BECM) + { + for(uiIndex = 2;uiIndex <=256; uiIndex*=2) + { + BeceemEEPROMBulkRead(Adapter,&uiData,uiIndex*1024,4); + if(uiData == BECM) + { + return uiIndex*1024; + } + } + } + else + { +// +// EEPROM may not be present or not programmed +// + + uiData = 0xBABEFACE; + if(0 == BeceemEEPROMBulkWrite(Adapter,(PUCHAR)&uiData,0,4,TRUE)) + { + uiData = 0; + for(uiIndex = 2;uiIndex <=256; uiIndex*=2) + { + BeceemEEPROMBulkRead(Adapter,&uiData,uiIndex*1024,4); + if(uiData == 0xBABEFACE) + { + return uiIndex*1024; + } + } + } + + } + return 0; +} + +#if 0 +/***********************************************************************************/ +// +// WriteBeceemEEPROM: Writes 4 byte data to EEPROM offset. +// +// uiEEPROMOffset - Offset to be written to. +// uiData - Data to be written. +// +/***********************************************************************************/ + +INT WriteBeceemEEPROM(PMINI_ADAPTER Adapter,UINT uiEEPROMOffset, UINT uiData) +{ + INT Status = 0; + ULONG ulRdBk = 0; + ULONG ulRetryCount = 3; + UINT value; + + if(uiEEPROMOffset > EEPROM_END) + { + + return -1; + } + + uiData = htonl(uiData); + while(ulRetryCount--) + { + value = 0x06000000; + wrmalt(Adapter, 0x0F003018,&value, sizeof(value));//flush the EEPROM FIFO. + wrmalt(Adapter, 0x0F00301C,&uiData, sizeof(uiData)); + value = 0x3A000000 | uiEEPROMOffset; + wrmalt(Adapter, 0x0F003018,&value, sizeof(value)); + __udelay(100000); + //read back and verify. + Status = ReadBeceemEEPROM(Adapter,uiEEPROMOffset,(UINT *)&ulRdBk); + if(Status == 0) + { + if(ulRdBk == uiData) + { + return Status; + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WriteBeceemEEPROM: Readback does not match\n"); + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "WriteBeceemEEPROM: Readback failed\n"); + } + } + + return 0; +} +#endif + +//----------------------------------------------------------------------------- +// Procedure: FlashSectorErase +// +// Description: Finds the sector size of the FLASH. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// addr - sector start address +// numOfSectors - number of sectors to be erased. +// +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + + +INT FlashSectorErase(PMINI_ADAPTER Adapter, + UINT addr, + UINT numOfSectors) +{ + UINT iIndex = 0, iRetries = 0; + UINT uiStatus = 0; + UINT value; + + for(iIndex=0;iIndexuiSectorSize; + } + return 0; +} +//----------------------------------------------------------------------------- +// Procedure: flashByteWrite +// +// Description: Performs Byte by Byte write to flash +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiOffset - Offset of the flash where data needs to be written to. +// pData - Address of Data to be written. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT flashByteWrite( + PMINI_ADAPTER Adapter, + UINT uiOffset, + PVOID pData) +{ + + UINT uiStatus = 0; + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 + + UINT value; + ULONG ulData = *(PUCHAR)pData; + +// +// need not write 0xFF because write requires an erase and erase will +// make whole sector 0xFF. +// + + if(0xFF == ulData) + { + return STATUS_SUCCESS; + } + +// DumpDebug(NVM_RW,("flashWrite ====>\n")); + value = (FLASH_CMD_WRITE_ENABLE << 24); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write enable in FLASH_SPI_CMDQ_REG register fails"); + return STATUS_FAILURE; + } + if(wrm(Adapter,FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"DATA Write on FLASH_SPI_WRITEQ_REG fails"); + return STATUS_FAILURE; + } + value = (0x02000000 | (uiOffset & 0xFFFFFF)); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programming of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + + //__udelay(950); + + do + { + value = (FLASH_CMD_STATUS_REG_READ << 24); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + //__udelay(1); + if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails"); + return STATUS_FAILURE; + } + iRetries--; + if( iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); + + }while((uiStatus & 0x1) && (iRetries >0) ); + + if(uiStatus & 0x1) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE ; + } + + return STATUS_SUCCESS; +} + + + +//----------------------------------------------------------------------------- +// Procedure: flashWrite +// +// Description: Performs write to flash +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiOffset - Offset of the flash where data needs to be written to. +// pData - Address of Data to be written. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT flashWrite( + PMINI_ADAPTER Adapter, + UINT uiOffset, + PVOID pData) + +{ + //UINT uiStatus = 0; + //INT iRetries = 0; + //UINT uiReadBack = 0; + + UINT uiStatus = 0; + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 + + UINT value; + UINT uiErasePattern[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; +// +// need not write 0xFFFFFFFF because write requires an erase and erase will +// make whole sector 0xFFFFFFFF. +// + if (!OsalMemCompare(pData, uiErasePattern, MAX_RW_SIZE)) + { + return 0; + } + + value = (FLASH_CMD_WRITE_ENABLE << 24); + + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write Enable of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + if(wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Data write fails..."); + return STATUS_FAILURE; + } + + //__udelay(950); + do + { + value = (FLASH_CMD_STATUS_REG_READ << 24); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + //__udelay(1); + if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails"); + return STATUS_FAILURE; + } + + iRetries--; + //this will ensure that in there will be no changes in the current path. + //currently one rdm/wrm takes 125 us. + //Hence 125 *2 * FLASH_PER_RETRIES_DELAY > 3 ms(worst case delay) + //Hence current implementation cycle will intoduce no delay in current path + if(iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); + }while((uiStatus & 0x1) && (iRetries > 0)); + + if(uiStatus & 0x1) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE ; + } + + return STATUS_SUCCESS; +} + +//----------------------------------------------------------------------------- +// Procedure: flashByteWriteStatus +// +// Description: Performs byte by byte write to flash with write done status check +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiOffset - Offset of the flash where data needs to be written to. +// pData - Address of the Data to be written. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- +INT flashByteWriteStatus( + PMINI_ADAPTER Adapter, + UINT uiOffset, + PVOID pData) +{ + UINT uiStatus = 0; + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 + ULONG ulData = *(PUCHAR)pData; + UINT value; + +// +// need not write 0xFFFFFFFF because write requires an erase and erase will +// make whole sector 0xFFFFFFFF. +// + + if(0xFF == ulData) + { + return STATUS_SUCCESS; + } + + // DumpDebug(NVM_RW,("flashWrite ====>\n")); + + value = (FLASH_CMD_WRITE_ENABLE << 24); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write enable in FLASH_SPI_CMDQ_REG register fails"); + return STATUS_SUCCESS; + } + if(wrm(Adapter,FLASH_SPI_WRITEQ_REG, (PCHAR)&ulData, 4) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"DATA Write on FLASH_SPI_WRITEQ_REG fails"); + return STATUS_FAILURE; + } + value = (0x02000000 | (uiOffset & 0xFFFFFF)); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programming of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + + //msleep(1); + + do + { + value = (FLASH_CMD_STATUS_REG_READ << 24); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + //__udelay(1); + if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails"); + return STATUS_FAILURE; + } + + iRetries--; + if( iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); + }while((uiStatus & 0x1) && (iRetries > 0)); + + if(uiStatus & 0x1) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE ; + } + + return STATUS_SUCCESS; + +} +//----------------------------------------------------------------------------- +// Procedure: flashWriteStatus +// +// Description: Performs write to flash with write done status check +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiOffset - Offset of the flash where data needs to be written to. +// pData - Address of the Data to be written. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT flashWriteStatus( + PMINI_ADAPTER Adapter, + UINT uiOffset, + PVOID pData) +{ + UINT uiStatus = 0; + INT iRetries = MAX_FLASH_RETRIES * FLASH_PER_RETRIES_DELAY; //3 + //UINT uiReadBack = 0; + UINT value; + UINT uiErasePattern[4] = {0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF}; + +// +// need not write 0xFFFFFFFF because write requires an erase and erase will +// make whole sector 0xFFFFFFFF. +// + if (!OsalMemCompare(pData,uiErasePattern,MAX_RW_SIZE)) + { + return 0; + } + + value = (FLASH_CMD_WRITE_ENABLE << 24); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Write Enable of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + if(wrm(Adapter, uiOffset, (PCHAR)pData, MAX_RW_SIZE) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Data write fails..."); + return STATUS_FAILURE; + } + // __udelay(1); + + do + { + value = (FLASH_CMD_STATUS_REG_READ << 24); + if(wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Programing of FLASH_SPI_CMDQ_REG fails"); + return STATUS_FAILURE; + } + //__udelay(1); + if(rdmalt(Adapter, FLASH_SPI_READQ_REG, &uiStatus, sizeof(uiStatus)) < 0) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Reading status of FLASH_SPI_READQ_REG fails"); + return STATUS_FAILURE; + } + iRetries--; + //this will ensure that in there will be no changes in the current path. + //currently one rdm/wrm takes 125 us. + //Hence 125 *2 * FLASH_PER_RETRIES_DELAY >3 ms(worst case delay) + //Hence current implementation cycle will intoduce no delay in current path + if(iRetries && ((iRetries % FLASH_PER_RETRIES_DELAY) == 0)) + msleep(1); + }while((uiStatus & 0x1) && (iRetries >0)); + + if(uiStatus & 0x1) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Flash Write fails even after checking status for 200 times."); + return STATUS_FAILURE ; + } + + return STATUS_SUCCESS; +} + +//----------------------------------------------------------------------------- +// Procedure: BcmRestoreBlockProtectStatus +// +// Description: Restores the original block protection status. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// ulWriteStatus -Original status +// Returns: +// +// +//----------------------------------------------------------------------------- + +VOID BcmRestoreBlockProtectStatus(PMINI_ADAPTER Adapter,ULONG ulWriteStatus) +{ + UINT value; + value = (FLASH_CMD_WRITE_ENABLE<< 24); + wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); + + udelay(20); + value = (FLASH_CMD_STATUS_REG_WRITE<<24)|(ulWriteStatus << 16); + wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); + udelay(20); +} +//----------------------------------------------------------------------------- +// Procedure: BcmFlashUnProtectBlock +// +// Description: UnProtects appropriate blocks for writing. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiOffset - Offset of the flash where data needs to be written to. This should be Sector aligned. +// Returns: +// ULONG - Status value before UnProtect. +// +//----------------------------------------------------------------------------- +ULONG BcmFlashUnProtectBlock(PMINI_ADAPTER Adapter,UINT uiOffset, UINT uiLength) +{ + ULONG ulStatus = 0; + ULONG ulWriteStatus = 0; + UINT value; + uiOffset = uiOffset&0x000FFFFF; + +// +// Implemented only for 1MB Flash parts. +// + if(FLASH_PART_SST25VF080B == Adapter->ulFlashID) + { + // + // Get Current BP status. + // + value = (FLASH_CMD_STATUS_REG_READ << 24); + wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); + udelay(10); + // + // Read status will be WWXXYYZZ. We have to take only WW. + // + rdmalt(Adapter, FLASH_SPI_READQ_REG, (PUINT)&ulStatus, sizeof(ulStatus)); + ulStatus >>= 24; + ulWriteStatus = ulStatus; + + // + // Bits [5-2] give current block level protection status. + // Bit5: BP3 - DONT CARE + // BP2-BP0: 0 - NO PROTECTION, 1 - UPPER 1/16, 2 - UPPER 1/8, 3 - UPPER 1/4 + // 4 - UPPER 1/2. 5 to 7 - ALL BLOCKS + // + + if(ulStatus) + { + if((uiOffset+uiLength) <= 0x80000) + { + // + // Offset comes in lower half of 1MB. Protect the upper half. + // Clear BP1 and BP0 and set BP2. + // + ulWriteStatus |= (0x4<<2); + ulWriteStatus &= ~(0x3<<2); + } + else if((uiOffset+uiLength) <= 0xC0000) + { + // + // Offset comes below Upper 1/4. Upper 1/4 can be protected. + // Clear BP2 and set BP1 and BP0. + // + ulWriteStatus |= (0x3<<2); + ulWriteStatus &= ~(0x1<<4); + } + else if((uiOffset+uiLength) <= 0xE0000) + { + // + // Offset comes below Upper 1/8. Upper 1/8 can be protected. + // Clear BP2 and BP0 and set BP1 + // + ulWriteStatus |= (0x1<<3); + ulWriteStatus &= ~(0x5<<2); + + } + else if((uiOffset+uiLength) <= 0xF0000) + { + // + // Offset comes below Upper 1/16. Only upper 1/16 can be protected. + // Set BP0 and Clear BP2,BP1. + // + ulWriteStatus |= (0x1<<2); + ulWriteStatus &= ~(0x3<<3); + } + else + { + // + // Unblock all. + // Clear BP2,BP1 and BP0. + // + ulWriteStatus &= ~(0x7<<2); + } + + value = (FLASH_CMD_WRITE_ENABLE<< 24); + wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); + udelay(20); + value = (FLASH_CMD_STATUS_REG_WRITE<<24)|(ulWriteStatus << 16); + wrmalt(Adapter, FLASH_SPI_CMDQ_REG, &value, sizeof(value)); + udelay(20); + + } + + } + return ulStatus; +} +//----------------------------------------------------------------------------- +// Procedure: BeceemFlashBulkWrite +// +// Description: Performs write to the flash +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Data to be written. +// uiOffset - Offset of the flash where data needs to be written to. +// uiNumBytes - Number of bytes to be written. +// bVerify - read verify flag. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT BeceemFlashBulkWrite( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) +{ + PCHAR pTempBuff = NULL; + PUCHAR pcBuffer = (PUCHAR)pBuffer; + UINT uiIndex = 0; + UINT uiOffsetFromSectStart = 0; + UINT uiSectAlignAddr = 0; + UINT uiCurrSectOffsetAddr = 0; + UINT uiSectBoundary = 0; + UINT uiNumSectTobeRead = 0; + UCHAR ucReadBk[16] = {0}; + ULONG ulStatus = 0; + INT Status = STATUS_SUCCESS; + UINT uiTemp = 0; + UINT index = 0; + UINT uiPartOffset = 0; + #if 0 + struct timeval tv1 = {0}; + struct timeval tv2 = {0}; + + struct timeval tr = {0}; + struct timeval te = {0}; + struct timeval tw = {0}; + struct timeval twv = {0}; + #endif + +#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_write((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE),( unsigned char *)pBuffer,uiNumBytes); + return Status; +#endif + + uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); + + //Adding flash Base address +// uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + + uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); + uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); + uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; + + //pTempBuff = OsalMemAlloc(MAX_SECTOR_SIZE,'!MVN'); + pTempBuff = OsalMemAlloc(Adapter->uiSectorSize ,'!MVN'); + if(NULL == pTempBuff) + { + goto BeceemFlashBulkWrite_EXIT; + } +// +// check if the data to be written is overlapped accross sectors +// + if(uiOffset+uiNumBytes < uiSectBoundary) + { + uiNumSectTobeRead = 1; + } + else + { + // Number of sectors = Last sector start address/First sector start address + uiNumSectTobeRead = (uiCurrSectOffsetAddr+uiNumBytes)/Adapter->uiSectorSize; + if((uiCurrSectOffsetAddr+uiNumBytes)%Adapter->uiSectorSize) + { + uiNumSectTobeRead++; + } + } + #if 1 + //Check whether Requested sector is writable or not in case of flash2x write. But if write call is + // for DSD calibration, allow it without checking of sector permission + + if(IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) + { + index = 0; + uiTemp = uiNumSectTobeRead ; + while(uiTemp) + { + if(IsOffsetWritable(Adapter, uiOffsetFromSectStart + index * Adapter->uiSectorSize ) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Sector Starting at offset <0X%X> is not writable", + (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); + Status = SECTOR_IS_NOT_WRITABLE; + goto BeceemFlashBulkWrite_EXIT; + } + uiTemp = uiTemp - 1; + index = index + 1 ; + } + } + #endif + Adapter->SelectedChip = RESET_CHIP_SELECT; + while(uiNumSectTobeRead) + { + //do_gettimeofday(&tv1); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nTime In start of write :%ld ms\n",(tv1.tv_sec *1000 + tv1.tv_usec /1000)); + uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); + + BcmDoChipSelect(Adapter,uiSectAlignAddr); + + if(0 != BeceemFlashBulkRead(Adapter, + (PUINT)pTempBuff, + uiOffsetFromSectStart, + Adapter->uiSectorSize)) + { + Status = -1; + goto BeceemFlashBulkWrite_EXIT; + } + + //do_gettimeofday(&tr); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Read :%ld ms\n", (tr.tv_sec *1000 + tr.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); + + ulStatus = BcmFlashUnProtectBlock(Adapter,uiSectAlignAddr,Adapter->uiSectorSize); + + + if(uiNumSectTobeRead > 1) + { + + OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + pcBuffer += ((uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr))); + uiNumBytes -= (uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + } + else + { + OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); + } + + if(IsFlash2x(Adapter)) + { + SaveHeaderIfPresent(Adapter,(PUCHAR)pTempBuff,uiOffsetFromSectStart); + } + + FlashSectorErase(Adapter,uiPartOffset,1); + //do_gettimeofday(&te); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by Erase :%ld ms\n", (te.tv_sec *1000 + te.tv_usec/1000) - (tr.tv_sec *1000 + tr.tv_usec/1000)); + + for(uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex +=Adapter->ulFlashWriteSize) + { + if(Adapter->device_removed) + { + Status = -1; + goto BeceemFlashBulkWrite_EXIT; + } + if(STATUS_SUCCESS != (*Adapter->fpFlashWrite)(Adapter,uiPartOffset+uiIndex,(&pTempBuff[uiIndex]))) + { + Status = -1; + goto BeceemFlashBulkWrite_EXIT; + } + } + + //do_gettimeofday(&tw); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash :%ld ms\n", (tw.tv_sec *1000 + tw.tv_usec/1000) - (te.tv_sec *1000 + te.tv_usec/1000)); + for(uiIndex = 0;uiIndex < Adapter->uiSectorSize;uiIndex += MAX_RW_SIZE) + { + if(STATUS_SUCCESS == BeceemFlashBulkRead(Adapter,(PUINT)ucReadBk,uiOffsetFromSectStart+uiIndex,MAX_RW_SIZE)) + { + if(Adapter->ulFlashWriteSize == 1) + { + UINT uiReadIndex = 0; + for(uiReadIndex = 0; uiReadIndex < 16; uiReadIndex++) + { + if(ucReadBk[uiReadIndex] != pTempBuff[uiIndex+uiReadIndex]) + { + if(STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter,uiPartOffset+uiIndex+uiReadIndex,&pTempBuff[uiIndex+uiReadIndex])) + { + Status = STATUS_FAILURE; + goto BeceemFlashBulkWrite_EXIT; + } + } + } + } + else + { + if(OsalMemCompare(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) + { + if(STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter,uiPartOffset+uiIndex,&pTempBuff[uiIndex])) + { + Status = STATUS_FAILURE; + goto BeceemFlashBulkWrite_EXIT; + } + } + } + } + } + //do_gettimeofday(&twv); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken in Write to Flash verification :%ld ms\n", (twv.tv_sec *1000 + twv.tv_usec/1000) - (tw.tv_sec *1000 + tw.tv_usec/1000)); + + + if(ulStatus) + { + BcmRestoreBlockProtectStatus(Adapter,ulStatus); + ulStatus = 0; + } + + uiCurrSectOffsetAddr = 0; + uiSectAlignAddr = uiSectBoundary; + uiSectBoundary += Adapter->uiSectorSize; + uiOffsetFromSectStart += Adapter->uiSectorSize; + uiNumSectTobeRead--; + } + //do_gettimeofday(&tv2); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Time after Write :%ld ms\n",(tv2.tv_sec *1000 + tv2.tv_usec/1000)); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Total time taken by in Write is :%ld ms\n", (tv2.tv_sec *1000 + tv2.tv_usec/1000) - (tv1.tv_sec *1000 + tv1.tv_usec/1000)); +// +// Cleanup. +// +BeceemFlashBulkWrite_EXIT: + if(ulStatus) + { + BcmRestoreBlockProtectStatus(Adapter,ulStatus); + } + if(pTempBuff) + { + OsalMemFree(pTempBuff,Adapter->uiSectorSize); + } + + Adapter->SelectedChip = RESET_CHIP_SELECT; + return Status; +} + + +//----------------------------------------------------------------------------- +// Procedure: BeceemFlashBulkWriteStatus +// +// Description: Writes to Flash. Checks the SPI status after each write. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Data to be written. +// uiOffset - Offset of the flash where data needs to be written to. +// uiNumBytes - Number of bytes to be written. +// bVerify - read verify flag. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT BeceemFlashBulkWriteStatus( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) +{ + PCHAR pTempBuff = NULL; + PUCHAR pcBuffer = (PUCHAR)pBuffer; + UINT uiIndex = 0; + UINT uiOffsetFromSectStart = 0; + UINT uiSectAlignAddr = 0; + UINT uiCurrSectOffsetAddr = 0; + UINT uiSectBoundary = 0; + UINT uiNumSectTobeRead = 0; + UCHAR ucReadBk[16] = {0}; + ULONG ulStatus = 0; + UINT Status = STATUS_SUCCESS; + UINT uiTemp = 0; + UINT index = 0; + UINT uiPartOffset = 0; + + uiOffsetFromSectStart = uiOffset & ~(Adapter->uiSectorSize - 1); + + //uiOffset += Adapter->ulFlashCalStart; + //Adding flash Base address +// uiOffset = uiOffset + GetFlashBaseAddr(Adapter); + + uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); + uiCurrSectOffsetAddr = uiOffset & (Adapter->uiSectorSize - 1); + uiSectBoundary = uiSectAlignAddr + Adapter->uiSectorSize; + + + +// pTempBuff = OsalMemAlloc(MAX_SECTOR_SIZE,'!MVN'); + pTempBuff = OsalMemAlloc(Adapter->uiSectorSize,'!MVN'); + if(NULL == pTempBuff) + { + goto BeceemFlashBulkWriteStatus_EXIT; + } +// +// check if the data to be written is overlapped accross sectors +// + if(uiOffset+uiNumBytes < uiSectBoundary) + { + uiNumSectTobeRead = 1; + } + else + { +// Number of sectors = Last sector start address/First sector start address + uiNumSectTobeRead = (uiCurrSectOffsetAddr+uiNumBytes)/Adapter->uiSectorSize; + if((uiCurrSectOffsetAddr+uiNumBytes)%Adapter->uiSectorSize) + { + uiNumSectTobeRead++; + } + } + + if(IsFlash2x(Adapter) && (Adapter->bAllDSDWriteAllow == FALSE)) + { + index = 0; + uiTemp = uiNumSectTobeRead ; + while(uiTemp) + { + if(IsOffsetWritable(Adapter,uiOffsetFromSectStart + index * Adapter->uiSectorSize ) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Sector Starting at offset <0X%x> is not writable", + (uiOffsetFromSectStart + index * Adapter->uiSectorSize)); + Status = SECTOR_IS_NOT_WRITABLE; + goto BeceemFlashBulkWriteStatus_EXIT; + } + uiTemp = uiTemp - 1; + index = index + 1 ; + } + } + + Adapter->SelectedChip = RESET_CHIP_SELECT; + while(uiNumSectTobeRead) + { + uiPartOffset = (uiSectAlignAddr & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); + + BcmDoChipSelect(Adapter,uiSectAlignAddr); + if(0 != BeceemFlashBulkRead(Adapter, + (PUINT)pTempBuff, + uiOffsetFromSectStart, + Adapter->uiSectorSize)) + { + Status = -1; + goto BeceemFlashBulkWriteStatus_EXIT; + } + + ulStatus = BcmFlashUnProtectBlock(Adapter,uiOffsetFromSectStart,Adapter->uiSectorSize); + + if(uiNumSectTobeRead > 1) + { + + OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + pcBuffer += ((uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr))); + uiNumBytes -= (uiSectBoundary-(uiSectAlignAddr+uiCurrSectOffsetAddr)); + } + else + { + OsalMemMove(&pTempBuff[uiCurrSectOffsetAddr],pcBuffer,uiNumBytes); + } + + if(IsFlash2x(Adapter)) + { + SaveHeaderIfPresent(Adapter,(PUCHAR)pTempBuff,uiOffsetFromSectStart); + } + + FlashSectorErase(Adapter,uiPartOffset,1); + + for(uiIndex = 0; uiIndex < Adapter->uiSectorSize; uiIndex +=Adapter->ulFlashWriteSize) + + { + if(Adapter->device_removed) + { + Status = -1; + goto BeceemFlashBulkWriteStatus_EXIT; + } + + if(STATUS_SUCCESS != (*Adapter->fpFlashWriteWithStatusCheck)(Adapter,uiPartOffset+uiIndex,&pTempBuff[uiIndex])) + { + Status = -1; + goto BeceemFlashBulkWriteStatus_EXIT; + } + } + + if(bVerify) + { + for(uiIndex = 0;uiIndex < Adapter->uiSectorSize;uiIndex += MAX_RW_SIZE) + { +#if 0 + if(0 == BeceemFlashBulkRead(Adapter,uiReadBk,uiOffsetFromSectStart+uiIndex + Adapter->ulFlashCalStart ,MAX_RW_SIZE)) + { + for(uiReadIndex = 0;uiReadIndex < 4; uiReadIndex++) + { + if(*((PUINT)&pTempBuff[uiIndex+uiReadIndex*4]) != uiReadBk[uiReadIndex]) + { + Status = -1; + goto BeceemFlashBulkWriteStatus_EXIT; + + } + } + + } +#endif + + if(STATUS_SUCCESS == BeceemFlashBulkRead(Adapter,(PUINT)ucReadBk,uiOffsetFromSectStart+uiIndex,MAX_RW_SIZE)) + { + if(OsalMemCompare(ucReadBk,&pTempBuff[uiIndex],MAX_RW_SIZE)) + { + Status = STATUS_FAILURE; + goto BeceemFlashBulkWriteStatus_EXIT; + } + + } + + } + } + + if(ulStatus) + { + BcmRestoreBlockProtectStatus(Adapter,ulStatus); + ulStatus = 0; + } + + uiCurrSectOffsetAddr = 0; + uiSectAlignAddr = uiSectBoundary; + uiSectBoundary += Adapter->uiSectorSize; + uiOffsetFromSectStart += Adapter->uiSectorSize; + uiNumSectTobeRead--; + } +// +// Cleanup. +// +BeceemFlashBulkWriteStatus_EXIT: + if(ulStatus) + { + BcmRestoreBlockProtectStatus(Adapter,ulStatus); + } + if(pTempBuff) + { + OsalMemFree(pTempBuff,Adapter->uiSectorSize); + } + Adapter->SelectedChip = RESET_CHIP_SELECT; + return Status; + +} + +//----------------------------------------------------------------------------- +// Procedure: PropagateCalParamsFromEEPROMToMemory +// +// Description: Dumps the calibration section of EEPROM to DDR. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + + +INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter) +{ + PCHAR pBuff = OsalMemAlloc(BUFFER_4K,'3MVN'); + UINT uiEepromSize = 0; + UINT uiIndex = 0; + UINT uiBytesToCopy = 0; + UINT uiCalStartAddr = EEPROM_CALPARAM_START; + UINT uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; + UINT value; + INT Status = 0; + if(pBuff == NULL) + { + return -1; + } + + if(0 != BeceemEEPROMBulkRead(Adapter,&uiEepromSize,EEPROM_SIZE_OFFSET,4)) + { + + OsalMemFree(pBuff,BUFFER_4K); + return -1; + } + + uiEepromSize >>= 16; + if(uiEepromSize > 1024*1024) + { + OsalMemFree(pBuff,BUFFER_4K); + return -1; + } + + + uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); + + while(uiBytesToCopy) + { + if(0 != BeceemEEPROMBulkRead(Adapter,(PUINT)pBuff,uiCalStartAddr,uiBytesToCopy)) + { + Status = -1; + break; + } + wrm(Adapter,uiMemoryLoc,(PCHAR)(((PULONG)pBuff)+uiIndex),uiBytesToCopy); + uiMemoryLoc += uiBytesToCopy; + uiEepromSize -= uiBytesToCopy; + uiCalStartAddr += uiBytesToCopy; + uiIndex += uiBytesToCopy/4; + uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); + + } + value = 0xbeadbead; + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC-4,&value, sizeof(value)); + value = 0xbeadbead; + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC-8,&value, sizeof(value)); + OsalMemFree(pBuff,MAX_RW_SIZE); + + return Status; + +} + +//----------------------------------------------------------------------------- +// Procedure: PropagateCalParamsFromFlashToMemory +// +// Description: Dumps the calibration section of EEPROM to DDR. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT PropagateCalParamsFromFlashToMemory(PMINI_ADAPTER Adapter) +{ + PCHAR pBuff, pPtr; + UINT uiEepromSize = 0; + UINT uiBytesToCopy = 0; + //UINT uiIndex = 0; + UINT uiCalStartAddr = EEPROM_CALPARAM_START; + UINT uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; + UINT value; + INT Status = 0; +// +// Write the signature first. This will ensure firmware does not access EEPROM. +// + value = 0xbeadbead; + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 4, &value, sizeof(value)); + value = 0xbeadbead; + wrmalt(Adapter, EEPROM_CAL_DATA_INTERNAL_LOC - 8, &value, sizeof(value)); + + if(0 != BeceemNVMRead(Adapter,&uiEepromSize,EEPROM_SIZE_OFFSET, 4)) + { + return -1; + } + uiEepromSize = ntohl(uiEepromSize); + uiEepromSize >>= 16; + +// +// subtract the auto init section size +// + uiEepromSize -= EEPROM_CALPARAM_START; + + if(uiEepromSize > 1024*1024) + { + return -1; + } + + pBuff = OsalMemAlloc(uiEepromSize, 0); + + if ( pBuff == NULL ) + { + return -1; + } + + if(0 != BeceemNVMRead(Adapter,(PUINT)pBuff,uiCalStartAddr, uiEepromSize)) + { + OsalMemFree(pBuff, 0); + return -1; + } + + pPtr = pBuff; + + uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); + + while(uiBytesToCopy) + { + Status = wrm(Adapter,uiMemoryLoc,(PCHAR)pPtr,uiBytesToCopy); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"wrm failed with status :%d",Status); + break; + } + + pPtr += uiBytesToCopy; + uiEepromSize -= uiBytesToCopy; + uiMemoryLoc += uiBytesToCopy; + uiBytesToCopy = MIN(BUFFER_4K,uiEepromSize); + } + + OsalMemFree(pBuff, 0); + return Status; + +} + +//----------------------------------------------------------------------------- +// Procedure: BeceemEEPROMReadBackandVerify +// +// Description: Read back the data written and verifies. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Data to be written. +// uiOffset - Offset of the flash where data needs to be written to. +// uiNumBytes - Number of bytes to be written. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT BeceemEEPROMReadBackandVerify( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) +{ + UINT uiRdbk = 0; + UINT uiIndex = 0; + UINT uiData = 0; + UINT auiData[4] = {0}; + + while(uiNumBytes) + { + if(Adapter->device_removed ) + { + return -1; + } + + if(uiNumBytes >= MAX_RW_SIZE) + {// for the requests more than or equal to MAX_RW_SIZE bytes, use bulk read function to make the access faster. + BeceemEEPROMBulkRead(Adapter,&auiData[0],uiOffset,MAX_RW_SIZE); + + if(OsalMemCompare(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) + { + // re-write + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)(pBuffer+uiIndex),uiOffset,MAX_RW_SIZE,FALSE); + mdelay(3); + BeceemEEPROMBulkRead(Adapter,&auiData[0],uiOffset,MAX_RW_SIZE); + + if(OsalMemCompare(&pBuffer[uiIndex],&auiData[0],MAX_RW_SIZE)) + { + return -1; + } + } + uiOffset += MAX_RW_SIZE; + uiNumBytes -= MAX_RW_SIZE; + uiIndex += 4; + + } + else if(uiNumBytes >= 4) + { + BeceemEEPROMBulkRead(Adapter,&uiData,uiOffset,4); + if(uiData != pBuffer[uiIndex]) + { + //re-write + BeceemEEPROMBulkWrite(Adapter,(PUCHAR)(pBuffer+uiIndex),uiOffset,4,FALSE); + mdelay(3); + BeceemEEPROMBulkRead(Adapter,&uiData,uiOffset,4); + if(uiData != pBuffer[uiIndex]) + { + return -1; + } + } + uiOffset += 4; + uiNumBytes -= 4; + uiIndex++; + + } + else + { // Handle the reads less than 4 bytes... + uiData = 0; + OsalMemMove(&uiData,((PUCHAR)pBuffer)+(uiIndex*sizeof(UINT)),uiNumBytes); + BeceemEEPROMBulkRead(Adapter,&uiRdbk,uiOffset,4); + + if(memcmp(&uiData, &uiRdbk, uiNumBytes)) + return -1; + + uiNumBytes = 0; + } + + } + + return 0; +} + +VOID BcmSwapWord(UINT *ptr1) { + + UINT tempval = (UINT)*ptr1; + char *ptr2 = (char *)&tempval; + char *ptr = (char *)ptr1; + + ptr[0] = ptr2[3]; + ptr[1] = ptr2[2]; + ptr[2] = ptr2[1]; + ptr[3] = ptr2[0]; +} + +//----------------------------------------------------------------------------- +// Procedure: BeceemEEPROMWritePage +// +// Description: Performs page write (16bytes) to the EEPROM +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiData - Data to be written. +// uiOffset - Offset of the EEPROM where data needs to be written to. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- +INT BeceemEEPROMWritePage( PMINI_ADAPTER Adapter, UINT uiData[], UINT uiOffset ) +{ + UINT uiRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + UINT uiStatus = 0; + UCHAR uiEpromStatus = 0; + UINT value =0 ; + + /* Flush the Write/Read/Cmd queues. */ + value = ( EEPROM_WRITE_QUEUE_FLUSH | EEPROM_CMD_QUEUE_FLUSH | EEPROM_READ_QUEUE_FLUSH ); + wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value)); + value = 0 ; + wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value) ); + + /* Clear the Empty/Avail/Full bits. After this it has been confirmed + * that the bit was cleared by reading back the register. See NOTE below. + * We also clear the Read queues as we do a EEPROM status register read + * later. */ + value = ( EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL | EEPROM_READ_DATA_AVAIL | EEPROM_READ_DATA_FULL ) ; + wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&value, sizeof(value)); + + /* Enable write */ + value = EEPROM_WRITE_ENABLE ; + wrmalt( Adapter, EEPROM_CMDQ_SPI_REG,&value, sizeof(value) ); + + /* We can write back to back 8bits * 16 into the queue and as we have + * checked for the queue to be empty we can write in a burst. */ + + value = uiData[0]; + BcmSwapWord(&value); + wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + + value = uiData[1]; + BcmSwapWord(&value); + wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + + value = uiData[2]; + BcmSwapWord(&value); + wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + + value = uiData[3]; + BcmSwapWord(&value); + wrm( Adapter, EEPROM_WRITE_DATAQ_REG, (PUCHAR)&value, 4); + + /* NOTE : After this write, on readback of EEPROM_SPI_Q_STATUS1_REG + * shows that we see 7 for the EEPROM data write. Which means that + * queue got full, also space is available as well as the queue is empty. + * This may happen in sequence. */ + value = EEPROM_16_BYTE_PAGE_WRITE | uiOffset ; + wrmalt( Adapter, EEPROM_CMDQ_SPI_REG, &value, sizeof(value) ); + + /* Ideally we should loop here without tries and eventually succeed. + * What we are checking if the previous write has completed, and this + * may take time. We should wait till the Empty bit is set. */ + uiStatus = 0; + rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&uiStatus, sizeof(uiStatus)) ; + while ( ( uiStatus & EEPROM_WRITE_QUEUE_EMPTY ) == 0 ) + { + uiRetries--; + if ( uiRetries == 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, %d retries failed.\n", uiStatus, MAX_EEPROM_RETRIES *RETRIES_PER_DELAY); + return STATUS_FAILURE ; + } + + if( !(uiRetries%RETRIES_PER_DELAY) ) + msleep(1); + + uiStatus = 0; + rdmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG,&uiStatus, sizeof(uiStatus)) ; + if(Adapter->device_removed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Modem got removed hence exiting from loop...."); + return -ENODEV; + } + + } + + if ( uiRetries != 0 ) + { + /* Clear the ones that are set - either, Empty/Full/Avail bits */ + value = ( uiStatus & ( EEPROM_WRITE_QUEUE_EMPTY | EEPROM_WRITE_QUEUE_AVAIL | EEPROM_WRITE_QUEUE_FULL ) ); + wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + } + + /* Here we should check if the EEPROM status register is correct before + * proceeding. Bit 0 in the EEPROM Status register should be 0 before + * we proceed further. A 1 at Bit 0 indicates that the EEPROM is busy + * with the previous write. Note also that issuing this read finally + * means the previous write to the EEPROM has completed. */ + uiRetries = MAX_EEPROM_RETRIES*RETRIES_PER_DELAY; + uiEpromStatus = 0; + while ( uiRetries != 0 ) + { + uiEpromStatus = ReadEEPROMStatusRegister( Adapter) ; + if(Adapter->device_removed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Modem has got removed hence exiting from loop..."); + return -ENODEV; + } + if ( ( EEPROM_STATUS_REG_WRITE_BUSY & uiEpromStatus ) == 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "EEPROM status register = %x tries = %d\n", uiEpromStatus, (MAX_EEPROM_RETRIES * RETRIES_PER_DELAY- uiRetries) ); + return STATUS_SUCCESS ; + } + uiRetries--; + if ( uiRetries == 0 ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "0x0f003004 = %x, for EEPROM status read %d retries failed.\n", uiEpromStatus, MAX_EEPROM_RETRIES *RETRIES_PER_DELAY); + return STATUS_FAILURE ; + } + uiEpromStatus = 0; + if( !(uiRetries%RETRIES_PER_DELAY) ) + msleep(1); + } + + return STATUS_SUCCESS ; +} /* BeceemEEPROMWritePage */ + + +//----------------------------------------------------------------------------- +// Procedure: BeceemEEPROMBulkWrite +// +// Description: Performs write to the EEPROM +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Data to be written. +// uiOffset - Offset of the EEPROM where data needs to be written to. +// uiNumBytes - Number of bytes to be written. +// bVerify - read verify flag. +// Returns: +// OSAL_STATUS_CODE +// +//----------------------------------------------------------------------------- + +INT BeceemEEPROMBulkWrite( + PMINI_ADAPTER Adapter, + PUCHAR pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) +{ + UINT uiBytesToCopy = uiNumBytes; + //UINT uiRdbk = 0; + UINT uiData[4] = {0}; + UINT uiIndex = 0; + UINT uiTempOffset = 0; + UINT uiExtraBytes = 0; + //PUINT puiBuffer = (PUINT)pBuffer; + //INT value; + + if(uiOffset%MAX_RW_SIZE && uiBytesToCopy) + { + uiTempOffset = uiOffset - (uiOffset%MAX_RW_SIZE); + uiExtraBytes = uiOffset-uiTempOffset; + + + BeceemEEPROMBulkRead(Adapter,&uiData[0],uiTempOffset,MAX_RW_SIZE); + + if(uiBytesToCopy >= (16 -uiExtraBytes)) + { + OsalMemMove((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,MAX_RW_SIZE- uiExtraBytes); + + if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiTempOffset ) ) + return STATUS_FAILURE; + + uiBytesToCopy -= (MAX_RW_SIZE - uiExtraBytes); + uiIndex += (MAX_RW_SIZE - uiExtraBytes); + uiOffset += (MAX_RW_SIZE - uiExtraBytes); + } + else + { + OsalMemMove((((PUCHAR)&uiData[0])+uiExtraBytes),pBuffer,uiBytesToCopy); + + if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiTempOffset ) ) + return STATUS_FAILURE; + + uiIndex += uiBytesToCopy; + uiOffset += uiBytesToCopy; + uiBytesToCopy = 0; + } + + + } + + while(uiBytesToCopy) + { + if(Adapter->device_removed) + { + return -1; + } + + if(uiBytesToCopy >= MAX_RW_SIZE) + { + + if (STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, (PUINT) &pBuffer[uiIndex], uiOffset ) ) + return STATUS_FAILURE; + + uiIndex += MAX_RW_SIZE; + uiOffset += MAX_RW_SIZE; + uiBytesToCopy -= MAX_RW_SIZE; + } + else + { + // + // To program non 16byte aligned data, read 16byte and then update. + // + BeceemEEPROMBulkRead(Adapter,&uiData[0],uiOffset,16); + OsalMemMove(&uiData[0],pBuffer+uiIndex,uiBytesToCopy); + + + if ( STATUS_FAILURE == BeceemEEPROMWritePage( Adapter, uiData, uiOffset ) ) + return STATUS_FAILURE; + uiBytesToCopy = 0; + } + + } + + return 0; +} + +//----------------------------------------------------------------------------- +// Procedure: BeceemNVMRead +// +// Description: Reads n number of bytes from NVM. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Buffer to store the data read from NVM +// uiOffset - Offset of NVM from where data should be read +// uiNumBytes - Number of bytes to be read from the NVM. +// +// Returns: +// OSAL_STATUS_SUCCESS - if NVM read is successfull. +// - if failed. +//----------------------------------------------------------------------------- + +INT BeceemNVMRead( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes) +{ + INT Status = 0; +#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT uiTemp = 0, value; +#endif + + if(Adapter->eNVMType == NVM_FLASH) + { + if(Adapter->bFlashRawRead == FALSE) + { + if (IsSectionExistInVendorInfo(Adapter,Adapter->eActiveDSD)) + return vendorextnReadSection(Adapter,(PUCHAR)pBuffer,Adapter->eActiveDSD,uiOffset,uiNumBytes); + uiOffset = uiOffset+ Adapter->ulFlashCalStart ; + } +#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_read((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE),( unsigned char *)pBuffer,uiNumBytes); +#else + + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + Status = BeceemFlashBulkRead(Adapter, + pBuffer, + uiOffset, + uiNumBytes); + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); +#endif + } + else if(Adapter->eNVMType == NVM_EEPROM) + { + Status = BeceemEEPROMBulkRead(Adapter, + pBuffer, + uiOffset, + uiNumBytes); + } + else + { + Status = -1; + } + return Status; +} + +//----------------------------------------------------------------------------- +// Procedure: BeceemNVMWrite +// +// Description: Writes n number of bytes to NVM. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pBuffer - Buffer contains the data to be written. +// uiOffset - Offset of NVM where data to be written to. +// uiNumBytes - Number of bytes to be written.. +// +// Returns: +// OSAL_STATUS_SUCCESS - if NVM write is successfull. +// - if failed. +//----------------------------------------------------------------------------- + +INT BeceemNVMWrite( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify) +{ + INT Status = 0; + UINT uiTemp = 0; + UINT uiMemoryLoc = EEPROM_CAL_DATA_INTERNAL_LOC; + UINT uiIndex = 0; +#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT value; +#endif + UINT uiFlashOffset = 0; + + if(Adapter->eNVMType == NVM_FLASH) + { + if (IsSectionExistInVendorInfo(Adapter,Adapter->eActiveDSD)) + Status = vendorextnWriteSection(Adapter,(PUCHAR)pBuffer,Adapter->eActiveDSD,uiOffset,uiNumBytes,bVerify); + else + { + uiFlashOffset = uiOffset + Adapter->ulFlashCalStart; + +#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_write((uiFlashOffset/FLASH_PART_SIZE), (uiFlashOffset % FLASH_PART_SIZE), (unsigned char *)pBuffer,uiNumBytes); +#else + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80, &value, sizeof(value)); + + if(Adapter->bStatusWrite == TRUE) + { + Status = BeceemFlashBulkWriteStatus(Adapter, + pBuffer, + uiFlashOffset, + uiNumBytes , + bVerify); + } + else + { + + Status = BeceemFlashBulkWrite(Adapter, + pBuffer, + uiFlashOffset, + uiNumBytes, + bVerify); + } +#endif + } + + + if(uiOffset >= EEPROM_CALPARAM_START) + { + uiMemoryLoc += (uiOffset - EEPROM_CALPARAM_START); + while(uiNumBytes) + { + if(uiNumBytes > BUFFER_4K) + { + wrm(Adapter,(uiMemoryLoc+uiIndex),(PCHAR)(pBuffer+(uiIndex/4)),BUFFER_4K); + uiNumBytes -= BUFFER_4K; + uiIndex += BUFFER_4K; + } + else + { + wrm(Adapter,uiMemoryLoc+uiIndex,(PCHAR)(pBuffer+(uiIndex/4)),uiNumBytes); + uiNumBytes = 0; + break; + } + } + } + else + { + if((uiOffset+uiNumBytes) > EEPROM_CALPARAM_START) + { + ULONG ulBytesTobeSkipped = 0; + PUCHAR pcBuffer = (PUCHAR)pBuffer;// char pointer to take care of odd byte cases. + uiNumBytes -= (EEPROM_CALPARAM_START - uiOffset); + ulBytesTobeSkipped += (EEPROM_CALPARAM_START - uiOffset); + uiOffset += (EEPROM_CALPARAM_START - uiOffset); + while(uiNumBytes) + { + if(uiNumBytes > BUFFER_4K) + { + wrm(Adapter,uiMemoryLoc+uiIndex,(PCHAR )&pcBuffer[ulBytesTobeSkipped+uiIndex],BUFFER_4K); + uiNumBytes -= BUFFER_4K; + uiIndex += BUFFER_4K; + } + else + { + wrm(Adapter,uiMemoryLoc+uiIndex,(PCHAR)&pcBuffer[ulBytesTobeSkipped+uiIndex],uiNumBytes); + uiNumBytes = 0; + break; + } + } + + } + } + + // restore the values. + wrmalt(Adapter,0x0f000C80,&uiTemp, sizeof(uiTemp)); + } + else if(Adapter->eNVMType == NVM_EEPROM) + { + Status = BeceemEEPROMBulkWrite(Adapter, + (PUCHAR)pBuffer, + uiOffset, + uiNumBytes, + bVerify); + if(bVerify) + { + Status = BeceemEEPROMReadBackandVerify(Adapter,(PUINT)pBuffer,uiOffset,uiNumBytes); + } + } + else + { + Status = -1; + } + return Status; +} + +//----------------------------------------------------------------------------- +// Procedure: BcmUpdateSectorSize +// +// Description: Updates the sector size to FLASH. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// uiSectorSize - sector size +// +// Returns: +// OSAL_STATUS_SUCCESS - if NVM write is successfull. +// - if failed. +//----------------------------------------------------------------------------- + +INT BcmUpdateSectorSize(PMINI_ADAPTER Adapter,UINT uiSectorSize) +{ + INT Status = -1; + FLASH_CS_INFO sFlashCsInfo = {0}; + UINT uiTemp = 0; + + UINT uiSectorSig = 0; + UINT uiCurrentSectorSize = 0; + + UINT value; + + + + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + +// +// Before updating the sector size in the reserved area, check if already present. +// + BeceemFlashBulkRead(Adapter,(PUINT)&sFlashCsInfo,Adapter->ulFlashControlSectionStart,sizeof(sFlashCsInfo)); + uiSectorSig = ntohl(sFlashCsInfo.FlashSectorSizeSig); + uiCurrentSectorSize = ntohl(sFlashCsInfo.FlashSectorSize); + + if(uiSectorSig == FLASH_SECTOR_SIZE_SIG) + { + + if((uiCurrentSectorSize <= MAX_SECTOR_SIZE) && (uiCurrentSectorSize >= MIN_SECTOR_SIZE)) + { + if(uiSectorSize == uiCurrentSectorSize) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Provided sector size is same as programmed in Flash"); + Status = STATUS_SUCCESS; + goto Restore ; + } + } + } + + if((uiSectorSize <= MAX_SECTOR_SIZE) && (uiSectorSize >= MIN_SECTOR_SIZE)) + { + + sFlashCsInfo.FlashSectorSize = htonl(uiSectorSize); + sFlashCsInfo.FlashSectorSizeSig = htonl(FLASH_SECTOR_SIZE_SIG); + + Status = BeceemFlashBulkWrite(Adapter, + (PUINT)&sFlashCsInfo, + Adapter->ulFlashControlSectionStart, + sizeof(sFlashCsInfo), + TRUE); + + + } + + Restore : + // restore the values. + wrmalt(Adapter, 0x0f000C80,&uiTemp, sizeof(uiTemp)); + + + return Status; + +} + +//----------------------------------------------------------------------------- +// Procedure: BcmGetFlashSectorSize +// +// Description: Finds the sector size of the FLASH. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// UINT - sector size. +// +//----------------------------------------------------------------------------- + +UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter, UINT FlashSectorSizeSig, UINT FlashSectorSize) +{ + UINT uiSectorSize = 0; + UINT uiSectorSig = 0; + + if(Adapter->bSectorSizeOverride && + (Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE)) + { + Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; + } + else + { + + uiSectorSig = FlashSectorSizeSig; + + if(uiSectorSig == FLASH_SECTOR_SIZE_SIG) + { + uiSectorSize = FlashSectorSize; + // + // If the sector size stored in the FLASH makes sense then use it. + // + if(uiSectorSize <= MAX_SECTOR_SIZE && uiSectorSize >= MIN_SECTOR_SIZE) + { + Adapter->uiSectorSize = uiSectorSize; + } + //No valid size in FLASH, check if Config file has it. + else if(Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) + { + Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; + } + // Init to Default, if none of the above works. + else + { + Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; + } + + } + else + { + if(Adapter->uiSectorSizeInCFG <= MAX_SECTOR_SIZE && + Adapter->uiSectorSizeInCFG >= MIN_SECTOR_SIZE) + { + Adapter->uiSectorSize = Adapter->uiSectorSizeInCFG; + } + else + { + Adapter->uiSectorSize = DEFAULT_SECTOR_SIZE; + } + } + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector size :%x \n", Adapter->uiSectorSize); + return Adapter->uiSectorSize; +} + +//----------------------------------------------------------------------------- +// Procedure: BcmInitEEPROMQueues +// +// Description: Initialization of EEPROM queues. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// +//----------------------------------------------------------------------------- + +INT BcmInitEEPROMQueues(PMINI_ADAPTER Adapter) +{ + UINT value = 0; + /* CHIP Bug : Clear the Avail bits on the Read queue. The default + * value on this register is supposed to be 0x00001102. + * But we get 0x00001122. */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Fixing reset value on 0x0f003004 register\n" ); + value = EEPROM_READ_DATA_AVAIL; + wrmalt( Adapter, EEPROM_SPI_Q_STATUS1_REG, &value, sizeof(value)); + + /* Flush the all the EEPROM queues. */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " Flushing the queues\n"); + value =EEPROM_ALL_QUEUE_FLUSH ; + wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value)); + + value = 0; + wrmalt( Adapter, SPI_FLUSH_REG, &value, sizeof(value) ); + + /* Read the EEPROM Status Register. Just to see, no real purpose. */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "EEPROM Status register value = %x\n", ReadEEPROMStatusRegister(Adapter) ); + + return STATUS_SUCCESS; +} /* BcmInitEEPROMQueues() */ + +//----------------------------------------------------------------------------- +// Procedure: BcmInitNVM +// +// Description: Initialization of NVM, EEPROM size,FLASH size, sector size etc. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// +//----------------------------------------------------------------------------- + +INT BcmInitNVM(PMINI_ADAPTER ps_adapter) +{ +#ifdef BCM_SHM_INTERFACE +#ifdef FLASH_DIRECT_ACCESS + unsigned int data,data1,data2 = 1; + wrm(ps_adapter, PAD_SELECT_REGISTER, &data2, 4); + data1 = rdm(ps_adapter,SYS_CFG,&data,4); + data1 = rdm(ps_adapter,SYS_CFG,&data,4); + data2 = (data | 0x80 | 0x8000); + wrm(ps_adapter,SYS_CFG, &data2,4); // over-write as Flash boot mode +#endif + ps_adapter->eNVMType = NVM_FLASH; +#else + BcmValidateNvmType(ps_adapter); + BcmInitEEPROMQueues(ps_adapter); +#endif + + if(ps_adapter->eNVMType == NVM_AUTODETECT) + { + ps_adapter->eNVMType = BcmGetNvmType(ps_adapter); + if(ps_adapter->eNVMType == NVM_UNKNOWN) + { + BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_PRINTK, 0, 0, "NVM Type is unknown!!\n"); + } + } + else if(ps_adapter->eNVMType == NVM_FLASH) + { + BcmGetFlashCSInfo(ps_adapter); + } + + BcmGetNvmSize(ps_adapter); + + return STATUS_SUCCESS; +} +/***************************************************************************/ +/*BcmGetNvmSize : set the EEPROM or flash size in Adapter. +* +*Input Parameter: +* Adapter data structure +*Return Value : +* 0. means sucess; +*/ +/***************************************************************************/ + +INT BcmGetNvmSize(PMINI_ADAPTER Adapter) +{ + if(Adapter->eNVMType == NVM_EEPROM) + { + Adapter->uiNVMDSDSize = BcmGetEEPROMSize(Adapter); + } + else if(Adapter->eNVMType == NVM_FLASH) + { + Adapter->uiNVMDSDSize = BcmGetFlashSize(Adapter); + } + return 0; +} + +//----------------------------------------------------------------------------- +// Procedure: BcmValidateNvm +// +// Description: Validates the NVM Type option selected against the device +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// +//----------------------------------------------------------------------------- +VOID BcmValidateNvmType(PMINI_ADAPTER Adapter) +{ + + // + // if forcing the FLASH through CFG file, we should ensure device really has a FLASH. + // Accessing the FLASH address without the FLASH being present can cause hang/freeze etc. + // So if NVM_FLASH is selected for older chipsets, change it to AUTODETECT where EEPROM is 1st choice. + // + + if(Adapter->eNVMType == NVM_FLASH && + Adapter->chip_id < 0xBECE3300) + { + Adapter->eNVMType = NVM_AUTODETECT; + } +} +//----------------------------------------------------------------------------- +// Procedure: BcmReadFlashRDID +// +// Description: Reads ID from Serial Flash +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// Flash ID +//----------------------------------------------------------------------------- +ULONG BcmReadFlashRDID(PMINI_ADAPTER Adapter) +{ + ULONG ulRDID = 0; + UINT value; +// +// Read ID Instruction. +// + value = (FLASH_CMD_READ_ID<<24); + wrmalt(Adapter, FLASH_SPI_CMDQ_REG,&value, sizeof(value)); + +//Delay + udelay(10); +// +// Read SPI READQ REG. The output will be WWXXYYZZ. +// The ID is 3Bytes long and is WWXXYY. ZZ needs to be Ignored. +// + rdmalt(Adapter, FLASH_SPI_READQ_REG,(PUINT)&ulRDID, sizeof(ulRDID)); + + return (ulRDID >>8); + + +} + +INT BcmAllocFlashCSStructure(PMINI_ADAPTER psAdapter) +{ + if(psAdapter == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0, "Adapter structure point is NULL"); + return -EINVAL; + } + psAdapter->psFlashCSInfo = (PFLASH_CS_INFO)kzalloc(sizeof(FLASH_CS_INFO), GFP_KERNEL); + if(psAdapter->psFlashCSInfo == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate memory for Flash 1.x"); + return -ENOMEM; + } + + psAdapter->psFlash2xCSInfo = (PFLASH2X_CS_INFO)kzalloc(sizeof(FLASH2X_CS_INFO), GFP_KERNEL); + if(psAdapter->psFlash2xCSInfo == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate memory for Flash 2.x"); + bcm_kfree(psAdapter->psFlashCSInfo); + return -ENOMEM; + } + + psAdapter->psFlash2xVendorInfo = (PFLASH2X_VENDORSPECIFIC_INFO)kzalloc(sizeof(FLASH2X_VENDORSPECIFIC_INFO), GFP_KERNEL); + if(psAdapter->psFlash2xVendorInfo == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0,"Can't Allocate Vendor Info Memory for Flash 2.x"); + bcm_kfree(psAdapter->psFlashCSInfo); + bcm_kfree(psAdapter->psFlash2xCSInfo); + return -ENOMEM; + } + + return STATUS_SUCCESS; +} + +INT BcmDeAllocFlashCSStructure(PMINI_ADAPTER psAdapter) +{ + if(psAdapter == NULL) + { + BCM_DEBUG_PRINT(psAdapter,DBG_TYPE_PRINTK, 0, 0," Adapter structure point is NULL"); + return -EINVAL; + } + bcm_kfree(psAdapter->psFlashCSInfo); + bcm_kfree(psAdapter->psFlash2xCSInfo); + bcm_kfree(psAdapter->psFlash2xVendorInfo); + return STATUS_SUCCESS ; +} + +INT BcmDumpFlash2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo,PMINI_ADAPTER Adapter) +{ + UINT Index = 0; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "**********************FLASH2X CS Structure *******************"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x", (psFlash2xCSInfo->MagicNumber)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Major Version :%d", MAJOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Minor Version :%d", MINOR_VERSION(psFlash2xCSInfo->FlashLayoutVersion)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, " ISOImageMajorVersion:0x%x", (psFlash2xCSInfo->ISOImageVersion)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SCSIFirmwareMajorVersion :0x%x", (psFlash2xCSInfo->SCSIFirmwareVersion)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart1ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForScsiFirmware :0x%x", (psFlash2xCSInfo->OffsetFromZeroForScsiFirmware)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SizeOfScsiFirmware :0x%x", (psFlash2xCSInfo->SizeOfScsiFirmware )); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForPart2ISOImage :0x%x", (psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDStart)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSDEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSDEnd)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAStart)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSAEnd :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSAEnd)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionStart :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionStart)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForControlSectionData :0x%x", (psFlash2xCSInfo->OffsetFromZeroForControlSectionData)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "CDLessInactivityTimeout :0x%x", (psFlash2xCSInfo->CDLessInactivityTimeout)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "NewImageSignature :0x%x", (psFlash2xCSInfo->NewImageSignature)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSizeSig :0x%x", (psFlash2xCSInfo->FlashSectorSizeSig)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashSectorSize :0x%x", (psFlash2xCSInfo->FlashSectorSize)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashWriteSupportSize :0x%x", (psFlash2xCSInfo->FlashWriteSupportSize)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "TotalFlashSize :0x%X", (psFlash2xCSInfo->TotalFlashSize)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashBaseAddr :0x%x", (psFlash2xCSInfo->FlashBaseAddr)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "FlashPartMaxSize :0x%x", (psFlash2xCSInfo->FlashPartMaxSize)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "IsCDLessDeviceBootSig :0x%x", (psFlash2xCSInfo->IsCDLessDeviceBootSig)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "MassStorageTimeout :0x%x", (psFlash2xCSInfo->MassStorageTimeout)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part1End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part2End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage1Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage1Part3End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part1End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part1End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part2End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part2End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3Start :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetISOImage2Part3End :0x%x", (psFlash2xCSInfo->OffsetISOImage2Part3End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromDSDStartForDSDHeader :0x%x", (psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD1End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForDSD2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForDSD2End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA1End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA1End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2Start :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2Start)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "OffsetFromZeroForVSA2End :0x%x", (psFlash2xCSInfo->OffsetFromZeroForVSA2End)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Sector Access Bit Map is Defined as :"); + for(Index =0; Index <(FLASH2X_TOTAL_SIZE/(DEFAULT_SECTOR_SIZE *16)); Index++) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectorAccessBitMap[%d] :0x%x", Index, + (psFlash2xCSInfo->SectorAccessBitMap[Index])); + } + + return STATUS_SUCCESS; +} + + +INT ConvertEndianOf2XCSStructure(PFLASH2X_CS_INFO psFlash2xCSInfo) +{ + UINT Index = 0; + psFlash2xCSInfo->MagicNumber = ntohl(psFlash2xCSInfo->MagicNumber); + psFlash2xCSInfo->FlashLayoutVersion= ntohl(psFlash2xCSInfo->FlashLayoutVersion); + //psFlash2xCSInfo->FlashLayoutMinorVersion = ntohs(psFlash2xCSInfo->FlashLayoutMinorVersion); + psFlash2xCSInfo->ISOImageVersion = ntohl(psFlash2xCSInfo->ISOImageVersion); + psFlash2xCSInfo->SCSIFirmwareVersion =ntohl(psFlash2xCSInfo->SCSIFirmwareVersion); + psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart1ISOImage); + psFlash2xCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); + psFlash2xCSInfo->SizeOfScsiFirmware = ntohl(psFlash2xCSInfo->SizeOfScsiFirmware ); + psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlash2xCSInfo->OffsetFromZeroForPart2ISOImage); + psFlash2xCSInfo->OffsetFromZeroForDSDStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDStart); + psFlash2xCSInfo->OffsetFromZeroForDSDEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSDEnd); + psFlash2xCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAStart); + psFlash2xCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSAEnd); + psFlash2xCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); + psFlash2xCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlash2xCSInfo->OffsetFromZeroForControlSectionData); + psFlash2xCSInfo->CDLessInactivityTimeout = ntohl(psFlash2xCSInfo->CDLessInactivityTimeout); + psFlash2xCSInfo->NewImageSignature = ntohl(psFlash2xCSInfo->NewImageSignature); + psFlash2xCSInfo->FlashSectorSizeSig = ntohl(psFlash2xCSInfo->FlashSectorSizeSig); + psFlash2xCSInfo->FlashSectorSize = ntohl(psFlash2xCSInfo->FlashSectorSize); + psFlash2xCSInfo->FlashWriteSupportSize = ntohl(psFlash2xCSInfo->FlashWriteSupportSize); + psFlash2xCSInfo->TotalFlashSize = ntohl(psFlash2xCSInfo->TotalFlashSize); + psFlash2xCSInfo->FlashBaseAddr = ntohl(psFlash2xCSInfo->FlashBaseAddr); + psFlash2xCSInfo->FlashPartMaxSize = ntohl(psFlash2xCSInfo->FlashPartMaxSize); + psFlash2xCSInfo->IsCDLessDeviceBootSig = ntohl(psFlash2xCSInfo->IsCDLessDeviceBootSig); + psFlash2xCSInfo->MassStorageTimeout = ntohl(psFlash2xCSInfo->MassStorageTimeout); + psFlash2xCSInfo->OffsetISOImage1Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1Start); + psFlash2xCSInfo->OffsetISOImage1Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part1End); + psFlash2xCSInfo->OffsetISOImage1Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2Start); + psFlash2xCSInfo->OffsetISOImage1Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part2End); + psFlash2xCSInfo->OffsetISOImage1Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3Start); + psFlash2xCSInfo->OffsetISOImage1Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage1Part3End); + psFlash2xCSInfo->OffsetISOImage2Part1Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1Start); + psFlash2xCSInfo->OffsetISOImage2Part1End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part1End); + psFlash2xCSInfo->OffsetISOImage2Part2Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2Start); + psFlash2xCSInfo->OffsetISOImage2Part2End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part2End); + psFlash2xCSInfo->OffsetISOImage2Part3Start = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3Start); + psFlash2xCSInfo->OffsetISOImage2Part3End = ntohl(psFlash2xCSInfo->OffsetISOImage2Part3End); + psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader = ntohl(psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader); + psFlash2xCSInfo->OffsetFromZeroForDSD1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1Start); + psFlash2xCSInfo->OffsetFromZeroForDSD1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD1End); + psFlash2xCSInfo->OffsetFromZeroForDSD2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2Start); + psFlash2xCSInfo->OffsetFromZeroForDSD2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForDSD2End); + psFlash2xCSInfo->OffsetFromZeroForVSA1Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1Start); + psFlash2xCSInfo->OffsetFromZeroForVSA1End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA1End); + psFlash2xCSInfo->OffsetFromZeroForVSA2Start = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2Start); + psFlash2xCSInfo->OffsetFromZeroForVSA2End = ntohl(psFlash2xCSInfo->OffsetFromZeroForVSA2End); + for(Index =0; Index <(FLASH2X_TOTAL_SIZE/(DEFAULT_SECTOR_SIZE *16)); Index++) + { + psFlash2xCSInfo->SectorAccessBitMap[Index] = ntohl(psFlash2xCSInfo->SectorAccessBitMap[Index]); + } + return STATUS_SUCCESS; +} + +INT ConvertEndianOfCSStructure(PFLASH_CS_INFO psFlashCSInfo) +{ + //UINT Index = 0; + psFlashCSInfo->MagicNumber =ntohl(psFlashCSInfo->MagicNumber); + psFlashCSInfo->FlashLayoutVersion =ntohl(psFlashCSInfo->FlashLayoutVersion); + psFlashCSInfo->ISOImageVersion = ntohl(psFlashCSInfo->ISOImageVersion); + //won't convert according to old assumption + psFlashCSInfo->SCSIFirmwareVersion =(psFlashCSInfo->SCSIFirmwareVersion); + + psFlashCSInfo->OffsetFromZeroForPart1ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart1ISOImage); + psFlashCSInfo->OffsetFromZeroForScsiFirmware = ntohl(psFlashCSInfo->OffsetFromZeroForScsiFirmware); + psFlashCSInfo->SizeOfScsiFirmware = ntohl(psFlashCSInfo->SizeOfScsiFirmware ); + psFlashCSInfo->OffsetFromZeroForPart2ISOImage = ntohl(psFlashCSInfo->OffsetFromZeroForPart2ISOImage); + psFlashCSInfo->OffsetFromZeroForCalibrationStart = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationStart); + psFlashCSInfo->OffsetFromZeroForCalibrationEnd = ntohl(psFlashCSInfo->OffsetFromZeroForCalibrationEnd); + psFlashCSInfo->OffsetFromZeroForVSAStart = ntohl(psFlashCSInfo->OffsetFromZeroForVSAStart); + psFlashCSInfo->OffsetFromZeroForVSAEnd = ntohl(psFlashCSInfo->OffsetFromZeroForVSAEnd); + psFlashCSInfo->OffsetFromZeroForControlSectionStart = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionStart); + psFlashCSInfo->OffsetFromZeroForControlSectionData = ntohl(psFlashCSInfo->OffsetFromZeroForControlSectionData); + psFlashCSInfo->CDLessInactivityTimeout = ntohl(psFlashCSInfo->CDLessInactivityTimeout); + psFlashCSInfo->NewImageSignature = ntohl(psFlashCSInfo->NewImageSignature); + psFlashCSInfo->FlashSectorSizeSig = ntohl(psFlashCSInfo->FlashSectorSizeSig); + psFlashCSInfo->FlashSectorSize = ntohl(psFlashCSInfo->FlashSectorSize); + psFlashCSInfo->FlashWriteSupportSize = ntohl(psFlashCSInfo->FlashWriteSupportSize); + psFlashCSInfo->TotalFlashSize = ntohl(psFlashCSInfo->TotalFlashSize); + psFlashCSInfo->FlashBaseAddr = ntohl(psFlashCSInfo->FlashBaseAddr); + psFlashCSInfo->FlashPartMaxSize = ntohl(psFlashCSInfo->FlashPartMaxSize); + psFlashCSInfo->IsCDLessDeviceBootSig = ntohl(psFlashCSInfo->IsCDLessDeviceBootSig); + psFlashCSInfo->MassStorageTimeout = ntohl(psFlashCSInfo->MassStorageTimeout); + + return STATUS_SUCCESS; +} + +INT IsSectionExistInVendorInfo(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section) +{ + return ( Adapter->uiVendorExtnFlag && + (Adapter->psFlash2xVendorInfo->VendorSection[section].AccessFlags & FLASH2X_SECTION_PRESENT) && + (Adapter->psFlash2xVendorInfo->VendorSection[section].OffsetFromZeroForSectionStart != UNINIT_PTR_IN_CS) ); +} + +VOID UpdateVendorInfo(PMINI_ADAPTER Adapter) +{ + B_UINT32 i = 0; + UINT uiSizeSection = 0; + + Adapter->uiVendorExtnFlag = FALSE; + + for(i = 0;i < TOTAL_SECTIONS;i++) + Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart = UNINIT_PTR_IN_CS; + + if(STATUS_SUCCESS != vendorextnGetSectionInfo(Adapter, Adapter->psFlash2xVendorInfo)) + return; + + i = 0; + while(i < TOTAL_SECTIONS) + { + if(!(Adapter->psFlash2xVendorInfo->VendorSection[i].AccessFlags & FLASH2X_SECTION_PRESENT)) + { + i++; + continue; + } + + Adapter->uiVendorExtnFlag = TRUE; + uiSizeSection = (Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionEnd - + Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart); + + switch(i) + { + case DSD0: + if(( uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd = UNINIT_PTR_IN_CS; + break; + + case DSD1: + if(( uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End = UNINIT_PTR_IN_CS; + break; + + case DSD2: + if(( uiSizeSection >= (Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER))) && + (UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart)) + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End = UNINIT_PTR_IN_CS; + break; + case VSA0: + if(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd = UNINIT_PTR_IN_CS; + break; + + case VSA1: + if(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End = UNINIT_PTR_IN_CS; + break; + case VSA2: + if(UNINIT_PTR_IN_CS != Adapter->psFlash2xVendorInfo->VendorSection[i].OffsetFromZeroForSectionStart) + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = VENDOR_PTR_IN_CS; + else + Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start = Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End = UNINIT_PTR_IN_CS; + break; + + default: + break; + } + i++; + } + +} + +//----------------------------------------------------------------------------- +// Procedure: BcmGetFlashCSInfo +// +// Description: Reads control structure and gets Cal section addresses. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// +//----------------------------------------------------------------------------- + +INT BcmGetFlashCSInfo(PMINI_ADAPTER Adapter) +{ + //FLASH_CS_INFO sFlashCsInfo = {0}; + +#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT value; +#endif + UINT uiFlashLayoutMajorVersion; + Adapter->uiFlashLayoutMinorVersion = 0; + Adapter->uiFlashLayoutMajorVersion = 0; + Adapter->ulFlashControlSectionStart = FLASH_CS_INFO_START_ADDR; + + + Adapter->uiFlashBaseAdd = 0; + Adapter->ulFlashCalStart = 0; + memset(Adapter->psFlashCSInfo, 0 ,sizeof(FLASH_CS_INFO)); + memset(Adapter->psFlash2xCSInfo, 0 ,sizeof(FLASH2X_CS_INFO)); + +#ifndef BCM_SHM_INTERFACE + if(!Adapter->bDDRInitDone) + { + { + value = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; + wrmalt(Adapter, 0xAF00A080, &value, sizeof(value)); + } + } + +#endif + + // Reading first 8 Bytes to get the Flash Layout + // MagicNumber(4 bytes) +FlashLayoutMinorVersion(2 Bytes) +FlashLayoutMajorVersion(2 Bytes) + BeceemFlashBulkRead(Adapter,(PUINT)Adapter->psFlashCSInfo,Adapter->ulFlashControlSectionStart,8); + + Adapter->psFlashCSInfo->FlashLayoutVersion = ntohl(Adapter->psFlashCSInfo->FlashLayoutVersion); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Version :%X", (Adapter->psFlashCSInfo->FlashLayoutVersion)); + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Flash Layout Minor Version :%d\n", ntohs(sFlashCsInfo.FlashLayoutMinorVersion)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Signature is :%x\n", ntohl(Adapter->psFlashCSInfo->MagicNumber)); + + if(FLASH_CONTROL_STRUCT_SIGNATURE == ntohl(Adapter->psFlashCSInfo->MagicNumber)) + { + uiFlashLayoutMajorVersion = MAJOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); + Adapter->uiFlashLayoutMinorVersion = MINOR_VERSION((Adapter->psFlashCSInfo->FlashLayoutVersion)); + } + else + { + Adapter->uiFlashLayoutMinorVersion = 0; + uiFlashLayoutMajorVersion = 0; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"FLASH LAYOUT MAJOR VERSION :%X", uiFlashLayoutMajorVersion); + + if(uiFlashLayoutMajorVersion < FLASH_2X_MAJOR_NUMBER) + { + BeceemFlashBulkRead(Adapter,(PUINT)Adapter->psFlashCSInfo,Adapter->ulFlashControlSectionStart,sizeof(FLASH_CS_INFO)); + ConvertEndianOfCSStructure(Adapter->psFlashCSInfo); + Adapter->ulFlashCalStart = (Adapter->psFlashCSInfo->OffsetFromZeroForCalibrationStart); + + if(!((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1))) + { + Adapter->ulFlashControlSectionStart = Adapter->psFlashCSInfo->OffsetFromZeroForControlSectionStart; + } + + if((FLASH_CONTROL_STRUCT_SIGNATURE == (Adapter->psFlashCSInfo->MagicNumber)) && + (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlashCSInfo->SCSIFirmwareVersion)) && + (FLASH_SECTOR_SIZE_SIG == (Adapter->psFlashCSInfo->FlashSectorSizeSig)) && + (BYTE_WRITE_SUPPORT == (Adapter->psFlashCSInfo->FlashWriteSupportSize))) + { + Adapter->ulFlashWriteSize = (Adapter->psFlashCSInfo->FlashWriteSupportSize); + Adapter->fpFlashWrite = flashByteWrite; + Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; + } + else + { + Adapter->ulFlashWriteSize = MAX_RW_SIZE; + Adapter->fpFlashWrite = flashWrite; + Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; + } + + BcmGetFlashSectorSize(Adapter, (Adapter->psFlashCSInfo->FlashSectorSizeSig), + (Adapter->psFlashCSInfo->FlashSectorSize)); + + + Adapter->uiFlashBaseAdd = Adapter->psFlashCSInfo->FlashBaseAddr & 0xFCFFFFFF; + + + } + else + { + if(BcmFlash2xBulkRead(Adapter,(PUINT)Adapter->psFlash2xCSInfo,NO_SECTION_VAL, + Adapter->ulFlashControlSectionStart,sizeof(FLASH2X_CS_INFO))) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Unable to read CS structure \n"); + return STATUS_FAILURE; + } + ConvertEndianOf2XCSStructure(Adapter->psFlash2xCSInfo); +#ifndef BCM_SHM_INTERFACE + BcmDumpFlash2XCSStructure(Adapter->psFlash2xCSInfo,Adapter); +#endif + if((FLASH_CONTROL_STRUCT_SIGNATURE == Adapter->psFlash2xCSInfo->MagicNumber) && + (SCSI_FIRMWARE_MINOR_VERSION <= MINOR_VERSION(Adapter->psFlash2xCSInfo->SCSIFirmwareVersion)) && + (FLASH_SECTOR_SIZE_SIG == Adapter->psFlash2xCSInfo->FlashSectorSizeSig) && + (BYTE_WRITE_SUPPORT == Adapter->psFlash2xCSInfo->FlashWriteSupportSize)) + { + Adapter->ulFlashWriteSize = Adapter->psFlash2xCSInfo->FlashWriteSupportSize; + Adapter->fpFlashWrite = flashByteWrite; + Adapter->fpFlashWriteWithStatusCheck = flashByteWriteStatus; + } + else + { + Adapter->ulFlashWriteSize = MAX_RW_SIZE; + Adapter->fpFlashWrite = flashWrite; + Adapter->fpFlashWriteWithStatusCheck = flashWriteStatus; + } + + BcmGetFlashSectorSize(Adapter, Adapter->psFlash2xCSInfo->FlashSectorSizeSig, + Adapter->psFlash2xCSInfo->FlashSectorSize); + + UpdateVendorInfo(Adapter); + + BcmGetActiveDSD(Adapter); + BcmGetActiveISO(Adapter); + Adapter->uiFlashBaseAdd = Adapter->psFlash2xCSInfo->FlashBaseAddr & 0xFCFFFFFF; + Adapter->ulFlashControlSectionStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart; + + } + /* + Concerns: what if CS sector size does not match with this sector size ??? + what is the indication of AccessBitMap in CS in flash 2.x ???? + */ +#ifndef BCM_SHM_INTERFACE + Adapter->ulFlashID = BcmReadFlashRDID(Adapter); +#endif + + Adapter->uiFlashLayoutMajorVersion = uiFlashLayoutMajorVersion; + + #if 0 + if(FLASH_PART_SST25VF080B == Adapter->ulFlashID) + { + // + // 1MB flash has been selected. we have to use 64K as sector size no matter what is kept in FLASH_CS. + // + Adapter->uiSectorSize = 0x10000; + } + #endif + + return STATUS_SUCCESS ; +} + + +//----------------------------------------------------------------------------- +// Procedure: BcmGetNvmType +// +// Description: Finds the type of NVM used. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// +// Returns: +// NVM_TYPE +// +//----------------------------------------------------------------------------- + +NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter) +{ + UINT uiData = 0; + + BeceemEEPROMBulkRead(Adapter,&uiData,0x0,4); + if(uiData == BECM) + { + return NVM_EEPROM; + } + // + // Read control struct and get cal addresses before accessing the flash + // + BcmGetFlashCSInfo(Adapter); + + BeceemFlashBulkRead(Adapter,&uiData,0x0 + Adapter->ulFlashCalStart,4); + if(uiData == BECM) + { + return NVM_FLASH; + } +// +// even if there is no valid signature on EEPROM/FLASH find out if they really exist. +// if exist select it. +// + if(BcmGetEEPROMSize(Adapter)) + { + return NVM_EEPROM; + } + +//TBD for Flash. + + + return NVM_UNKNOWN; +} + +/** +* BcmGetSectionValStartOffset - this will calculate the section's starting offset if section val is given +* @Adapter : Drivers Private Data structure +* @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL +* +* Return value:- +* On success it return the start offset of the provided section val +* On Failure -returns STATUS_FAILURE +**/ + +INT BcmGetSectionValStartOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) +{ + /* + * Considering all the section for which end offset can be calculated or directly given + * in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section + * endoffset can't be calculated or given in CS Stucture. + */ + + INT SectStartOffset = 0 ; + + SectStartOffset = INVALID_OFFSET ; + + if(IsSectionExistInVendorInfo(Adapter,eFlashSectionVal)) + { + return Adapter->psFlash2xVendorInfo->VendorSection[eFlashSectionVal].OffsetFromZeroForSectionStart; + } + + switch(eFlashSectionVal) + { + case ISO_IMAGE1 : + if((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); + break; + case ISO_IMAGE2 : + if((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); + break; + case DSD0 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart); + break; + case DSD1 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start); + break; + case DSD2 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start); + break; + case VSA0 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart); + break; + case VSA1 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start); + break; + case VSA2 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start); + break; + case SCSI : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware); + break; + case CONTROL_SECTION : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart); + break; + case ISO_IMAGE1_PART2 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start); + break; + case ISO_IMAGE1_PART3 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); + break; + case ISO_IMAGE2_PART2 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start); + break; + case ISO_IMAGE2_PART3 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start != UNINIT_PTR_IN_CS) + SectStartOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); + break; + default : + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section Does not exist in Flash 2.x"); + SectStartOffset = INVALID_OFFSET; + } + return SectStartOffset; +} + +/** +* BcmGetSectionValEndOffset - this will calculate the section's Ending offset if section val is given +* @Adapter : Drivers Private Data structure +* @eFlashSectionVal : Flash secion value defined in enum FLASH2X_SECTION_VAL +* +* Return value:- +* On success it return the end offset of the provided section val +* On Failure -returns STATUS_FAILURE +**/ + +INT BcmGetSectionValEndOffset(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +{ + INT SectEndOffset = 0 ; + SectEndOffset = INVALID_OFFSET; + + if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectionVal)) + { + return Adapter->psFlash2xVendorInfo->VendorSection[eFlash2xSectionVal].OffsetFromZeroForSectionEnd; + } + + switch(eFlash2xSectionVal) + { + case ISO_IMAGE1 : + if((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End!= UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End); + break; + case ISO_IMAGE2 : + if((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End!= UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End); + break; + case DSD0 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDEnd); + break; + case DSD1 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1End); + break; + case DSD2 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2End); + break; + case VSA0 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAEnd); + break; + case VSA1 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1End); + break; + case VSA2 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2End); + break; + case SCSI : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectEndOffset = ((Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) + + (Adapter->psFlash2xCSInfo->SizeOfScsiFirmware)); + break; + case CONTROL_SECTION : + //Not Clear So Putting failure. confirm and fix it. + SectEndOffset = STATUS_FAILURE; + case ISO_IMAGE1_PART2 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End!= UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End); + break; + case ISO_IMAGE1_PART3 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End!= UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End); + break; + case ISO_IMAGE2_PART2 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End != UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End); + break; + case ISO_IMAGE2_PART3 : + if(Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End!= UNINIT_PTR_IN_CS) + SectEndOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End); + break; + + default : + SectEndOffset = INVALID_OFFSET; + } + return SectEndOffset ; +} + +/* +* BcmFlash2xBulkRead:- Read API for Flash Map 2.x . +* @Adapter :Driver Private Data Structure +* @pBuffer : Buffer where data has to be put after reading +* @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL +* @uiOffsetWithinSectionVal :- Offset with in provided section +* @uiNumBytes : Number of Bytes for Read +* +* Return value:- +* return true on sucess and STATUS_FAILURE on fail. +*/ + +INT BcmFlash2xBulkRead( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + FLASH2X_SECTION_VAL eFlash2xSectionVal, + UINT uiOffsetWithinSectionVal, + UINT uiNumBytes) +{ + + INT Status = STATUS_SUCCESS; + INT SectionStartOffset = 0; + UINT uiAbsoluteOffset = 0 ; + UINT uiTemp =0, value =0 ; + if(Adapter == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); + return -EINVAL; + } + if(Adapter->device_removed ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); + return -ENODEV; + } + + //NO_SECTION_VAL means absolute offset is given. + if(eFlash2xSectionVal == NO_SECTION_VAL) + SectionStartOffset = 0; + else + SectionStartOffset = BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal); + + if(SectionStartOffset == STATUS_FAILURE ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"This Section<%d> does not exixt in Flash 2.x Map ",eFlash2xSectionVal); + return -EINVAL; + } + + if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectionVal)) + return vendorextnReadSection(Adapter,(PUCHAR)pBuffer, eFlash2xSectionVal, uiOffsetWithinSectionVal, uiNumBytes); + + //calculating the absolute offset from FLASH; + uiAbsoluteOffset = uiOffsetWithinSectionVal + SectionStartOffset; + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + + Status= BeceemFlashBulkRead(Adapter, pBuffer,uiAbsoluteOffset,uiNumBytes) ; + + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Flash Read Failed with Status :%d", Status); + return Status ; + } + + return Status; +} + +/* +* BcmFlash2xBulkWrite :-API for Writing on the Flash Map 2.x. +* @Adapter :Driver Private Data Structure +* @pBuffer : Buffer From where data has to taken for writing +* @eFlashSectionVal :Flash Section Val defined in FLASH2X_SECTION_VAL +* @uiOffsetWithinSectionVal :- Offset with in provided section +* @uiNumBytes : Number of Bytes for Write +* +* Return value:- +* return true on sucess and STATUS_FAILURE on fail. +* +*/ + +INT BcmFlash2xBulkWrite( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + FLASH2X_SECTION_VAL eFlash2xSectVal, + UINT uiOffset, + UINT uiNumBytes, + UINT bVerify) +{ + + INT Status = STATUS_SUCCESS; + UINT FlashSectValStartOffset = 0; + UINT uiTemp = 0, value = 0; + if(Adapter == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Adapter structure is NULL"); + return -EINVAL; + } + if(Adapter->device_removed ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Device has been removed"); + return -ENODEV; + } + + //NO_SECTION_VAL means absolute offset is given. + if(eFlash2xSectVal == NO_SECTION_VAL) + FlashSectValStartOffset = 0; + else + FlashSectValStartOffset = BcmGetSectionValStartOffset(Adapter,eFlash2xSectVal); + + if(FlashSectValStartOffset == STATUS_FAILURE ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"This Section<%d> does not exixt in Flash Map 2.x",eFlash2xSectVal); + return -EINVAL; + } + + if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectVal)) + return vendorextnWriteSection(Adapter, (PUCHAR)pBuffer, eFlash2xSectVal, uiOffset, uiNumBytes, bVerify); + + //calculating the absolute offset from FLASH; + uiOffset = uiOffset + FlashSectValStartOffset; + + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + + Status = BeceemFlashBulkWrite(Adapter, pBuffer,uiOffset,uiNumBytes,bVerify); + + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Flash Write failed with Status :%d", Status); + return Status ; + } + + return Status; + +} + +/** +* ReadDSDHeader : Read the DSD map for the DSD Section val provided in Argument. +* @Adapter : Beceem Private Data Structure +* @psDSDHeader :Pointer of the buffer where header has to be read +* @dsd :value of the Dyanmic DSD like DSD0 of DSD1 or DSD2 +* +* Return Value:- +* if suceeds return STATUS_SUCCESS or negative error code. +**/ +INT ReadDSDHeader(PMINI_ADAPTER Adapter, PDSD_HEADER psDSDHeader, FLASH2X_SECTION_VAL dsd) +{ + INT Status = STATUS_SUCCESS; + + Status =BcmFlash2xBulkRead(Adapter, + (PUINT)psDSDHeader, + dsd, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader, + sizeof(DSD_HEADER)); + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImageMagicNumber :0X%x", ntohl(psDSDHeader->DSDImageMagicNumber)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImageSize :0X%x ",ntohl(psDSDHeader->DSDImageSize)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImageCRC :0X%x",ntohl(psDSDHeader->DSDImageCRC)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "DSDImagePriority :0X%x",ntohl(psDSDHeader->DSDImagePriority)); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"DSD Header read is failed with status :%d", Status); + } + + return Status; +} + +/** +* BcmGetActiveDSD : Set the Active DSD in Adapter Structure which has to be dumped in DDR +* @Adapter :-Drivers private Data Structure +* +* Return Value:- +* Return STATUS_SUCESS if get sucess in setting the right DSD else negaive error code +* +**/ +INT BcmGetActiveDSD(PMINI_ADAPTER Adapter) +{ + FLASH2X_SECTION_VAL uiHighestPriDSD = 0 ; + + uiHighestPriDSD = getHighestPriDSD(Adapter); + Adapter->eActiveDSD = uiHighestPriDSD; + + if(DSD0 == uiHighestPriDSD) + Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart; + if(DSD1 == uiHighestPriDSD) + Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start; + if(DSD2 == uiHighestPriDSD) + Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; + if(Adapter->eActiveDSD) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Active DSD :%d", Adapter->eActiveDSD); + if(Adapter->eActiveDSD == 0) + { + //if No DSD gets Active, Make Active the DSD with WR permission + if(IsSectionWritable(Adapter,DSD2)) + { + Adapter->eActiveDSD = DSD2; + Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start; + } + else if(IsSectionWritable(Adapter,DSD1)) + { + Adapter->eActiveDSD = DSD1; + Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start; + } + else if(IsSectionWritable(Adapter,DSD0)) + { + Adapter->eActiveDSD = DSD0; + Adapter->ulFlashCalStart = Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart; + } + } + + return STATUS_SUCCESS; +} + +/** +* ReadISOUnReservedBytes : Read the ISO map for the ISO Section val provided in Argument. +* @Adapter : Driver Private Data Structure +* @psISOHeader :Pointer of the location where header has to be read +* @IsoImage :value of the Dyanmic ISO like ISO_IMAGE1 of ISO_IMAGE2 +* +* Return Value:- +* if suceeds return STATUS_SUCCESS or negative error code. +**/ + +INT ReadISOHeader(PMINI_ADAPTER Adapter, PISO_HEADER psISOHeader, FLASH2X_SECTION_VAL IsoImage) +{ + INT Status = STATUS_SUCCESS; + + Status = BcmFlash2xBulkRead(Adapter, + (PUINT)psISOHeader, + IsoImage, + 0, + sizeof(ISO_HEADER)); + + if(Status == STATUS_SUCCESS) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImageMagicNumber :0X%x", ntohl(psISOHeader->ISOImageMagicNumber)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImageSize :0X%x ",ntohl(psISOHeader->ISOImageSize)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImageCRC :0X%x",ntohl(psISOHeader->ISOImageCRC)); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "ISOImagePriority :0X%x",ntohl(psISOHeader->ISOImagePriority)); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ISO Header Read failed"); + } + return Status; +} + +/** +* BcmGetActiveISO :- Set the Active ISO in Adapter Data Structue +* @Adapter : Driver private Data Structure +* +* Return Value:- +* Sucsess:- STATUS_SUCESS +* Failure- : negative erro code +* +**/ + +INT BcmGetActiveISO(PMINI_ADAPTER Adapter) +{ + + INT HighestPriISO = 0 ; + HighestPriISO = getHighestPriISO(Adapter); + + Adapter->eActiveISO = HighestPriISO ; + if(Adapter->eActiveISO == ISO_IMAGE2) + Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start); + else if(Adapter->eActiveISO == ISO_IMAGE1) + Adapter->uiActiveISOOffset = (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start); + + if(Adapter->eActiveISO) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Active ISO :%x", Adapter->eActiveISO); + + return STATUS_SUCCESS; +} + +/** +* IsOffsetWritable :- it will tell the access permission of the sector having passed offset +* @Adapter : Drivers Private Data Structure +* @uiOffset : Offset provided in the Flash +* +* Return Value:- +* Sucess:-TRUE , offset is writable +* Failure:-FALSE, offset is RO +* +**/ +B_UINT8 IsOffsetWritable(PMINI_ADAPTER Adapter, UINT uiOffset) +{ + UINT uiSectorNum = 0; + UINT uiWordOfSectorPermission =0; + UINT uiBitofSectorePermission = 0; + B_UINT32 permissionBits = 0; + uiSectorNum = uiOffset/Adapter->uiSectorSize; + + //calculating the word having this Sector Access permission from SectorAccessBitMap Array + uiWordOfSectorPermission = Adapter->psFlash2xCSInfo->SectorAccessBitMap[uiSectorNum /16]; + + //calculating the bit index inside the word for this sector + uiBitofSectorePermission = 2*(15 - uiSectorNum %16); + + //Setting Access permission + permissionBits = uiWordOfSectorPermission & (0x3 << uiBitofSectorePermission) ; + permissionBits = (permissionBits >> uiBitofSectorePermission) & 0x3; + if(permissionBits == SECTOR_READWRITE_PERMISSION) + return TRUE; + else + return FALSE; +} + +INT BcmDumpFlash2xSectionBitMap(PFLASH2X_BITMAP psFlash2xBitMap) +{ + PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(gblpnetdev); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "***************Flash 2.x Section Bitmap***************"); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO_IMAGE1 :0X%x", psFlash2xBitMap->ISO_IMAGE1); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO_IMAGE2 :0X%x", psFlash2xBitMap->ISO_IMAGE2); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD0 :0X%x", psFlash2xBitMap->DSD0); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD1 :0X%x", psFlash2xBitMap->DSD1); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD2 :0X%x", psFlash2xBitMap->DSD2); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"VSA0 :0X%x", psFlash2xBitMap->VSA0); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"VSA1 :0X%x", psFlash2xBitMap->VSA1); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"VSA2 :0X%x", psFlash2xBitMap->VSA2); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"SCSI :0X%x", psFlash2xBitMap->SCSI); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"CONTROL_SECTION :0X%x", psFlash2xBitMap->CONTROL_SECTION); + + return STATUS_SUCCESS; +} + +/** +* BcmGetFlash2xSectionalBitMap :- It will provide the bit map of all the section present in Flash +* 8bit has been assigned to every section. + bit[0] :Section present or not + bit[1] :section is valid or not + bit[2] : Secton is read only or has write permission too. + bit[3] : Active Section - + bit[7...4] = Reserved . + + @Adapter:-Driver private Data Structure +* +* Return value:- +* Sucess:- STATUS_SUCESS +* Failure:- negative error code +**/ + +INT BcmGetFlash2xSectionalBitMap(PMINI_ADAPTER Adapter, PFLASH2X_BITMAP psFlash2xBitMap) +{ + + + PFLASH2X_CS_INFO psFlash2xCSInfo = Adapter->psFlash2xCSInfo; + FLASH2X_SECTION_VAL uiHighestPriDSD = 0 ; + FLASH2X_SECTION_VAL uiHighestPriISO= 0 ; + BOOLEAN SetActiveDSDDone = FALSE ; + BOOLEAN SetActiveISODone = FALSE ; + + //For 1.x map all the section except DSD0 will be shown as not present + //This part will be used by calibration tool to detect the number of DSD present in Flash. + if(IsFlash2x(Adapter) == FALSE) + { + psFlash2xBitMap->ISO_IMAGE2 = 0; + psFlash2xBitMap->ISO_IMAGE1 = 0; + psFlash2xBitMap->DSD0 = FLASH2X_SECTION_VALID | FLASH2X_SECTION_ACT | FLASH2X_SECTION_PRESENT; //0xF; //0000(Reseved)1(Active)0(RW)1(valid)1(present) + psFlash2xBitMap->DSD1 = 0 ; + psFlash2xBitMap->DSD2 = 0 ; + psFlash2xBitMap->VSA0 = 0 ; + psFlash2xBitMap->VSA1 = 0 ; + psFlash2xBitMap->VSA2 = 0 ; + psFlash2xBitMap->CONTROL_SECTION = 0 ; + psFlash2xBitMap->SCSI= 0 ; + psFlash2xBitMap->Reserved0 = 0 ; + psFlash2xBitMap->Reserved1 = 0 ; + psFlash2xBitMap->Reserved2 = 0 ; + return STATUS_SUCCESS ; + + } + + uiHighestPriDSD = getHighestPriDSD(Adapter); + uiHighestPriISO = getHighestPriISO(Adapter); + + /// + // IS0 IMAGE 2 + /// + if((psFlash2xCSInfo->OffsetISOImage2Part1Start) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->ISO_IMAGE2= psFlash2xBitMap->ISO_IMAGE2 | FLASH2X_SECTION_PRESENT; + + + if(ReadISOSignature(Adapter,ISO_IMAGE2)== ISO_IMAGE_MAGIC_NUMBER) + psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_VALID; + + + //Calculation for extrating the Access permission + if(IsSectionWritable(Adapter, ISO_IMAGE2) == FALSE) + psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_RO; + + if(SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE2) + { + psFlash2xBitMap->ISO_IMAGE2 |= FLASH2X_SECTION_ACT ; + SetActiveISODone = TRUE; + } + + } + + /// + // IS0 IMAGE 1 + /// + if((psFlash2xCSInfo->OffsetISOImage1Part1Start) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->ISO_IMAGE1 = psFlash2xBitMap->ISO_IMAGE1 | FLASH2X_SECTION_PRESENT; + + if(ReadISOSignature(Adapter,ISO_IMAGE1) == ISO_IMAGE_MAGIC_NUMBER) + psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_VALID; + + // Calculation for extrating the Access permission + if(IsSectionWritable(Adapter, ISO_IMAGE1) == FALSE) + psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_RO; + + if(SetActiveISODone == FALSE && uiHighestPriISO == ISO_IMAGE1) + { + psFlash2xBitMap->ISO_IMAGE1 |= FLASH2X_SECTION_ACT ; + SetActiveISODone = TRUE; + } + } + + + + /// + // DSD2 + /// + if((psFlash2xCSInfo->OffsetFromZeroForDSD2Start) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->DSD2= psFlash2xBitMap->DSD2 | FLASH2X_SECTION_PRESENT; + + if(ReadDSDSignature(Adapter,DSD2)== DSD_IMAGE_MAGIC_NUMBER) + psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_VALID; + + //Calculation for extrating the Access permission + if(IsSectionWritable(Adapter, DSD2) == FALSE) + { + psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_RO; + + } + else + { + //Means section is writable + if((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD2)) + { + psFlash2xBitMap->DSD2 |= FLASH2X_SECTION_ACT ; + SetActiveDSDDone =TRUE ; + } + } + } + + /// + // DSD 1 + /// + if((psFlash2xCSInfo->OffsetFromZeroForDSD1Start) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->DSD1= psFlash2xBitMap->DSD1 | FLASH2X_SECTION_PRESENT; + + + if(ReadDSDSignature(Adapter,DSD1)== DSD_IMAGE_MAGIC_NUMBER) + psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_VALID; + + //Calculation for extrating the Access permission + if(IsSectionWritable(Adapter, DSD1) == FALSE) + { + psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_RO; + } + else + { + //Means section is writable + if((SetActiveDSDDone == FALSE) && (uiHighestPriDSD == DSD1)) + { + psFlash2xBitMap->DSD1 |= FLASH2X_SECTION_ACT ; + SetActiveDSDDone =TRUE ; + } + } + + } + + /// + //For DSD 0 + // + if((psFlash2xCSInfo->OffsetFromZeroForDSDStart) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->DSD0 = psFlash2xBitMap->DSD0 | FLASH2X_SECTION_PRESENT; + + if(ReadDSDSignature(Adapter,DSD0) == DSD_IMAGE_MAGIC_NUMBER) + psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_VALID; + + //Setting Access permission + if(IsSectionWritable(Adapter, DSD0) == FALSE) + { + psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_RO; + } + else + { + //Means section is writable + if((SetActiveDSDDone == FALSE) &&(uiHighestPriDSD == DSD0)) + { + psFlash2xBitMap->DSD0 |= FLASH2X_SECTION_ACT ; + SetActiveDSDDone =TRUE ; + } + } + } + + /// + // VSA 0 + /// + if((psFlash2xCSInfo->OffsetFromZeroForVSAStart) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->VSA0= psFlash2xBitMap->VSA0 | FLASH2X_SECTION_PRESENT; + + //Setting the Access Bit. Map is not defined hece setting it always valid + psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_VALID; + + //Calculation for extrating the Access permission + if(IsSectionWritable(Adapter, VSA0) == FALSE) + psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_RO; + + //By Default section is Active + psFlash2xBitMap->VSA0 |= FLASH2X_SECTION_ACT ; + + } + + + /// + // VSA 1 + /// + + if((psFlash2xCSInfo->OffsetFromZeroForVSA1Start) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->VSA1= psFlash2xBitMap->VSA1 | FLASH2X_SECTION_PRESENT; + + //Setting the Access Bit. Map is not defined hece setting it always valid + psFlash2xBitMap->VSA1|= FLASH2X_SECTION_VALID; + + //Checking For Access permission + if(IsSectionWritable(Adapter, VSA1) == FALSE) + psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_RO; + + //By Default section is Active + psFlash2xBitMap->VSA1 |= FLASH2X_SECTION_ACT ; + + } + + + /// + // VSA 2 + /// + + if((psFlash2xCSInfo->OffsetFromZeroForVSA2Start) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->VSA2= psFlash2xBitMap->VSA2 | FLASH2X_SECTION_PRESENT; + + + //Setting the Access Bit. Map is not defined hece setting it always valid + psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_VALID; + + //Checking For Access permission + if(IsSectionWritable(Adapter, VSA2) == FALSE) + psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_RO; + + //By Default section is Active + psFlash2xBitMap->VSA2 |= FLASH2X_SECTION_ACT ; + } + + /// + // SCSI Section + /// + if((psFlash2xCSInfo->OffsetFromZeroForScsiFirmware) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->SCSI= psFlash2xBitMap->SCSI | FLASH2X_SECTION_PRESENT; + + + //Setting the Access Bit. Map is not defined hece setting it always valid + psFlash2xBitMap->SCSI|= FLASH2X_SECTION_VALID; + + //Checking For Access permission + if(IsSectionWritable(Adapter, SCSI) == FALSE) + psFlash2xBitMap->SCSI |= FLASH2X_SECTION_RO; + + //By Default section is Active + psFlash2xBitMap->SCSI |= FLASH2X_SECTION_ACT ; + + } + + + /// + // Control Section + /// + if((psFlash2xCSInfo->OffsetFromZeroForControlSectionStart) != UNINIT_PTR_IN_CS) + { + //Setting the 0th Bit representing the Section is present or not. + psFlash2xBitMap->CONTROL_SECTION = psFlash2xBitMap->CONTROL_SECTION | (FLASH2X_SECTION_PRESENT); + + + //Setting the Access Bit. Map is not defined hece setting it always valid + psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_VALID; + + //Checking For Access permission + if(IsSectionWritable(Adapter, CONTROL_SECTION) == FALSE) + psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_RO; + + //By Default section is Active + psFlash2xBitMap->CONTROL_SECTION |= FLASH2X_SECTION_ACT ; + + } + + /// + // For Reserved Sections + /// + psFlash2xBitMap->Reserved0 = 0; + psFlash2xBitMap->Reserved0 = 0; + psFlash2xBitMap->Reserved0 = 0; + + BcmDumpFlash2xSectionBitMap(psFlash2xBitMap); + + return STATUS_SUCCESS ; + +} +/** +BcmSetActiveSection :- Set Active section is used to make priority field highest over other + section of same type. + +@Adapater :- Bcm Driver Private Data Structure +@eFlash2xSectionVal :- Flash section val whose priority has to be made highest. + +Return Value:- Make the priorit highest else return erorr code + +**/ +INT BcmSetActiveSection(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectVal) +{ + INT SectImagePriority = 0; + INT Status =STATUS_SUCCESS; + + //DSD_HEADER sDSD = {0}; + //ISO_HEADER sISO = {0}; + INT HighestPriDSD = 0 ; + INT HighestPriISO = 0; + + + + Status = IsSectionWritable(Adapter,eFlash2xSectVal) ; + if(Status != TRUE ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Provided Section <%d> is not writable",eFlash2xSectVal); + return STATUS_FAILURE; + } + + Adapter->bHeaderChangeAllowed = TRUE ; + switch(eFlash2xSectVal) + { + case ISO_IMAGE1 : + case ISO_IMAGE2 : + if(ReadISOSignature(Adapter,eFlash2xSectVal)== ISO_IMAGE_MAGIC_NUMBER ) + { + HighestPriISO = getHighestPriISO(Adapter); + + if(HighestPriISO == eFlash2xSectVal ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given ISO<%x> already has highest priority",eFlash2xSectVal ); + Status = STATUS_SUCCESS ; + break; + } + + SectImagePriority = ReadISOPriority(Adapter, HighestPriISO) + 1; + + if((SectImagePriority <= 0) && IsSectionWritable(Adapter,HighestPriISO)) + { + // This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF. + // We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO + // by user + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happend, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); + SectImagePriority = htonl(0x1); + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + HighestPriISO, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + SIGNATURE_SIZE, + TRUE); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Priority has not been written properly"); + Status = STATUS_FAILURE; + break ; + } + + HighestPriISO = getHighestPriISO(Adapter); + + if(HighestPriISO == eFlash2xSectVal ) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given ISO<%x> already has highest priority",eFlash2xSectVal ); + Status = STATUS_SUCCESS ; + break; + } + + SectImagePriority = 2; + } + + + SectImagePriority = htonl(SectImagePriority); + + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + eFlash2xSectVal, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + SIGNATURE_SIZE, + TRUE); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Priority has not been written properly"); + break ; + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); + Status = STATUS_FAILURE ; + break; + } + break; + case DSD0 : + case DSD1 : + case DSD2 : + if(ReadDSDSignature(Adapter,eFlash2xSectVal)== DSD_IMAGE_MAGIC_NUMBER) + { + HighestPriDSD = getHighestPriDSD(Adapter); + + if((HighestPriDSD == eFlash2xSectVal)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given DSD<%x> already has highest priority", eFlash2xSectVal); + Status = STATUS_SUCCESS ; + break; + } + + SectImagePriority = ReadDSDPriority(Adapter, HighestPriDSD) + 1 ; + if(SectImagePriority <= 0) + { + // This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF. + // We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD + // by user + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happend, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal); + SectImagePriority = htonl(0x1); + + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + HighestPriDSD, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + SIGNATURE_SIZE, + TRUE); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + break ; + } + + HighestPriDSD = getHighestPriDSD(Adapter); + + if((HighestPriDSD == eFlash2xSectVal)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Made the DSD: %x highest by reducing priority of other\n", eFlash2xSectVal); + Status = STATUS_SUCCESS ; + break; + } + + SectImagePriority = htonl(0x2); + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + HighestPriDSD, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + SIGNATURE_SIZE, + TRUE); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Priority has not been written properly"); + break ; + } + + HighestPriDSD = getHighestPriDSD(Adapter); + + if((HighestPriDSD == eFlash2xSectVal)) + { + Status = STATUS_SUCCESS ; + break; + } + SectImagePriority = 3 ; + + } + SectImagePriority = htonl(SectImagePriority); + Status = BcmFlash2xBulkWrite(Adapter, + &SectImagePriority, + eFlash2xSectVal, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + SIGNATURE_SIZE , + TRUE); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Priority has not been written properly"); + Status = STATUS_FAILURE ; + break ; + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Signature is currupted. Hence can't increase the priority"); + Status = STATUS_FAILURE ; + break; + } + break; + case VSA0 : + case VSA1 : + case VSA2 : + //Has to be decided + break ; + default : + Status = STATUS_FAILURE ; + break; + + } + + Adapter->bHeaderChangeAllowed = FALSE ; + return Status; + +} + +/** +BcmCopyISO - Used only for copying the ISO section +@Adapater :- Bcm Driver Private Data Structure +@sCopySectStrut :- Section copy structure + +Return value:- SUCCESS if copies successfully else negative error code + +**/ +INT BcmCopyISO(PMINI_ADAPTER Adapter, FLASH2X_COPY_SECTION sCopySectStrut) +{ + + PCHAR Buff = NULL; + FLASH2X_SECTION_VAL eISOReadPart = 0,eISOWritePart = 0; + UINT uiReadOffsetWithinPart = 0, uiWriteOffsetWithinPart = 0; + UINT uiTotalDataToCopy = 0; + BOOLEAN IsThisHeaderSector = FALSE ; + UINT sigOffset = 0; + UINT ISOLength = 0; + UINT Status = STATUS_SUCCESS; + UINT SigBuff[MAX_RW_SIZE]; + UINT i = 0; + + if(ReadISOSignature(Adapter,sCopySectStrut.SrcSection) != ISO_IMAGE_MAGIC_NUMBER) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "error as Source ISO Section does not have valid signature"); + return STATUS_FAILURE; + } + + Status = BcmFlash2xBulkRead(Adapter, + &ISOLength, + sCopySectStrut.SrcSection, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER,ISOImageSize), + 4); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO\n"); + return Status; + } + + ISOLength = htonl(ISOLength); + + if(ISOLength % Adapter->uiSectorSize) + { + ISOLength = Adapter->uiSectorSize*(1 + ISOLength/Adapter->uiSectorSize); + } + + sigOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImageMagicNumber); + + Buff = kzalloc(Adapter->uiSectorSize, GFP_KERNEL); + + if(Buff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed for section size"); + return -ENOMEM; + } + + if(sCopySectStrut.SrcSection ==ISO_IMAGE1 && sCopySectStrut.DstSection ==ISO_IMAGE2) + { + eISOReadPart = ISO_IMAGE1 ; + eISOWritePart = ISO_IMAGE2 ; + uiReadOffsetWithinPart = 0; + uiWriteOffsetWithinPart = 0 ; + + uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); + + if(uiTotalDataToCopy < ISOLength) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); + return STATUS_FAILURE; + } + + uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); + + if(uiTotalDataToCopy < ISOLength) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); + return STATUS_FAILURE; + } + + uiTotalDataToCopy = ISOLength; + + CorruptISOSig(Adapter,ISO_IMAGE2); + + while(uiTotalDataToCopy) + { + if(uiTotalDataToCopy == Adapter->uiSectorSize) + { + //Setting for write of first sector. First sector is assumed to be written in last + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Writing the signature sector"); + eISOReadPart = ISO_IMAGE1 ; + uiReadOffsetWithinPart = 0; + eISOWritePart = ISO_IMAGE2; + uiWriteOffsetWithinPart = 0 ; + IsThisHeaderSector = TRUE ; + + } + else + { + uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize ; + uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize ; + + if((eISOReadPart == ISO_IMAGE1) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start) )) + { + eISOReadPart = ISO_IMAGE1_PART2 ; + uiReadOffsetWithinPart = 0; + } + if((eISOReadPart == ISO_IMAGE1_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) + { + eISOReadPart = ISO_IMAGE1_PART3 ; + uiReadOffsetWithinPart = 0; + } + if((eISOWritePart == ISO_IMAGE2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start))) + { + eISOWritePart = ISO_IMAGE2_PART2 ; + uiWriteOffsetWithinPart = 0; + } + if((eISOWritePart == ISO_IMAGE2_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) + { + eISOWritePart = ISO_IMAGE2_PART3 ; + uiWriteOffsetWithinPart = 0; + } + } + + Status = BcmFlash2xBulkRead(Adapter, + (PUINT)Buff, + eISOReadPart, + uiReadOffsetWithinPart, + Adapter->uiSectorSize + ); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); + break; + } + + if(IsThisHeaderSector == TRUE) + { + //If this is header sector write 0xFFFFFFFF at the sig time and in last write sig + memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); + + for(i = 0; i < MAX_RW_SIZE;i++) + *(Buff + sigOffset + i) = 0xFF; + } + Adapter->bHeaderChangeAllowed = TRUE ; + + Status = BcmFlash2xBulkWrite(Adapter, + (PUINT)Buff, + eISOWritePart, + uiWriteOffsetWithinPart, + Adapter->uiSectorSize, + TRUE); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); + break; + } + + Adapter->bHeaderChangeAllowed = FALSE; + + if(IsThisHeaderSector == TRUE) + { + WriteToFlashWithoutSectorErase(Adapter, + SigBuff, + eISOWritePart, + sigOffset, + MAX_RW_SIZE); + IsThisHeaderSector = FALSE ; + } + //substracting the written Data + uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ; + } + + + } + + if(sCopySectStrut.SrcSection ==ISO_IMAGE2 && sCopySectStrut.DstSection ==ISO_IMAGE1) + { + eISOReadPart = ISO_IMAGE2 ; + eISOWritePart = ISO_IMAGE1 ; + uiReadOffsetWithinPart = 0; + uiWriteOffsetWithinPart = 0 ; + + uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage2Part3Start); + + if(uiTotalDataToCopy < ISOLength) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Source ISO Section does not have valid signature"); + return STATUS_FAILURE; + } + + uiTotalDataToCopy =(Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start)+ + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3End) - + (Adapter->psFlash2xCSInfo->OffsetISOImage1Part3Start); + + if(uiTotalDataToCopy < ISOLength) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"error as Dest ISO Section does not have enough section size"); + return STATUS_FAILURE; + } + + uiTotalDataToCopy = ISOLength; + + CorruptISOSig(Adapter,ISO_IMAGE1); + + while(uiTotalDataToCopy) + { + if(uiTotalDataToCopy == Adapter->uiSectorSize) + { + //Setting for write of first sector. First sector is assumed to be written in last + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Writing the signature sector"); + eISOReadPart = ISO_IMAGE2 ; + uiReadOffsetWithinPart = 0; + eISOWritePart = ISO_IMAGE1; + uiWriteOffsetWithinPart = 0 ; + IsThisHeaderSector = TRUE; + + } + else + { + uiReadOffsetWithinPart = uiReadOffsetWithinPart + Adapter->uiSectorSize ; + uiWriteOffsetWithinPart = uiWriteOffsetWithinPart + Adapter->uiSectorSize ; + + if((eISOReadPart == ISO_IMAGE2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start) )) + { + eISOReadPart = ISO_IMAGE2_PART2 ; + uiReadOffsetWithinPart = 0; + } + if((eISOReadPart == ISO_IMAGE2_PART2) && (uiReadOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage2Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage2Part2Start))) + { + eISOReadPart = ISO_IMAGE2_PART3 ; + uiReadOffsetWithinPart = 0; + } + if((eISOWritePart == ISO_IMAGE1) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part1End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start))) + { + eISOWritePart = ISO_IMAGE1_PART2 ; + uiWriteOffsetWithinPart = 0; + } + if((eISOWritePart == ISO_IMAGE1_PART2) && (uiWriteOffsetWithinPart == (Adapter->psFlash2xCSInfo->OffsetISOImage1Part2End - Adapter->psFlash2xCSInfo->OffsetISOImage1Part2Start))) + { + eISOWritePart = ISO_IMAGE1_PART3 ; + uiWriteOffsetWithinPart = 0; + } + } + + Status = BcmFlash2xBulkRead(Adapter, + (PUINT)Buff, + eISOReadPart, + uiReadOffsetWithinPart, + Adapter->uiSectorSize + ); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOReadPart, uiReadOffsetWithinPart); + break; + } + + if(IsThisHeaderSector == TRUE) + { + //If this is header sector write 0xFFFFFFFF at the sig time and in last write sig + memcpy(SigBuff, Buff + sigOffset, MAX_RW_SIZE); + + for(i = 0; i < MAX_RW_SIZE;i++) + *(Buff + sigOffset + i) = 0xFF; + + } + Adapter->bHeaderChangeAllowed = TRUE ; + Status = BcmFlash2xBulkWrite(Adapter, + (PUINT)Buff, + eISOWritePart, + uiWriteOffsetWithinPart, + Adapter->uiSectorSize, + TRUE); + + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Write failed while copying ISO: Part: %x, OffsetWithinPart: %x\n", eISOWritePart, uiWriteOffsetWithinPart); + break; + } + + Adapter->bHeaderChangeAllowed = FALSE ; + + if(IsThisHeaderSector == TRUE) + { + WriteToFlashWithoutSectorErase(Adapter, + SigBuff, + eISOWritePart, + sigOffset, + MAX_RW_SIZE); + IsThisHeaderSector = FALSE ; + } + + //substracting the written Data + uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ; + } + + + } + + bcm_kfree(Buff); + + return Status; +} +/** +BcmFlash2xCorruptSig : this API is used to corrupt the written sig in Bcm Header present in flash section. + It will corrupt the sig, if Section is writable, by making first bytes as zero. +@Adapater :- Bcm Driver Private Data Structure +@eFlash2xSectionVal :- Flash section val which has header + +Return Value :- + Sucess :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS + Failure :-Return negative error code + + +**/ +INT BcmFlash2xCorruptSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +{ + + INT Status = STATUS_SUCCESS ; + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Section Value :%x \n", eFlash2xSectionVal); + + if((eFlash2xSectionVal == DSD0) || (eFlash2xSectionVal == DSD1) || (eFlash2xSectionVal == DSD2)) + { + Status = CorruptDSDSig(Adapter, eFlash2xSectionVal); + } + else if(eFlash2xSectionVal == ISO_IMAGE1 || eFlash2xSectionVal == ISO_IMAGE2) + { + Status = CorruptISOSig(Adapter, eFlash2xSectionVal); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Given Section <%d>does not have Header",eFlash2xSectionVal); + return STATUS_SUCCESS; + } + return Status; +} +/** +BcmFlash2xWriteSig :-this API is used to Write the sig if requested Section has + header and Write Permission. +@Adapater :- Bcm Driver Private Data Structure +@eFlashSectionVal :- Flash section val which has header + +Return Value :- + Sucess :- If Section is present and writable write the sig and return STATUS_SUCCESS + Failure :-Return negative error code + +**/ +INT BcmFlash2xWriteSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlashSectionVal) +{ + + UINT uiSignature = 0 ; + UINT uiOffset = 0; + //DSD_HEADER dsdHeader = {0}; + + if(Adapter->bSigCorrupted == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Signature is not corrupted by driver, hence not restoring\n"); + return STATUS_SUCCESS; + } + if(Adapter->bAllDSDWriteAllow == FALSE) + { + if(IsSectionWritable(Adapter,eFlashSectionVal) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Write signature"); + return SECTOR_IS_NOT_WRITABLE; + } + } + if((eFlashSectionVal == DSD0) ||(eFlashSectionVal == DSD1) || (eFlashSectionVal == DSD2)) + { + uiSignature = htonl(DSD_IMAGE_MAGIC_NUMBER) ; + uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader ; + + uiOffset += FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber); + + if((ReadDSDSignature(Adapter,eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Corrupted Pattern is not there. Hence won't write sig"); + return STATUS_FAILURE; + } + + } + else if((eFlashSectionVal == ISO_IMAGE1) || (eFlashSectionVal == ISO_IMAGE2)) + { + uiSignature = htonl(ISO_IMAGE_MAGIC_NUMBER); + //uiOffset = 0; + uiOffset = FIELD_OFFSET_IN_HEADER(PISO_HEADER,ISOImageMagicNumber); + if((ReadISOSignature(Adapter,eFlashSectionVal) & 0xFF000000) != CORRUPTED_PATTERN) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Currupted Pattern is not there. Hence won't write sig"); + return STATUS_FAILURE; + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"GIVEN SECTION< %d > IS NOT VALID FOR SIG WRITE...", eFlashSectionVal); + return STATUS_FAILURE; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Restoring the signature"); + + + Adapter->bHeaderChangeAllowed = TRUE; + Adapter->bSigCorrupted = FALSE; + BcmFlash2xBulkWrite(Adapter, &uiSignature,eFlashSectionVal,uiOffset,SIGNATURE_SIZE,TRUE); + Adapter->bHeaderChangeAllowed = FALSE; + + + + return STATUS_SUCCESS; +} +/** +validateFlash2xReadWrite :- This API is used to validate the user request for Read/Write. + if requested Bytes goes beyond the Requested section, it reports error. +@Adapater :- Bcm Driver Private Data Structure +@psFlash2xReadWrite :-Flash2x Read/write structure pointer + +Return values:-Return TRUE is request is valid else FALSE. + + +**/ +INT validateFlash2xReadWrite(PMINI_ADAPTER Adapter, PFLASH2X_READWRITE psFlash2xReadWrite) +{ + UINT uiNumOfBytes = 0 ; + UINT uiSectStartOffset = 0 ; + UINT uiSectEndOffset = 0; + uiNumOfBytes = psFlash2xReadWrite->numOfBytes; + + if(IsSectionExistInFlash(Adapter,psFlash2xReadWrite->Section) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section<%x> does not exixt in Flash",psFlash2xReadWrite->Section); + return FALSE; + } + uiSectStartOffset = BcmGetSectionValStartOffset(Adapter,psFlash2xReadWrite->Section); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Start offset :%x ,section :%d\n",uiSectStartOffset,psFlash2xReadWrite->Section); + if((psFlash2xReadWrite->Section == ISO_IMAGE1) ||(psFlash2xReadWrite->Section == ISO_IMAGE2)) + { + if(psFlash2xReadWrite->Section == ISO_IMAGE1) + { + uiSectEndOffset = BcmGetSectionValEndOffset(Adapter,ISO_IMAGE1) - + BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1)+ + BcmGetSectionValEndOffset(Adapter,ISO_IMAGE1_PART2) - + BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1_PART2)+ + BcmGetSectionValEndOffset(Adapter,ISO_IMAGE1_PART3) - + BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1_PART3); + } + else if(psFlash2xReadWrite->Section == ISO_IMAGE2) + { + uiSectEndOffset = BcmGetSectionValEndOffset(Adapter,ISO_IMAGE2) - + BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2)+ + BcmGetSectionValEndOffset(Adapter,ISO_IMAGE2_PART2) - + BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2_PART2)+ + BcmGetSectionValEndOffset(Adapter,ISO_IMAGE2_PART3) - + BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2_PART3); + + } + + //since this uiSectEndoffset is the size of iso Image. hence for calculating the vitual endoffset + //it should be added in startoffset. so that check done in last of this function can be valued. + uiSectEndOffset = uiSectStartOffset + uiSectEndOffset ; + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Total size of the ISO Image :%x",uiSectEndOffset); + } + else + uiSectEndOffset = BcmGetSectionValEndOffset(Adapter,psFlash2xReadWrite->Section); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "End offset :%x \n",uiSectEndOffset); + + //Checking the boundary condition + if((uiSectStartOffset + psFlash2xReadWrite->offset + uiNumOfBytes) <= uiSectEndOffset) + return TRUE; + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Invalid Request...."); + return FALSE; + } + +} + +/** +IsFlash2x :- check for Flash 2.x +@Adapater :- Bcm Driver Private Data Structure + +Return value:- + return TRUE if flah2.x of hgher version else return false. +**/ + +INT IsFlash2x(PMINI_ADAPTER Adapter) +{ + if(Adapter->uiFlashLayoutMajorVersion >= FLASH_2X_MAJOR_NUMBER) + return TRUE ; + else + return FALSE; +} +/** +GetFlashBaseAddr :- Calculate the Flash Base address +@Adapater :- Bcm Driver Private Data Structure + +Return Value:- + Success :- Base Address of the Flash +**/ + +INT GetFlashBaseAddr(PMINI_ADAPTER Adapter) +{ + + UINT uiBaseAddr = 0; + + if(Adapter->bDDRInitDone) + { + /* + For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr + In case of Raw Read... use the default value + */ + if(Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && + !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)) + ) + uiBaseAddr = Adapter->uiFlashBaseAdd ; + else + uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT; + } + else + { + /* + For All Valid Flash Versions... except 1.1, take the value from FlashBaseAddr + In case of Raw Read... use the default value + */ + if(Adapter->uiFlashLayoutMajorVersion && (Adapter->bFlashRawRead == FALSE) && + !((Adapter->uiFlashLayoutMajorVersion == 1) && (Adapter->uiFlashLayoutMinorVersion == 1)) + ) + uiBaseAddr = Adapter->uiFlashBaseAdd | FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; + else + uiBaseAddr = FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT; + } + + return uiBaseAddr ; +} +/** +BcmCopySection :- This API is used to copy the One section in another. Both section should + be contiuous and of same size. Hence this Will not be applicabe to copy ISO. + +@Adapater :- Bcm Driver Private Data Structure +@SrcSection :- Source section From where data has to be copied +@DstSection :- Destination section to which data has to be copied +@offset :- Offset from/to where data has to be copied from one section to another. +@numOfBytes :- number of byes that has to be copyed from one section to another at given offset. + in case of numofBytes equal zero complete section will be copied. + +Return Values- + Sucess : Return STATUS_SUCCESS + Faillure :- return negative error code + +**/ + +INT BcmCopySection(PMINI_ADAPTER Adapter, + FLASH2X_SECTION_VAL SrcSection, + FLASH2X_SECTION_VAL DstSection, + UINT offset, + UINT numOfBytes) +{ + UINT BuffSize = 0 ; + UINT BytesToBeCopied = 0; + PUCHAR pBuff = NULL ; + INT Status = STATUS_SUCCESS ; + if(SrcSection == DstSection) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source and Destination should be different ...try again"); + return -EINVAL; + } + if((SrcSection != DSD0) && (SrcSection != DSD1) && (SrcSection != DSD2)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Source should be DSD subsection"); + return -EINVAL; + } + if((DstSection != DSD0) && (DstSection != DSD1) && (DstSection != DSD2)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Destination should be DSD subsection"); + return -EINVAL; + } + + #if 0 + else + { + if((SrcSection == VSA0) || (SrcSection == VSA1) || (SrcSection == VSA2)) + { + if((DstSection != VSA0) && (DstSection != VSA1) && (DstSection != VSA2)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Source and Destion secton is not of same type"); + return -EINVAL; + } + } + + } + #endif + //if offset zero means have to copy complete secton + + if(numOfBytes == 0) + { + numOfBytes = BcmGetSectionValEndOffset(Adapter,SrcSection) + - BcmGetSectionValStartOffset(Adapter,SrcSection); + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL," Section Size :0x%x",numOfBytes); + } + + if((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter,SrcSection) + - BcmGetSectionValStartOffset(Adapter,SrcSection)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Input parameters going beyond the section offS: %x numB: %x of Source Section\n", + offset, numOfBytes); + return -EINVAL; + } + + if((offset + numOfBytes) > BcmGetSectionValEndOffset(Adapter,DstSection) + - BcmGetSectionValStartOffset(Adapter,DstSection)) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0," Input parameters going beyond the section offS: %x numB: %x of Destination Section\n", + offset, numOfBytes); + return -EINVAL; + } + + + if(numOfBytes > Adapter->uiSectorSize ) + BuffSize = Adapter->uiSectorSize; + else + BuffSize = numOfBytes ; + + pBuff = (PCHAR)kzalloc(BuffSize, GFP_KERNEL); + if(pBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed.. "); + return -ENOMEM; + } + + + BytesToBeCopied = Adapter->uiSectorSize ; + if(offset % Adapter->uiSectorSize) + BytesToBeCopied = Adapter->uiSectorSize - (offset % Adapter->uiSectorSize); + if(BytesToBeCopied > numOfBytes) + BytesToBeCopied = numOfBytes ; + + + + Adapter->bHeaderChangeAllowed = TRUE; + + do + { + Status = BcmFlash2xBulkRead(Adapter, (PUINT)pBuff, SrcSection , offset,BytesToBeCopied); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Read failed at offset :%d for NOB :%d", SrcSection,BytesToBeCopied); + break; + } + Status = BcmFlash2xBulkWrite(Adapter,(PUINT)pBuff,DstSection,offset,BytesToBeCopied,FALSE); + if(Status) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Write failed at offset :%d for NOB :%d", DstSection,BytesToBeCopied); + break; + } + offset = offset + BytesToBeCopied; + numOfBytes = numOfBytes - BytesToBeCopied ; + if(numOfBytes) + { + if(numOfBytes > Adapter->uiSectorSize ) + BytesToBeCopied = Adapter->uiSectorSize; + else + BytesToBeCopied = numOfBytes; + } + }while(numOfBytes > 0) ; + bcm_kfree(pBuff); + Adapter->bHeaderChangeAllowed = FALSE ; + return Status; +} + +/** +SaveHeaderIfPresent :- This API is use to Protect the Header in case of Header Sector write +@Adapater :- Bcm Driver Private Data Structure +@pBuff :- Data buffer that has to be written in sector having the header map. +@uiOffset :- Flash offset that has to be written. + +Return value :- + Sucess :- On sucess return STATUS_SUCCESS + Faillure :- Return negative error code + +**/ + +INT SaveHeaderIfPresent(PMINI_ADAPTER Adapter, PUCHAR pBuff, UINT uiOffset) +{ + UINT offsetToProtect = 0,HeaderSizeToProtect =0; + BOOLEAN bHasHeader = FALSE ; + PUCHAR pTempBuff =NULL; + UINT uiSectAlignAddr = 0; + UINT sig = 0; + + #if 0 + //if Chenges in Header is allowed, Return back + if(Adapter->bHeaderChangeAllowed == TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Header Change is allowed"); + return STATUS_SUCCESS ; + } + #endif + //making the offset sector alligned + uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1); + + + if((uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD2)- Adapter->uiSectorSize)|| + (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD1)- Adapter->uiSectorSize)|| + (uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD0)- Adapter->uiSectorSize)) + { + + //offset from the sector boundry having the header map + offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize; + HeaderSizeToProtect = sizeof(DSD_HEADER); + bHasHeader = TRUE ; + } + + if(uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter,ISO_IMAGE1) || + uiSectAlignAddr == BcmGetSectionValStartOffset(Adapter,ISO_IMAGE2)) + { + offsetToProtect = 0; + HeaderSizeToProtect = sizeof(ISO_HEADER); + bHasHeader = TRUE; + } + //If Header is present overwrite passed buffer with this + if(bHasHeader && (Adapter->bHeaderChangeAllowed == FALSE)) + { + pTempBuff = (PUCHAR)kzalloc(HeaderSizeToProtect, GFP_KERNEL); + if(pTempBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Memory allocation failed "); + return -ENOMEM; + } + //Read header + BeceemFlashBulkRead(Adapter,(PUINT)pTempBuff,(uiSectAlignAddr + offsetToProtect),HeaderSizeToProtect); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,pTempBuff ,HeaderSizeToProtect); + //Replace Buffer content with Header + memcpy(pBuff +offsetToProtect,pTempBuff,HeaderSizeToProtect); + + bcm_kfree(pTempBuff); + } + if(bHasHeader && Adapter->bSigCorrupted) + { + sig = *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber))); + sig = ntohl(sig); + if((sig & 0xFF000000) != CORRUPTED_PATTERN) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Desired pattern is not at sig offset. Hence won't restore"); + Adapter->bSigCorrupted = FALSE; + return STATUS_SUCCESS; + } + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL," Corrupted sig is :%X", sig); + *((PUINT)(pBuff + offsetToProtect + FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber)))= htonl(DSD_IMAGE_MAGIC_NUMBER); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Restoring the signature in Header Write only"); + Adapter->bSigCorrupted = FALSE; + } + + return STATUS_SUCCESS ; +} +INT BcmMakeFlashCSActive(PMINI_ADAPTER Adapter, UINT offset) +{ + UINT GPIOConfig = 0 ; + + + if(Adapter->bFlashRawRead == FALSE) + { + //Applicable for Flash2.x + if(IsFlash2x(Adapter) == FALSE) + return STATUS_SUCCESS; + } + + if(offset/FLASH_PART_SIZE) + { + //bit[14..12] -> will select make Active CS1, CS2 or CS3 + // Select CS1, CS2 and CS3 (CS0 is dedicated pin) + rdmalt(Adapter,FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); + GPIOConfig |= (7 << 12); + wrmalt(Adapter,FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); + } + + return STATUS_SUCCESS ; +} +/** +BcmDoChipSelect : This will selcet the appropriate chip for writing. +@Adapater :- Bcm Driver Private Data Structure + +OutPut:- + Select the Appropriate chip and retrn status Sucess +**/ +INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset) +{ + UINT FlashConfig = 0; + INT ChipNum = 0; + UINT GPIOConfig = 0; + UINT PartNum = 0; + + ChipNum = offset / FLASH_PART_SIZE ; + + // + // Chip Select mapping to enable flash0. + // To select flash 0, we have to OR with (0<<12). + // ORing 0 will have no impact so not doing that part. + // In future if Chip select value changes from 0 to non zero, + // That needs be taken care with backward comaptibility. No worries for now. + // + + /* + SelectedChip Variable is the selection that the host is 100% Sure the same as what the register will hold. This can be ONLY ensured + if the Chip doesn't goes to low power mode while the flash operation is in progress (NVMRdmWrmLock is taken) + Before every new Flash Write operation, we reset the variable. This is to ensure that after any wake-up from + power down modes (Idle mode/shutdown mode), the values in the register will be different. + */ + + if(Adapter->SelectedChip == ChipNum) + return STATUS_SUCCESS; + + //BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "Selected Chip :%x", ChipNum); + Adapter->SelectedChip = ChipNum ; + + //bit[13..12] will select the appropriate chip + rdmalt(Adapter,FLASH_CONFIG_REG, &FlashConfig, 4); + rdmalt(Adapter,FLASH_GPIO_CONFIG_REG, &GPIOConfig, 4); + + { + switch(ChipNum) + { + case 0: + PartNum = 0; + break; + case 1: + PartNum = 3; + GPIOConfig |= (0x4 << CHIP_SELECT_BIT12); + break; + case 2: + PartNum = 1; + GPIOConfig |= (0x1 << CHIP_SELECT_BIT12); + break; + case 3: + PartNum = 2; + GPIOConfig |= (0x2 << CHIP_SELECT_BIT12); + break; + } + } + /* In case the bits already written in the FLASH_CONFIG_REG is same as what the user desired, + nothing to do... can return immediately. + ASSUMPTION: FLASH_GPIO_CONFIG_REG will be in sync with FLASH_CONFIG_REG. + Even if the chip goes to low power mode, it should wake with values in each register in sync with each other. + These values are not written by host other than during CHIP_SELECT. + */ + if(PartNum == ((FlashConfig >> CHIP_SELECT_BIT12) & 0x3)) + return STATUS_SUCCESS; + + //clearing the bit[13..12] + FlashConfig &= 0xFFFFCFFF; + FlashConfig = (FlashConfig | (PartNum<psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + FIELD_OFFSET_IN_HEADER(PDSD_HEADER,DSDImageMagicNumber), + SIGNATURE_SIZE); + + uiDSDsig = ntohl(uiDSDsig); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD SIG :%x", uiDSDsig); + + return uiDSDsig ; +} +INT ReadDSDPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL dsd) +{ + //UINT priOffsetInMap = 0 ; + INT uiDSDPri = STATUS_FAILURE; + //DSD_HEADER dsdHeader = {0}; + //priOffsetInMap = (PUCHAR)&(dsdHeader.DSDImagePriority) -(PUCHAR)&dsdHeader; + if(IsSectionWritable(Adapter,dsd)) + { + if(ReadDSDSignature(Adapter,dsd)== DSD_IMAGE_MAGIC_NUMBER) + { + BcmFlash2xBulkRead(Adapter, + &uiDSDPri, + dsd, + Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader +FIELD_OFFSET_IN_HEADER(PDSD_HEADER, DSDImagePriority), + 4); + + uiDSDPri = ntohl(uiDSDPri); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"DSD<%x> Priority :%x", dsd, uiDSDPri); + + } + } + return uiDSDPri; +} +FLASH2X_SECTION_VAL getHighestPriDSD(PMINI_ADAPTER Adapter) +{ + INT DSDHighestPri = STATUS_FAILURE; + INT DsdPri= 0 ; + FLASH2X_SECTION_VAL HighestPriDSD = 0 ; + + if(IsSectionWritable(Adapter,DSD2)) + { + DSDHighestPri = ReadDSDPriority(Adapter,DSD2); + HighestPriDSD = DSD2 ; + } + if(IsSectionWritable(Adapter,DSD1)) + { + DsdPri = ReadDSDPriority(Adapter,DSD1); + if(DSDHighestPri < DsdPri) + { + DSDHighestPri = DsdPri ; + HighestPriDSD = DSD1; + } + } + if(IsSectionWritable(Adapter,DSD0)) + { + DsdPri = ReadDSDPriority(Adapter,DSD0); + if(DSDHighestPri < DsdPri) + { + DSDHighestPri = DsdPri ; + HighestPriDSD = DSD0; + } + } + if(HighestPriDSD) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Highest DSD :%x , and its Pri :%x", HighestPriDSD, DSDHighestPri); + return HighestPriDSD ; +} + +INT ReadISOSignature(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso) +{ + UINT uiISOsig = 0; + //UINT sigoffsetInMap = 0; + //ISO_HEADER ISOHeader = {0}; + + + //sigoffsetInMap =(PUCHAR)&(ISOHeader.ISOImageMagicNumber) -(PUCHAR)&ISOHeader; + + if(iso != ISO_IMAGE1 && iso != ISO_IMAGE2) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"passed section value is not for ISOs"); + return STATUS_FAILURE; + } + BcmFlash2xBulkRead(Adapter, + &uiISOsig, + iso, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER,ISOImageMagicNumber), + SIGNATURE_SIZE); + + uiISOsig = ntohl(uiISOsig); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO SIG :%x", uiISOsig); + + return uiISOsig ; +} +INT ReadISOPriority(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL iso) +{ + + INT ISOPri = STATUS_FAILURE; + if(IsSectionWritable(Adapter,iso)) + { + if(ReadISOSignature(Adapter,iso)== ISO_IMAGE_MAGIC_NUMBER) + { + BcmFlash2xBulkRead(Adapter, + &ISOPri, + iso, + 0 + FIELD_OFFSET_IN_HEADER(PISO_HEADER, ISOImagePriority), + 4); + + ISOPri = ntohl(ISOPri); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"ISO<%x> Priority :%x", iso, ISOPri); + + } + } + return ISOPri; +} +FLASH2X_SECTION_VAL getHighestPriISO(PMINI_ADAPTER Adapter) +{ + INT ISOHighestPri = STATUS_FAILURE; + INT ISOPri= 0 ; + FLASH2X_SECTION_VAL HighestPriISO = NO_SECTION_VAL ; + + if(IsSectionWritable(Adapter,ISO_IMAGE2)) + { + ISOHighestPri = ReadISOPriority(Adapter,ISO_IMAGE2); + HighestPriISO = ISO_IMAGE2 ; + } + if(IsSectionWritable(Adapter,ISO_IMAGE1)) + { + ISOPri = ReadISOPriority(Adapter,ISO_IMAGE1); + if(ISOHighestPri < ISOPri) + { + ISOHighestPri = ISOPri ; + HighestPriISO = ISO_IMAGE1; + } + } + if(HighestPriISO) + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Highest ISO :%x and its Pri :%x",HighestPriISO,ISOHighestPri); + return HighestPriISO ; +} +INT WriteToFlashWithoutSectorErase(PMINI_ADAPTER Adapter, + PUINT pBuff, + FLASH2X_SECTION_VAL eFlash2xSectionVal, + UINT uiOffset, + UINT uiNumBytes + ) +{ +#if !defined(BCM_SHM_INTERFACE) || defined(FLASH_DIRECT_ACCESS) + UINT uiTemp = 0, value = 0 ; + UINT i = 0; + UINT uiPartOffset = 0; +#endif + UINT uiStartOffset = 0; + //Adding section start address + INT Status = STATUS_SUCCESS; + PUCHAR pcBuff = (PUCHAR)pBuff; + + if(uiNumBytes % Adapter->ulFlashWriteSize) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Writing without Sector Erase for non-FlashWriteSize number of bytes 0x%x\n", uiNumBytes); + return STATUS_FAILURE; + } + + uiStartOffset = BcmGetSectionValStartOffset(Adapter,eFlash2xSectionVal); + + if(IsSectionExistInVendorInfo(Adapter,eFlash2xSectionVal)) + { + return vendorextnWriteSectionWithoutErase(Adapter, pcBuff, eFlash2xSectionVal, uiOffset, uiNumBytes); + } + + uiOffset = uiOffset + uiStartOffset; + +#if defined(BCM_SHM_INTERFACE) && !defined(FLASH_DIRECT_ACCESS) + Status = bcmflash_raw_writenoerase((uiOffset/FLASH_PART_SIZE),(uiOffset % FLASH_PART_SIZE), pcBuff,uiNumBytes); +#else + rdmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + value = 0; + wrmalt(Adapter, 0x0f000C80,&value, sizeof(value)); + + Adapter->SelectedChip = RESET_CHIP_SELECT; + BcmDoChipSelect(Adapter,uiOffset); + uiPartOffset = (uiOffset & (FLASH_PART_SIZE - 1)) + GetFlashBaseAddr(Adapter); + + for(i = 0 ; i< uiNumBytes; i += Adapter->ulFlashWriteSize) + { + if(Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) + Status = flashByteWrite(Adapter,uiPartOffset, pcBuff); + else + Status = flashWrite(Adapter,uiPartOffset, pcBuff); + + if(Status != STATUS_SUCCESS) + break; + + pcBuff = pcBuff + Adapter->ulFlashWriteSize; + uiPartOffset = uiPartOffset + Adapter->ulFlashWriteSize; + } + wrmalt(Adapter, 0x0f000C80, &uiTemp, sizeof(uiTemp)); + Adapter->SelectedChip = RESET_CHIP_SELECT; +#endif + + return Status; +} + +#if 0 +UINT getNumOfSubSectionWithWRPermisson(PMINI_ADAPTER Adapter, SECTION_TYPE secType) +{ + + UINT numOfWRSubSec = 0; + switch(secType) + { + case ISO : + if(IsSectionWritable(Adapter,ISO_IMAGE1)) + numOfWRSubSec = numOfWRSubSec + 1; + if(IsSectionWritable(Adapter,ISO_IMAGE2)) + numOfWRSubSec = numOfWRSubSec + 1; + break; + + case DSD : + if(IsSectionWritable(Adapter,DSD2)) + numOfWRSubSec = numOfWRSubSec + 1; + if(IsSectionWritable(Adapter,DSD1)) + numOfWRSubSec = numOfWRSubSec + 1; + if(IsSectionWritable(Adapter,DSD0)) + numOfWRSubSec = numOfWRSubSec + 1; + break ; + + case VSA : + //for VSA Add code Here + default : + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Invalid secton<%d> is passed", secType);\ + numOfWRSubSec = 0; + + } + return numOfWRSubSec; +} +#endif +BOOLEAN IsSectionExistInFlash(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL section) +{ + + BOOLEAN SectionPresent = FALSE ; + + switch(section) + { + + case ISO_IMAGE1 : + if((Adapter->psFlash2xCSInfo->OffsetISOImage1Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectionPresent = TRUE ; + break; + case ISO_IMAGE2 : + if((Adapter->psFlash2xCSInfo->OffsetISOImage2Part1Start != UNINIT_PTR_IN_CS) && + (IsNonCDLessDevice(Adapter) == FALSE)) + SectionPresent = TRUE ; + break; + case DSD0 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSDStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + case DSD1 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD1Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + case DSD2 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForDSD2Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + case VSA0 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSAStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + case VSA1 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA1Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + case VSA2 : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForVSA2Start != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + case SCSI : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForScsiFirmware != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + case CONTROL_SECTION : + if(Adapter->psFlash2xCSInfo->OffsetFromZeroForControlSectionStart != UNINIT_PTR_IN_CS) + SectionPresent = TRUE ; + break; + default : + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section Does not exist in Flash 2.x"); + SectionPresent = FALSE; + } + return SectionPresent ; +} +INT IsSectionWritable(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL Section) +{ + INT offset = STATUS_FAILURE; + INT Status = FALSE; + if(IsSectionExistInFlash(Adapter,Section) == FALSE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section <%d> does not exixt", Section); + return FALSE; + } + offset = BcmGetSectionValStartOffset(Adapter,Section); + if(offset == INVALID_OFFSET) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section<%d> does not exixt", Section); + return FALSE; + } + + if(IsSectionExistInVendorInfo(Adapter,Section)) + { + return !(Adapter->psFlash2xVendorInfo->VendorSection[Section].AccessFlags & FLASH2X_SECTION_RO); + } + + Status = IsOffsetWritable(Adapter,offset); + return Status ; +} + +INT CorruptDSDSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +{ + + PUCHAR pBuff = 0 ; + UINT sig = 0; + UINT uiOffset = 0; + UINT BlockStatus = 0; + UINT uiSectAlignAddr = 0; + + Adapter->bSigCorrupted = FALSE; + + if(Adapter->bAllDSDWriteAllow == FALSE) + { + if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence cant Corrupt signature"); + return SECTOR_IS_NOT_WRITABLE; + } + } + + pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL); + if(pBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Can't allocate memorey"); + return -ENOMEM ; + } + + uiOffset = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader + sizeof(DSD_HEADER); + uiOffset -= MAX_RW_SIZE ; + + BcmFlash2xBulkRead(Adapter, (PUINT)pBuff,eFlash2xSectionVal,uiOffset,MAX_RW_SIZE); + + + sig = *((PUINT)(pBuff +12)); + sig =ntohl(sig); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,pBuff,MAX_RW_SIZE); + //Now corrupting the sig by corrupting 4th last Byte. + *(pBuff + 12) = 0; + + if(sig == DSD_IMAGE_MAGIC_NUMBER) + { + Adapter->bSigCorrupted = TRUE; + if(Adapter->ulFlashWriteSize == BYTE_WRITE_SUPPORT) + { + uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize -1); + BlockStatus = BcmFlashUnProtectBlock(Adapter,uiSectAlignAddr,Adapter->uiSectorSize); + + WriteToFlashWithoutSectorErase(Adapter,(PUINT)(pBuff + 12),eFlash2xSectionVal, + (uiOffset + 12),BYTE_WRITE_SUPPORT); + if(BlockStatus) + { + BcmRestoreBlockProtectStatus(Adapter,BlockStatus); + BlockStatus = 0; + } + } + else + { + WriteToFlashWithoutSectorErase(Adapter,(PUINT)pBuff,eFlash2xSectionVal, + uiOffset ,MAX_RW_SIZE); + } + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BCM Signature is not present in header"); + bcm_kfree(pBuff); + return STATUS_FAILURE; + } + + bcm_kfree(pBuff); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Corrupted the signature"); + return STATUS_SUCCESS ; +} + +INT CorruptISOSig(PMINI_ADAPTER Adapter, FLASH2X_SECTION_VAL eFlash2xSectionVal) +{ + + PUCHAR pBuff = 0 ; + UINT sig = 0; + UINT uiOffset = 0; + + Adapter->bSigCorrupted = FALSE; + + if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence cant Corrupt signature"); + return SECTOR_IS_NOT_WRITABLE; + } + + pBuff = (PUCHAR)kzalloc(MAX_RW_SIZE, GFP_KERNEL); + if(pBuff == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Can't allocate memorey"); + return -ENOMEM ; + } + + uiOffset = 0; + + BcmFlash2xBulkRead(Adapter, (PUINT)pBuff,eFlash2xSectionVal,uiOffset, MAX_RW_SIZE); + + sig = *((PUINT)pBuff); + sig =ntohl(sig); + + //corrupt signature + *pBuff = 0; + + if(sig == ISO_IMAGE_MAGIC_NUMBER) + { + Adapter->bSigCorrupted = TRUE; + WriteToFlashWithoutSectorErase(Adapter,(PUINT)pBuff,eFlash2xSectionVal, + uiOffset ,Adapter->ulFlashWriteSize); + } + else + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"BCM Signature is not present in header"); + bcm_kfree(pBuff); + return STATUS_FAILURE; + } + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,"Corrupted the signature"); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL,pBuff,MAX_RW_SIZE); + + bcm_kfree(pBuff); + return STATUS_SUCCESS ; +} + +BOOLEAN IsNonCDLessDevice(PMINI_ADAPTER Adapter) +{ + if(Adapter->psFlash2xCSInfo->IsCDLessDeviceBootSig == NON_CDLESS_DEVICE_BOOT_SIG) + return TRUE; + else + return FALSE ; +} + diff --git a/drivers/staging/bcm/nvm.h b/drivers/staging/bcm/nvm.h new file mode 100644 index 0000000..6ec6ca8 --- /dev/null +++ b/drivers/staging/bcm/nvm.h @@ -0,0 +1,489 @@ +/*************************************************************************************** +// +// Copyright (c) Beceem Communications Inc. +// +// Module Name: +// NVM.h +// +// Abstract: +// This file has the prototypes,preprocessors and definitions various NVM libraries. +// +// +// Revision History: +// Who When What +// -------- -------- ---------------------------------------------- +// Name Date Created/reviewed/modified +// +// Notes: +// +****************************************************************************************/ + + +#ifndef _NVM_H_ +#define _NVM_H_ + +typedef struct _FLASH_SECTOR_INFO +{ + UINT uiSectorSig; + UINT uiSectorSize; + +}FLASH_SECTOR_INFO,*PFLASH_SECTOR_INFO; + +typedef struct _FLASH_CS_INFO +{ + B_UINT32 MagicNumber; +// let the magic number be 0xBECE-F1A5 - F1A5 for "flas-h" + + B_UINT32 FlashLayoutVersion ; + + // ISO Image/Format/BuildTool versioning + B_UINT32 ISOImageVersion; + + // SCSI/Flash BootLoader versioning + B_UINT32 SCSIFirmwareVersion; + + + B_UINT32 OffsetFromZeroForPart1ISOImage; +// typically 0 + + B_UINT32 OffsetFromZeroForScsiFirmware; +//typically at 12MB + + B_UINT32 SizeOfScsiFirmware ; +//size of the firmware - depends on binary size + + B_UINT32 OffsetFromZeroForPart2ISOImage; +// typically at first Word Aligned offset 12MB + sizeOfScsiFirmware. + + B_UINT32 OffsetFromZeroForCalibrationStart; +// typically at 15MB + + B_UINT32 OffsetFromZeroForCalibrationEnd; + +// VSA0 offsets + B_UINT32 OffsetFromZeroForVSAStart; + B_UINT32 OffsetFromZeroForVSAEnd; + +// Control Section offsets + B_UINT32 OffsetFromZeroForControlSectionStart; + B_UINT32 OffsetFromZeroForControlSectionData; + +// NO Data Activity timeout to switch from MSC to NW Mode + B_UINT32 CDLessInactivityTimeout; + +// New ISO Image Signature + B_UINT32 NewImageSignature; + +// Signature to validate the sector size. + B_UINT32 FlashSectorSizeSig; + +// Sector Size + B_UINT32 FlashSectorSize; + +// Write Size Support + B_UINT32 FlashWriteSupportSize; + +// Total Flash Size + B_UINT32 TotalFlashSize; + +// Flash Base Address for offset specified + B_UINT32 FlashBaseAddr; + +// Flash Part Max Size + B_UINT32 FlashPartMaxSize; + +// Is CDLess or Flash Bootloader + B_UINT32 IsCDLessDeviceBootSig; + +// MSC Timeout after reset to switch from MSC to NW Mode + B_UINT32 MassStorageTimeout; + + +}FLASH_CS_INFO,*PFLASH_CS_INFO; + +#define FLASH2X_TOTAL_SIZE (64*1024*1024) +#define DEFAULT_SECTOR_SIZE (64*1024) + +typedef struct _FLASH_2X_CS_INFO +{ + + // magic number as 0xBECE-F1A5 - F1A5 for "flas-h" + B_UINT32 MagicNumber; + + B_UINT32 FlashLayoutVersion ; + + // ISO Image/Format/BuildTool versioning + B_UINT32 ISOImageVersion; + + // SCSI/Flash BootLoader versioning + B_UINT32 SCSIFirmwareVersion; + + // ISO Image1 Part1/SCSI Firmware/Flash Bootloader Start offset, size + B_UINT32 OffsetFromZeroForPart1ISOImage; + B_UINT32 OffsetFromZeroForScsiFirmware; + B_UINT32 SizeOfScsiFirmware ; + + // ISO Image1 Part2 start offset + B_UINT32 OffsetFromZeroForPart2ISOImage; + + + // DSD0 offset + B_UINT32 OffsetFromZeroForDSDStart; + B_UINT32 OffsetFromZeroForDSDEnd; + + // VSA0 offset + B_UINT32 OffsetFromZeroForVSAStart; + B_UINT32 OffsetFromZeroForVSAEnd; + + // Control Section offset + B_UINT32 OffsetFromZeroForControlSectionStart; + B_UINT32 OffsetFromZeroForControlSectionData; + + // NO Data Activity timeout to switch from MSC to NW Mode + B_UINT32 CDLessInactivityTimeout; + + // New ISO Image Signature + B_UINT32 NewImageSignature; + + B_UINT32 FlashSectorSizeSig; // Sector Size Signature + B_UINT32 FlashSectorSize; // Sector Size + B_UINT32 FlashWriteSupportSize; // Write Size Support + + B_UINT32 TotalFlashSize; // Total Flash Size + + // Flash Base Address for offset specified + B_UINT32 FlashBaseAddr; + B_UINT32 FlashPartMaxSize; // Flash Part Max Size + + // Is CDLess or Flash Bootloader + B_UINT32 IsCDLessDeviceBootSig; + + // MSC Timeout after reset to switch from MSC to NW Mode + B_UINT32 MassStorageTimeout; + + /* Flash Map 2.0 Field */ + B_UINT32 OffsetISOImage1Part1Start; // ISO Image1 Part1 offset + B_UINT32 OffsetISOImage1Part1End; + B_UINT32 OffsetISOImage1Part2Start; // ISO Image1 Part2 offset + B_UINT32 OffsetISOImage1Part2End; + B_UINT32 OffsetISOImage1Part3Start; // ISO Image1 Part3 offset + B_UINT32 OffsetISOImage1Part3End; + + B_UINT32 OffsetISOImage2Part1Start; // ISO Image2 Part1 offset + B_UINT32 OffsetISOImage2Part1End; + B_UINT32 OffsetISOImage2Part2Start; // ISO Image2 Part2 offset + B_UINT32 OffsetISOImage2Part2End; + B_UINT32 OffsetISOImage2Part3Start; // ISO Image2 Part3 offset + B_UINT32 OffsetISOImage2Part3End; + + + // DSD Header offset from start of DSD + B_UINT32 OffsetFromDSDStartForDSDHeader; + B_UINT32 OffsetFromZeroForDSD1Start; // DSD 1 offset + B_UINT32 OffsetFromZeroForDSD1End; + B_UINT32 OffsetFromZeroForDSD2Start; // DSD 2 offset + B_UINT32 OffsetFromZeroForDSD2End; + + B_UINT32 OffsetFromZeroForVSA1Start; // VSA 1 offset + B_UINT32 OffsetFromZeroForVSA1End; + B_UINT32 OffsetFromZeroForVSA2Start; // VSA 2 offset + B_UINT32 OffsetFromZeroForVSA2End; + + /* +* ACCESS_BITS_PER_SECTOR 2 +* ACCESS_RW 0 +* ACCESS_RO 1 +* ACCESS_RESVD 2 +* ACCESS_RESVD 3 +* */ + B_UINT32 SectorAccessBitMap[FLASH2X_TOTAL_SIZE/(DEFAULT_SECTOR_SIZE *16)]; + +// All expansions to the control data structure should add here + +}FLASH2X_CS_INFO,*PFLASH2X_CS_INFO; + +typedef struct _VENDOR_SECTION_INFO +{ + B_UINT32 OffsetFromZeroForSectionStart; + B_UINT32 OffsetFromZeroForSectionEnd; + B_UINT32 AccessFlags; + B_UINT32 Reserved[16]; + +} VENDOR_SECTION_INFO, *PVENDOR_SECTION_INFO; + +typedef struct _FLASH2X_VENDORSPECIFIC_INFO +{ + VENDOR_SECTION_INFO VendorSection[TOTAL_SECTIONS]; + B_UINT32 Reserved[16]; + +} FLASH2X_VENDORSPECIFIC_INFO, *PFLASH2X_VENDORSPECIFIC_INFO; + +typedef struct _DSD_HEADER +{ + B_UINT32 DSDImageSize; + B_UINT32 DSDImageCRC; + B_UINT32 DSDImagePriority; + //We should not consider right now. Reading reserve is worthless. + B_UINT32 Reserved[252]; // Resvd for DSD Header + B_UINT32 DSDImageMagicNumber; + +}DSD_HEADER, *PDSD_HEADER; + +typedef struct _ISO_HEADER +{ + B_UINT32 ISOImageMagicNumber; + B_UINT32 ISOImageSize; + B_UINT32 ISOImageCRC; + B_UINT32 ISOImagePriority; + //We should not consider right now. Reading reserve is worthless. + B_UINT32 Reserved[60]; //Resvd for ISO Header extension + +}ISO_HEADER, *PISO_HEADER; + +#define EEPROM_BEGIN_CIS (0) +#define EEPROM_BEGIN_NON_CIS (0x200) +#define EEPROM_END (0x2000) + +#define INIT_PARAMS_SIGNATURE (0x95a7a597) + +#define MAX_INIT_PARAMS_LENGTH (2048) + + +#define MAC_ADDRESS_OFFSET 0x200 + + +#define INIT_PARAMS_1_SIGNATURE_ADDRESS EEPROM_BEGIN_NON_CIS +#define INIT_PARAMS_1_DATA_ADDRESS (INIT_PARAMS_1_SIGNATURE_ADDRESS+16) +#define INIT_PARAMS_1_MACADDRESS_ADDRESS (MAC_ADDRESS_OFFSET) +#define INIT_PARAMS_1_LENGTH_ADDRESS (INIT_PARAMS_1_SIGNATURE_ADDRESS+4) + +#define INIT_PARAMS_2_SIGNATURE_ADDRESS (EEPROM_BEGIN_NON_CIS+2048+16) +#define INIT_PARAMS_2_DATA_ADDRESS (INIT_PARAMS_2_SIGNATURE_ADDRESS+16) +#define INIT_PARAMS_2_MACADDRESS_ADDRESS (INIT_PARAMS_2_SIGNATURE_ADDRESS+8) +#define INIT_PARAMS_2_LENGTH_ADDRESS (INIT_PARAMS_2_SIGNATURE_ADDRESS+4) + +#define EEPROM_SPI_DEV_CONFIG_REG 0x0F003000 +#define EEPROM_SPI_Q_STATUS1_REG 0x0F003004 +#define EEPROM_SPI_Q_STATUS1_MASK_REG 0x0F00300C + +#define EEPROM_SPI_Q_STATUS_REG 0x0F003008 +#define EEPROM_CMDQ_SPI_REG 0x0F003018 +#define EEPROM_WRITE_DATAQ_REG 0x0F00301C +#define EEPROM_READ_DATAQ_REG 0x0F003020 +#define SPI_FLUSH_REG 0x0F00304C + +#define EEPROM_WRITE_ENABLE 0x06000000 +#define EEPROM_READ_STATUS_REGISTER 0x05000000 +#define EEPROM_16_BYTE_PAGE_WRITE 0xFA000000 +#define EEPROM_WRITE_QUEUE_EMPTY 0x00001000 +#define EEPROM_WRITE_QUEUE_AVAIL 0x00002000 +#define EEPROM_WRITE_QUEUE_FULL 0x00004000 +#define EEPROM_16_BYTE_PAGE_READ 0xFB000000 +#define EEPROM_4_BYTE_PAGE_READ 0x3B000000 + +#define EEPROM_CMD_QUEUE_FLUSH 0x00000001 +#define EEPROM_WRITE_QUEUE_FLUSH 0x00000002 +#define EEPROM_READ_QUEUE_FLUSH 0x00000004 +#define EEPROM_ETH_QUEUE_FLUSH 0x00000008 +#define EEPROM_ALL_QUEUE_FLUSH 0x0000000f +#define EEPROM_READ_ENABLE 0x06000000 +#define EEPROM_16_BYTE_PAGE_WRITE 0xFA000000 +#define EEPROM_READ_DATA_FULL 0x00000010 +#define EEPROM_READ_DATA_AVAIL 0x00000020 +#define EEPROM_READ_QUEUE_EMPTY 0x00000002 +#define EEPROM_CMD_QUEUE_EMPTY 0x00000100 +#define EEPROM_CMD_QUEUE_AVAIL 0x00000200 +#define EEPROM_CMD_QUEUE_FULL 0x00000400 + +/* Most EEPROM status register bit 0 indicates if the EEPROM is busy + * with a write if set 1. See the details of the EEPROM Status Register + * in the EEPROM data sheet. */ +#define EEPROM_STATUS_REG_WRITE_BUSY 0x00000001 + +// We will have 1 mSec for every RETRIES_PER_DELAY count and have a max attempts of MAX_EEPROM_RETRIES +// This will give us 80 mSec minimum of delay = 80mSecs +#define MAX_EEPROM_RETRIES 80 +#define RETRIES_PER_DELAY 64 + + +#define MAX_RW_SIZE 0x10 +#define MAX_READ_SIZE 0x10 +#define MAX_SECTOR_SIZE (512*1024) +#define MIN_SECTOR_SIZE (1024) +#define FLASH_SECTOR_SIZE_OFFSET 0xEFFFC +#define FLASH_SECTOR_SIZE_SIG_OFFSET 0xEFFF8 +#define FLASH_SECTOR_SIZE_SIG 0xCAFEBABE +#define FLASH_CS_INFO_START_ADDR 0xFF0000 +#define FLASH_CONTROL_STRUCT_SIGNATURE 0xBECEF1A5 +#define SCSI_FIRMWARE_MAJOR_VERSION 0x1 +#define SCSI_FIRMWARE_MINOR_VERSION 0x5 +#define BYTE_WRITE_SUPPORT 0x1 + +#define FLASH_AUTO_INIT_BASE_ADDR 0xF00000 + + + +#ifdef BCM_SHM_INTERFACE + +#define FLASH_ADDR_MASK 0x1F000000 +extern int bcmflash_raw_read(unsigned int flash_id, unsigned int offset, unsigned char *inbuf, unsigned int len); +extern int bcmflash_raw_write(unsigned int flash_id, unsigned int offset, unsigned char *outbuf, unsigned int len); +extern int bcmflash_raw_writenoerase(unsigned int flash_id, unsigned int offset, unsigned char *outbuf, unsigned int len); + + +#endif + +#define FLASH_CONTIGIOUS_START_ADDR_AFTER_INIT 0x1C000000 +#define FLASH_CONTIGIOUS_START_ADDR_BEFORE_INIT 0x1F000000 + +#define FLASH_CONTIGIOUS_START_ADDR_BCS350 0x08000000 +#define FLASH_CONTIGIOUS_END_ADDR_BCS350 0x08FFFFFF + + + +#define FLASH_SIZE_ADDR 0xFFFFEC + +#define FLASH_SPI_CMDQ_REG 0xAF003040 +#define FLASH_SPI_WRITEQ_REG 0xAF003044 +#define FLASH_SPI_READQ_REG 0xAF003048 +#define FLASH_CONFIG_REG 0xAF003050 +#define FLASH_GPIO_CONFIG_REG 0xAF000030 + +#define FLASH_CMD_WRITE_ENABLE 0x06 +#define FLASH_CMD_READ_ENABLE 0x03 +#define FLASH_CMD_RESET_WRITE_ENABLE 0x04 +#define FLASH_CMD_STATUS_REG_READ 0x05 +#define FLASH_CMD_STATUS_REG_WRITE 0x01 +#define FLASH_CMD_READ_ID 0x9F + +#define PAD_SELECT_REGISTER 0xAF000410 + +#define FLASH_PART_SST25VF080B 0xBF258E + +#define EEPROM_CAL_DATA_INTERNAL_LOC 0xbFB00008 + +#define EEPROM_CALPARAM_START 0x200 +#define EEPROM_SIZE_OFFSET 524 + +//As Read/Write time vaires from 1.5 to 3.0 ms. +//so After Ignoring the rdm/wrm time(that is dependent on many factor like interface etc.), +//here time calculated meets the worst case delay, 3.0 ms +#define MAX_FLASH_RETRIES 4 +#define FLASH_PER_RETRIES_DELAY 16 + + +#define EEPROM_MAX_CAL_AREA_SIZE 0xF0000 + + + +#define BECM ntohl(0x4245434d) + +#define FLASH_2X_MAJOR_NUMBER 0x2 +#define DSD_IMAGE_MAGIC_NUMBER 0xBECE0D5D +#define ISO_IMAGE_MAGIC_NUMBER 0xBECE0150 +#define NON_CDLESS_DEVICE_BOOT_SIG 0xBECEB007 +#define MINOR_VERSION(x) ((x >>16) & 0xFFFF) +#define MAJOR_VERSION(x) (x & 0xFFFF) +#define CORRUPTED_PATTERN 0x0 +#define UNINIT_PTR_IN_CS 0xBBBBDDDD + +#define VENDOR_PTR_IN_CS 0xAAAACCCC + + +#define FLASH2X_SECTION_PRESENT 1<<0 +#define FLASH2X_SECTION_VALID 1<<1 +#define FLASH2X_SECTION_RO 1<<2 +#define FLASH2X_SECTION_ACT 1<<3 +#define SECTOR_IS_NOT_WRITABLE STATUS_FAILURE +#define INVALID_OFFSET STATUS_FAILURE +#define INVALID_SECTION STATUS_FAILURE +#define SECTOR_1K 1024 +#define SECTOR_64K (64 *SECTOR_1K) +#define SECTOR_128K (2 * SECTOR_64K) +#define SECTOR_256k (2 * SECTOR_128K) +#define SECTOR_512K (2 * SECTOR_256k) +#define FLASH_PART_SIZE (16 * 1024 * 1024) +#define RESET_CHIP_SELECT -1 +#define CHIP_SELECT_BIT12 12 + +#define SECTOR_READWRITE_PERMISSION 0 +#define SECTOR_READONLY 1 +#define SIGNATURE_SIZE 4 +#define DEFAULT_BUFF_SIZE 0x10000 + + +#define FIELD_OFFSET_IN_HEADER(HeaderPointer,Field) ((PUCHAR)&((HeaderPointer)(NULL))->Field - (PUCHAR)(NULL)) + +#if 0 +INT BeceemEEPROMBulkRead( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes); + + +INT BeceemFlashBulkRead( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes); + +UINT BcmGetEEPROMSize(PMINI_ADAPTER Adapter); + +UINT BcmGetFlashSize(PMINI_ADAPTER Adapter); + +UINT BcmGetFlashSectorSize(PMINI_ADAPTER Adapter); + + + +INT BeceemFlashBulkWrite( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify); + +INT PropagateCalParamsFromFlashToMemory(PMINI_ADAPTER Adapter); + +INT PropagateCalParamsFromEEPROMToMemory(PMINI_ADAPTER Adapter); + + +INT BeceemEEPROMBulkWrite( + PMINI_ADAPTER Adapter, + PUCHAR pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify); + + +INT ReadBeceemEEPROM(PMINI_ADAPTER Adapter,UINT dwAddress, UINT *pdwData); + +NVM_TYPE BcmGetNvmType(PMINI_ADAPTER Adapter); + +INT BeceemNVMRead( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes); + +INT BeceemNVMWrite( + PMINI_ADAPTER Adapter, + PUINT pBuffer, + UINT uiOffset, + UINT uiNumBytes, + BOOLEAN bVerify); + +INT ReadMacAddressFromEEPROM(PMINI_ADAPTER Adapter); + +INT BcmUpdateSectorSize(PMINI_ADAPTER Adapter,UINT uiSectorSize); + +INT BcmInitNVM(PMINI_ADAPTER Adapter); + +VOID BcmValidateNvmType(PMINI_ADAPTER Adapter); + +VOID BcmGetFlashCSInfo(PMINI_ADAPTER Adapter); + +#endif + +#endif + diff --git a/drivers/staging/bcm/osal_misc.h b/drivers/staging/bcm/osal_misc.h new file mode 100644 index 0000000..ff4adde --- /dev/null +++ b/drivers/staging/bcm/osal_misc.h @@ -0,0 +1,49 @@ + /*++ + + Copyright (c) Beceem Communications Inc. + + Module Name: + OSAL_Misc.h + + Abstract: + Provides the OS Abstracted macros to access: + Linked Lists + Dispatcher Objects(Events,Semaphores,Spin Locks and the like) + Files + + + Revision History: + Who When What + -------- -------- ---------------------------------------------- + Name Date Created/reviewed/modified + Rajeev 24/1/08 Created + Notes: + + --*/ +#ifndef _OSAL_MISC_H_ +#define _OSAL_MISC_H_ +//OSAL Macros +//OSAL Primitives +typedef PUCHAR POSAL_NW_PACKET ; //Nw packets + + +#define OsalMemAlloc(n,t) kmalloc(n,GFP_KERNEL) + +#define OsalMemFree(x,n) bcm_kfree(x) + +#define OsalMemMove(dest, src, len) \ +{ \ + memcpy(dest,src, len); \ +} + +#define OsalZeroMemory(pDest, Len) \ +{ \ + memset(pDest,0,Len); \ +} + +//#define OsalMemSet(pSrc,Char,Len) memset(pSrc,Char,Len) + +bool OsalMemCompare(void *dest, void *src, UINT len); + +#endif + diff --git a/drivers/staging/bcm/sort.c b/drivers/staging/bcm/sort.c new file mode 100644 index 0000000..fc5d07a --- /dev/null +++ b/drivers/staging/bcm/sort.c @@ -0,0 +1,63 @@ +#include "headers.h" + +/* + * File Name: sort.c + * + * Author: Beceem Communications Pvt. Ltd + * + * Abstract: This file contains the routines sorting the classification rules. + * + * Copyright (c) 2007 Beceem Communications Pvt. Ltd + */ + +VOID SortPackInfo(PMINI_ADAPTER Adapter) +{ + UINT nIndex1; + UINT nIndex2; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<======="); + + for(nIndex1 = 0; nIndex1 < NO_OF_QUEUES -2 ; nIndex1++) + { + for(nIndex2 = nIndex1 + 1 ; nIndex2 < NO_OF_QUEUES -1 ; nIndex2++) + { + if(Adapter->PackInfo[nIndex1].bValid && Adapter->PackInfo[nIndex2].bValid) + { + if(Adapter->PackInfo[nIndex2].u8TrafficPriority < + Adapter->PackInfo[nIndex1].u8TrafficPriority) + { + PacketInfo stTemppackInfo = Adapter->PackInfo[nIndex2]; + Adapter->PackInfo[nIndex2] = Adapter->PackInfo[nIndex1]; + Adapter->PackInfo[nIndex1] = stTemppackInfo; + + } + } + } + } +} + +VOID SortClassifiers(PMINI_ADAPTER Adapter) +{ + UINT nIndex1; + UINT nIndex2; + + BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "<======="); + + for(nIndex1 = 0; nIndex1 < MAX_CLASSIFIERS -1 ; nIndex1++) + { + for(nIndex2 = nIndex1 + 1 ; nIndex2 < MAX_CLASSIFIERS ; nIndex2++) + { + if(Adapter->astClassifierTable[nIndex1].bUsed && Adapter->astClassifierTable[nIndex2].bUsed) + { + if(Adapter->astClassifierTable[nIndex2].u8ClassifierRulePriority < + Adapter->astClassifierTable[nIndex1].u8ClassifierRulePriority) + { + S_CLASSIFIER_RULE stTempClassifierRule = Adapter->astClassifierTable[nIndex2]; + Adapter->astClassifierTable[nIndex2] = Adapter->astClassifierTable[nIndex1]; + Adapter->astClassifierTable[nIndex1] = stTempClassifierRule; + + } + } + } + } +} diff --git a/drivers/staging/bcm/target_params.h b/drivers/staging/bcm/target_params.h new file mode 100644 index 0000000..2d8b8a3 --- /dev/null +++ b/drivers/staging/bcm/target_params.h @@ -0,0 +1,81 @@ +#ifndef TARGET_PARAMS_H +#define TARGET_PARAMS_H + +typedef struct _TARGET_PARAMS +{ + B_UINT32 m_u32CfgVersion; + + // Scanning Related Params + B_UINT32 m_u32CenterFrequency; + B_UINT32 m_u32BandAScan; + B_UINT32 m_u32BandBScan; + B_UINT32 m_u32BandCScan; + + + // QoS Params + B_UINT32 m_u32ErtpsOptions; + + B_UINT32 m_u32PHSEnable; + + + // HO Params + B_UINT32 m_u32HoEnable; + + B_UINT32 m_u32HoReserved1; + B_UINT32 m_u32HoReserved2; + // Power Control Params + + B_UINT32 m_u32MimoEnable; + + B_UINT32 m_u32SecurityEnable; + + B_UINT32 m_u32PowerSavingModesEnable; //bit 1: 1 Idlemode enable; bit2: 1 Sleepmode Enable + /* PowerSaving Mode Options: + bit 0 = 1: CPE mode - to keep pcmcia if alive; + bit 1 = 1: CINR reporing in Idlemode Msg + bit 2 = 1: Default PSC Enable in sleepmode*/ + B_UINT32 m_u32PowerSavingModeOptions; + + B_UINT32 m_u32ArqEnable; + + // From Version #3, the HARQ section renamed as general + B_UINT32 m_u32HarqEnable; + // EEPROM Param Location + B_UINT32 m_u32EEPROMFlag; + // BINARY TYPE - 4th MSByte: Interface Type - 3rd MSByte: Vendor Type - 2nd MSByte + // Unused - LSByte + B_UINT32 m_u32Customize; + B_UINT32 m_u32ConfigBW; /* In Hz */ + B_UINT32 m_u32ShutDownInitThresholdTimer; + + B_UINT32 m_u32RadioParameter; + B_UINT32 m_u32PhyParameter1; + B_UINT32 m_u32PhyParameter2; + B_UINT32 m_u32PhyParameter3; + + B_UINT32 m_u32TestOptions; // in eval mode only; lower 16bits = basic cid for testing; then bit 16 is test cqich,bit 17 test init rang; bit 18 test periodic rang and bit 19 is test harq ack/nack + + B_UINT32 m_u32MaxMACDataperDLFrame; + B_UINT32 m_u32MaxMACDataperULFrame; + + B_UINT32 m_u32Corr2MacFlags; + + //adding driver params. + B_UINT32 HostDrvrConfig1; + B_UINT32 HostDrvrConfig2; + B_UINT32 HostDrvrConfig3; + B_UINT32 HostDrvrConfig4; + B_UINT32 HostDrvrConfig5; + B_UINT32 HostDrvrConfig6; + B_UINT32 m_u32SegmentedPUSCenable; + + // removed SHUT down related 'unused' params from here to sync 4.x and 5.x CFG files.. + + //BAMC Related Parameters + //Bit 0-15 Band AMC signaling configuration: Bit 1 = 1 – Enable Band AMC signaling. + //bit 16-31 Band AMC Data configuration: Bit 16 = 1 – Band AMC 2x3 support. + B_UINT32 m_u32BandAMCEnable; + +} stTargetParams,TARGET_PARAMS,*PTARGET_PARAMS, STARGETPARAMS, *PSTARGETPARAMS; + +#endif diff --git a/drivers/staging/bcm/vendorspecificextn.c b/drivers/staging/bcm/vendorspecificextn.c new file mode 100644 index 0000000..4178cd1 --- /dev/null +++ b/drivers/staging/bcm/vendorspecificextn.c @@ -0,0 +1,146 @@ +#include "headers.h" +//----------------------------------------------------------------------------- +// Procedure: vendorextnGetSectionInfo +// +// Description: Finds the type of NVM used. +// +// Arguments: +// Adapter - ptr to Adapter object instance +// pNVMType - ptr to NVM type. +// Returns: +// STATUS_SUCCESS/STATUS_FAILURE +// +//----------------------------------------------------------------------------- +INT vendorextnGetSectionInfo(PVOID pContext,PFLASH2X_VENDORSPECIFIC_INFO pVendorInfo) +{ + return STATUS_FAILURE; +} + +//----------------------------------------------------------------------------- +// Procedure: vendorextnInit +// +// Description: Initializing the vendor extension NVM interface +// +// Arguments: +// Adapter - Pointer to MINI Adapter Structure. + +// Returns: +// STATUS_SUCCESS/STATUS_FAILURE +// +//----------------------------------------------------------------------------- +INT vendorextnInit(PMINI_ADAPTER Adapter) +{ + return STATUS_SUCCESS; +} + +//----------------------------------------------------------------------------- +// Procedure: vendorextnExit +// +// Description: Free the resource associated with vendor extension NVM interface +// +// Arguments: +// Adapter - Pointer to MINI Adapter Structure. + +// Returns: +// STATUS_SUCCESS/STATUS_FAILURE +// +//----------------------------------------------------------------------------- +INT vendorextnExit(PMINI_ADAPTER Adapter) +{ + return STATUS_SUCCESS; +} + +//------------------------------------------------------------------------ +// Procedure: vendorextnIoctl +// +// Description: execute the vendor extension specific ioctl +// +//Arguments: +// Adapter -Beceem private Adapter Structure +// cmd -vendor extension specific Ioctl commad +// arg -input parameter sent by vendor +// +// Returns: +// CONTINUE_COMMON_PATH in case it is not meant to be processed by vendor ioctls +// STATUS_SUCCESS/STATUS_FAILURE as per the IOCTL return value +// +//-------------------------------------------------------------------------- +INT vendorextnIoctl(PMINI_ADAPTER Adapter, UINT cmd, ULONG arg) +{ + return CONTINUE_COMMON_PATH; +} + + + +//------------------------------------------------------------------ +// Procedure: vendorextnReadSection +// +// Description: Reads from a section of NVM +// +// Arguments: +// pContext - ptr to Adapter object instance +// pBuffer - Read the data from Vendor Area to this buffer +// SectionVal - Value of type of Section +// Offset - Read from the Offset of the Vendor Section. +// numOfBytes - Read numOfBytes from the Vendor section to Buffer +// +// Returns: +// STATUS_SUCCESS/STATUS_FAILURE +// +//------------------------------------------------------------------ + +INT vendorextnReadSection(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, + UINT offset, UINT numOfBytes) +{ + return STATUS_FAILURE; +} + + + +//------------------------------------------------------------------ +// Procedure: vendorextnWriteSection +// +// Description: Write to a Section of NVM +// +// Arguments: +// pContext - ptr to Adapter object instance +// pBuffer - Write the data provided in the buffer +// SectionVal - Value of type of Section +// Offset - Writes to the Offset of the Vendor Section. +// numOfBytes - Write num Bytes after reading from pBuffer. +// bVerify - the Buffer Written should be verified. +// +// Returns: +// STATUS_SUCCESS/STATUS_FAILURE +// +//------------------------------------------------------------------ +INT vendorextnWriteSection(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, + UINT offset, UINT numOfBytes, BOOLEAN bVerify) +{ + return STATUS_FAILURE; +} + + + +//------------------------------------------------------------------ +// Procedure: vendorextnWriteSectionWithoutErase +// +// Description: Write to a Section of NVM without erasing the sector +// +// Arguments: +// pContext - ptr to Adapter object instance +// pBuffer - Write the data provided in the buffer +// SectionVal - Value of type of Section +// Offset - Writes to the Offset of the Vendor Section. +// numOfBytes - Write num Bytes after reading from pBuffer. +// +// Returns: +// STATUS_SUCCESS/STATUS_FAILURE +// +//------------------------------------------------------------------ +INT vendorextnWriteSectionWithoutErase(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, + UINT offset, UINT numOfBytes) +{ + return STATUS_FAILURE; +} + diff --git a/drivers/staging/bcm/vendorspecificextn.h b/drivers/staging/bcm/vendorspecificextn.h new file mode 100644 index 0000000..7ff1495 --- /dev/null +++ b/drivers/staging/bcm/vendorspecificextn.h @@ -0,0 +1,18 @@ + +#ifndef __VENDOR_EXTN_NVM_H__ +#define __VENDOR_EXTN_NVM_H__ + +#define CONTINUE_COMMON_PATH 0xFFFF + +INT vendorextnGetSectionInfo(PVOID pContext,PFLASH2X_VENDORSPECIFIC_INFO pVendorInfo); +INT vendorextnExit(PMINI_ADAPTER Adapter); +INT vendorextnInit(PMINI_ADAPTER Adapter); +INT vendorextnIoctl(PMINI_ADAPTER Adapter, UINT cmd, ULONG arg); +INT vendorextnReadSection(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, + UINT offset, UINT numOfBytes); +INT vendorextnWriteSection(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, + UINT offset, UINT numOfBytes, BOOLEAN bVerify); +INT vendorextnWriteSectionWithoutErase(PVOID pContext, PUCHAR pBuffer, FLASH2X_SECTION_VAL SectionVal, + UINT offset, UINT numOfBytes); + +#endif /* */