linux/drivers/staging/rt3090/rt_linux.c
<<
>>
Prefs
   1/*
   2 *************************************************************************
   3 * Ralink Tech Inc.
   4 * 5F., No.36, Taiyuan St., Jhubei City,
   5 * Hsinchu County 302,
   6 * Taiwan, R.O.C.
   7 *
   8 * (c) Copyright 2002-2007, Ralink Technology, Inc.
   9 *
  10 * This program is free software; you can redistribute it and/or modify  *
  11 * it under the terms of the GNU General Public License as published by  *
  12 * the Free Software Foundation; either version 2 of the License, or     *
  13 * (at your option) any later version.                                   *
  14 *                                                                       *
  15 * This program is distributed in the hope that it will be useful,       *
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
  18 * GNU General Public License for more details.                          *
  19 *                                                                       *
  20 * You should have received a copy of the GNU General Public License     *
  21 * along with this program; if not, write to the                         *
  22 * Free Software Foundation, Inc.,                                       *
  23 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  24 *                                                                       *
  25 *************************************************************************
  26 */
  27
  28#include <linux/sched.h>
  29#include "rt_config.h"
  30
  31ULONG   RTDebugLevel = RT_DEBUG_ERROR;
  32
  33
  34// for wireless system event message
  35char const *pWirelessSysEventText[IW_SYS_EVENT_TYPE_NUM] = {
  36        // system status event
  37    "had associated successfully",                                                      /* IW_ASSOC_EVENT_FLAG */
  38    "had disassociated",                                                                        /* IW_DISASSOC_EVENT_FLAG */
  39    "had deauthenticated",                                                                      /* IW_DEAUTH_EVENT_FLAG */
  40    "had been aged-out and disassociated",                                      /* IW_AGEOUT_EVENT_FLAG */
  41    "occurred CounterMeasures attack",                                          /* IW_COUNTER_MEASURES_EVENT_FLAG */
  42    "occurred replay counter different in Key Handshaking",     /* IW_REPLAY_COUNTER_DIFF_EVENT_FLAG */
  43    "occurred RSNIE different in Key Handshaking",                      /* IW_RSNIE_DIFF_EVENT_FLAG */
  44    "occurred MIC different in Key Handshaking",                        /* IW_MIC_DIFF_EVENT_FLAG */
  45    "occurred ICV error in RX",                                                         /* IW_ICV_ERROR_EVENT_FLAG */
  46    "occurred MIC error in RX",                                                         /* IW_MIC_ERROR_EVENT_FLAG */
  47        "Group Key Handshaking timeout",                                                /* IW_GROUP_HS_TIMEOUT_EVENT_FLAG */
  48        "Pairwise Key Handshaking timeout",                                             /* IW_PAIRWISE_HS_TIMEOUT_EVENT_FLAG */
  49        "RSN IE sanity check failure",                                                  /* IW_RSNIE_SANITY_FAIL_EVENT_FLAG */
  50        "set key done in WPA/WPAPSK",                                                   /* IW_SET_KEY_DONE_WPA1_EVENT_FLAG */
  51        "set key done in WPA2/WPA2PSK",                         /* IW_SET_KEY_DONE_WPA2_EVENT_FLAG */
  52        "connects with our wireless client",                    /* IW_STA_LINKUP_EVENT_FLAG */
  53        "disconnects with our wireless client",                 /* IW_STA_LINKDOWN_EVENT_FLAG */
  54        "scan completed"                                                                                /* IW_SCAN_COMPLETED_EVENT_FLAG */
  55        "scan terminate!! Busy!! Enqueue fail!!"                                /* IW_SCAN_ENQUEUE_FAIL_EVENT_FLAG */
  56        };
  57
  58// for wireless IDS_spoof_attack event message
  59char const *pWirelessSpoofEventText[IW_SPOOF_EVENT_TYPE_NUM] = {
  60    "detected conflict SSID",                                                           /* IW_CONFLICT_SSID_EVENT_FLAG */
  61    "detected spoofed association response",                            /* IW_SPOOF_ASSOC_RESP_EVENT_FLAG */
  62    "detected spoofed reassociation responses",                         /* IW_SPOOF_REASSOC_RESP_EVENT_FLAG */
  63    "detected spoofed probe response",                                          /* IW_SPOOF_PROBE_RESP_EVENT_FLAG */
  64    "detected spoofed beacon",                                                          /* IW_SPOOF_BEACON_EVENT_FLAG */
  65    "detected spoofed disassociation",                                          /* IW_SPOOF_DISASSOC_EVENT_FLAG */
  66    "detected spoofed authentication",                                          /* IW_SPOOF_AUTH_EVENT_FLAG */
  67    "detected spoofed deauthentication",                                        /* IW_SPOOF_DEAUTH_EVENT_FLAG */
  68    "detected spoofed unknown management frame",                        /* IW_SPOOF_UNKNOWN_MGMT_EVENT_FLAG */
  69        "detected replay attack"                                                                /* IW_REPLAY_ATTACK_EVENT_FLAG */
  70        };
  71
  72// for wireless IDS_flooding_attack event message
  73char const *pWirelessFloodEventText[IW_FLOOD_EVENT_TYPE_NUM] = {
  74        "detected authentication flooding",                                             /* IW_FLOOD_AUTH_EVENT_FLAG */
  75    "detected association request flooding",                            /* IW_FLOOD_ASSOC_REQ_EVENT_FLAG */
  76    "detected reassociation request flooding",                          /* IW_FLOOD_REASSOC_REQ_EVENT_FLAG */
  77    "detected probe request flooding",                                          /* IW_FLOOD_PROBE_REQ_EVENT_FLAG */
  78    "detected disassociation flooding",                                         /* IW_FLOOD_DISASSOC_EVENT_FLAG */
  79    "detected deauthentication flooding",                                       /* IW_FLOOD_DEAUTH_EVENT_FLAG */
  80    "detected 802.1x eap-request flooding"                                      /* IW_FLOOD_EAP_REQ_EVENT_FLAG */
  81        };
  82
  83
  84/* timeout -- ms */
  85VOID RTMP_SetPeriodicTimer(
  86        IN      NDIS_MINIPORT_TIMER *pTimer,
  87        IN      unsigned long timeout)
  88{
  89        timeout = ((timeout*OS_HZ) / 1000);
  90        pTimer->expires = jiffies + timeout;
  91        add_timer(pTimer);
  92}
  93
  94/* convert NdisMInitializeTimer --> RTMP_OS_Init_Timer */
  95VOID RTMP_OS_Init_Timer(
  96        IN      PRTMP_ADAPTER pAd,
  97        IN      NDIS_MINIPORT_TIMER *pTimer,
  98        IN      TIMER_FUNCTION function,
  99        IN      PVOID data)
 100{
 101        init_timer(pTimer);
 102    pTimer->data = (unsigned long)data;
 103    pTimer->function = function;
 104}
 105
 106
 107VOID RTMP_OS_Add_Timer(
 108        IN      NDIS_MINIPORT_TIMER             *pTimer,
 109        IN      unsigned long timeout)
 110{
 111        if (timer_pending(pTimer))
 112                return;
 113
 114        timeout = ((timeout*OS_HZ) / 1000);
 115        pTimer->expires = jiffies + timeout;
 116        add_timer(pTimer);
 117}
 118
 119VOID RTMP_OS_Mod_Timer(
 120        IN      NDIS_MINIPORT_TIMER             *pTimer,
 121        IN      unsigned long timeout)
 122{
 123        timeout = ((timeout*OS_HZ) / 1000);
 124        mod_timer(pTimer, jiffies + timeout);
 125}
 126
 127VOID RTMP_OS_Del_Timer(
 128        IN      NDIS_MINIPORT_TIMER             *pTimer,
 129        OUT     BOOLEAN                                 *pCancelled)
 130{
 131        if (timer_pending(pTimer))
 132        {
 133                *pCancelled = del_timer_sync(pTimer);
 134        }
 135        else
 136        {
 137                *pCancelled = TRUE;
 138        }
 139
 140}
 141
 142VOID RTMP_OS_Release_Packet(
 143        IN      PRTMP_ADAPTER pAd,
 144        IN      PQUEUE_ENTRY  pEntry)
 145{
 146        //RTMPFreeNdisPacket(pAd, (struct sk_buff *)pEntry);
 147}
 148
 149// Unify all delay routine by using udelay
 150VOID RTMPusecDelay(
 151        IN      ULONG   usec)
 152{
 153        ULONG   i;
 154
 155        for (i = 0; i < (usec / 50); i++)
 156                udelay(50);
 157
 158        if (usec % 50)
 159                udelay(usec % 50);
 160}
 161
 162void RTMP_GetCurrentSystemTime(LARGE_INTEGER *time)
 163{
 164        time->u.LowPart = jiffies;
 165}
 166
 167// pAd MUST allow to be NULL
 168NDIS_STATUS os_alloc_mem(
 169        IN      RTMP_ADAPTER *pAd,
 170        OUT     UCHAR **mem,
 171        IN      ULONG  size)
 172{
 173        *mem = (PUCHAR) kmalloc(size, GFP_ATOMIC);
 174        if (*mem)
 175                return (NDIS_STATUS_SUCCESS);
 176        else
 177                return (NDIS_STATUS_FAILURE);
 178}
 179
 180// pAd MUST allow to be NULL
 181NDIS_STATUS os_free_mem(
 182        IN      PRTMP_ADAPTER pAd,
 183        IN      PVOID mem)
 184{
 185
 186        ASSERT(mem);
 187        kfree(mem);
 188        return (NDIS_STATUS_SUCCESS);
 189}
 190
 191
 192
 193
 194PNDIS_PACKET RtmpOSNetPktAlloc(
 195        IN RTMP_ADAPTER *pAd,
 196        IN int size)
 197{
 198        struct sk_buff *skb;
 199        /* Add 2 more bytes for ip header alignment*/
 200        skb = dev_alloc_skb(size+2);
 201
 202        return ((PNDIS_PACKET)skb);
 203}
 204
 205
 206PNDIS_PACKET RTMP_AllocateFragPacketBuffer(
 207        IN      PRTMP_ADAPTER pAd,
 208        IN      ULONG   Length)
 209{
 210        struct sk_buff *pkt;
 211
 212        pkt = dev_alloc_skb(Length);
 213
 214        if (pkt == NULL)
 215        {
 216                DBGPRINT(RT_DEBUG_ERROR, ("can't allocate frag rx %ld size packet\n",Length));
 217        }
 218
 219        if (pkt)
 220        {
 221                RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
 222        }
 223
 224        return (PNDIS_PACKET) pkt;
 225}
 226
 227
 228PNDIS_PACKET RTMP_AllocateTxPacketBuffer(
 229        IN      PRTMP_ADAPTER pAd,
 230        IN      ULONG   Length,
 231        IN      BOOLEAN Cached,
 232        OUT     PVOID   *VirtualAddress)
 233{
 234        struct sk_buff *pkt;
 235
 236        pkt = dev_alloc_skb(Length);
 237
 238        if (pkt == NULL)
 239        {
 240                DBGPRINT(RT_DEBUG_ERROR, ("can't allocate tx %ld size packet\n",Length));
 241        }
 242
 243        if (pkt)
 244        {
 245                RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
 246                *VirtualAddress = (PVOID) pkt->data;
 247        }
 248        else
 249        {
 250                *VirtualAddress = (PVOID) NULL;
 251        }
 252
 253        return (PNDIS_PACKET) pkt;
 254}
 255
 256
 257VOID build_tx_packet(
 258        IN      PRTMP_ADAPTER   pAd,
 259        IN      PNDIS_PACKET    pPacket,
 260        IN      PUCHAR  pFrame,
 261        IN      ULONG   FrameLen)
 262{
 263
 264        struct sk_buff  *pTxPkt;
 265
 266        ASSERT(pPacket);
 267        pTxPkt = RTPKT_TO_OSPKT(pPacket);
 268
 269        NdisMoveMemory(skb_put(pTxPkt, FrameLen), pFrame, FrameLen);
 270}
 271
 272VOID    RTMPFreeAdapter(
 273        IN      PRTMP_ADAPTER   pAd)
 274{
 275        POS_COOKIE os_cookie;
 276        int index;
 277
 278        os_cookie=(POS_COOKIE)pAd->OS_Cookie;
 279
 280        if (pAd->BeaconBuf)
 281                kfree(pAd->BeaconBuf);
 282
 283
 284        NdisFreeSpinLock(&pAd->MgmtRingLock);
 285
 286#ifdef RTMP_MAC_PCI
 287        NdisFreeSpinLock(&pAd->RxRingLock);
 288#ifdef RT3090
 289NdisFreeSpinLock(&pAd->McuCmdLock);
 290#endif // RT3090 //
 291#endif // RTMP_MAC_PCI //
 292
 293        for (index =0 ; index < NUM_OF_TX_RING; index++)
 294        {
 295                NdisFreeSpinLock(&pAd->TxSwQueueLock[index]);
 296                NdisFreeSpinLock(&pAd->DeQueueLock[index]);
 297                pAd->DeQueueRunning[index] = FALSE;
 298        }
 299
 300        NdisFreeSpinLock(&pAd->irq_lock);
 301
 302
 303        vfree(pAd); // pci_free_consistent(os_cookie->pci_dev,sizeof(RTMP_ADAPTER),pAd,os_cookie->pAd_pa);
 304        if (os_cookie)
 305                kfree(os_cookie);
 306}
 307
 308BOOLEAN OS_Need_Clone_Packet(void)
 309{
 310        return (FALSE);
 311}
 312
 313
 314
 315/*
 316        ========================================================================
 317
 318        Routine Description:
 319                clone an input NDIS PACKET to another one. The new internally created NDIS PACKET
 320                must have only one NDIS BUFFER
 321                return - byte copied. 0 means can't create NDIS PACKET
 322                NOTE: internally created NDIS_PACKET should be destroyed by RTMPFreeNdisPacket
 323
 324        Arguments:
 325                pAd     Pointer to our adapter
 326                pInsAMSDUHdr    EWC A-MSDU format has extra 14-bytes header. if TRUE, insert this 14-byte hdr in front of MSDU.
 327                *pSrcTotalLen                   return total packet length. This lenght is calculated with 802.3 format packet.
 328
 329        Return Value:
 330                NDIS_STATUS_SUCCESS
 331                NDIS_STATUS_FAILURE
 332
 333        Note:
 334
 335        ========================================================================
 336*/
 337NDIS_STATUS RTMPCloneNdisPacket(
 338        IN      PRTMP_ADAPTER   pAd,
 339        IN      BOOLEAN                 pInsAMSDUHdr,
 340        IN      PNDIS_PACKET    pInPacket,
 341        OUT PNDIS_PACKET   *ppOutPacket)
 342{
 343
 344        struct sk_buff *pkt;
 345
 346        ASSERT(pInPacket);
 347        ASSERT(ppOutPacket);
 348
 349        // 1. Allocate a packet
 350        pkt = dev_alloc_skb(2048);
 351
 352        if (pkt == NULL)
 353        {
 354                return NDIS_STATUS_FAILURE;
 355        }
 356
 357        skb_put(pkt, GET_OS_PKT_LEN(pInPacket));
 358        NdisMoveMemory(pkt->data, GET_OS_PKT_DATAPTR(pInPacket), GET_OS_PKT_LEN(pInPacket));
 359        *ppOutPacket = OSPKT_TO_RTPKT(pkt);
 360
 361
 362        RTMP_SET_PACKET_SOURCE(OSPKT_TO_RTPKT(pkt), PKTSRC_NDIS);
 363
 364        printk("###Clone###\n");
 365
 366        return NDIS_STATUS_SUCCESS;
 367}
 368
 369
 370// the allocated NDIS PACKET must be freed via RTMPFreeNdisPacket()
 371NDIS_STATUS RTMPAllocateNdisPacket(
 372        IN      PRTMP_ADAPTER   pAd,
 373        OUT PNDIS_PACKET   *ppPacket,
 374        IN      PUCHAR                  pHeader,
 375        IN      UINT                    HeaderLen,
 376        IN      PUCHAR                  pData,
 377        IN      UINT                    DataLen)
 378{
 379        PNDIS_PACKET    pPacket;
 380        ASSERT(pData);
 381        ASSERT(DataLen);
 382
 383        // 1. Allocate a packet
 384        pPacket = (PNDIS_PACKET *) dev_alloc_skb(HeaderLen + DataLen + RTMP_PKT_TAIL_PADDING);
 385        if (pPacket == NULL)
 386        {
 387                *ppPacket = NULL;
 388#ifdef DEBUG
 389                printk("RTMPAllocateNdisPacket Fail\n\n");
 390#endif
 391                return NDIS_STATUS_FAILURE;
 392        }
 393
 394        // 2. clone the frame content
 395        if (HeaderLen > 0)
 396                NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket), pHeader, HeaderLen);
 397        if (DataLen > 0)
 398                NdisMoveMemory(GET_OS_PKT_DATAPTR(pPacket) + HeaderLen, pData, DataLen);
 399
 400        // 3. update length of packet
 401        skb_put(GET_OS_PKT_TYPE(pPacket), HeaderLen+DataLen);
 402
 403        RTMP_SET_PACKET_SOURCE(pPacket, PKTSRC_NDIS);
 404//      printk("%s : pPacket = %p, len = %d\n", __FUNCTION__, pPacket, GET_OS_PKT_LEN(pPacket));
 405        *ppPacket = pPacket;
 406        return NDIS_STATUS_SUCCESS;
 407}
 408
 409/*
 410  ========================================================================
 411  Description:
 412        This routine frees a miniport internally allocated NDIS_PACKET and its
 413        corresponding NDIS_BUFFER and allocated memory.
 414  ========================================================================
 415*/
 416VOID RTMPFreeNdisPacket(
 417        IN PRTMP_ADAPTER pAd,
 418        IN PNDIS_PACKET  pPacket)
 419{
 420        dev_kfree_skb_any(RTPKT_TO_OSPKT(pPacket));
 421}
 422
 423
 424// IRQL = DISPATCH_LEVEL
 425// NOTE: we do have an assumption here, that Byte0 and Byte1 always reasid at the same
 426//                       scatter gather buffer
 427NDIS_STATUS Sniff2BytesFromNdisBuffer(
 428        IN      PNDIS_BUFFER    pFirstBuffer,
 429        IN      UCHAR                   DesiredOffset,
 430        OUT PUCHAR                      pByte0,
 431        OUT PUCHAR                      pByte1)
 432{
 433    *pByte0 = *(PUCHAR)(pFirstBuffer + DesiredOffset);
 434    *pByte1 = *(PUCHAR)(pFirstBuffer + DesiredOffset + 1);
 435
 436        return NDIS_STATUS_SUCCESS;
 437}
 438
 439
 440void RTMP_QueryPacketInfo(
 441        IN  PNDIS_PACKET pPacket,
 442        OUT PACKET_INFO  *pPacketInfo,
 443        OUT PUCHAR               *pSrcBufVA,
 444        OUT     UINT             *pSrcBufLen)
 445{
 446        pPacketInfo->BufferCount = 1;
 447        pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
 448        pPacketInfo->PhysicalBufferCount = 1;
 449        pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
 450
 451        *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
 452        *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
 453}
 454
 455void RTMP_QueryNextPacketInfo(
 456        IN  PNDIS_PACKET *ppPacket,
 457        OUT PACKET_INFO  *pPacketInfo,
 458        OUT PUCHAR               *pSrcBufVA,
 459        OUT     UINT             *pSrcBufLen)
 460{
 461        PNDIS_PACKET pPacket = NULL;
 462
 463        if (*ppPacket)
 464                pPacket = GET_OS_PKT_NEXT(*ppPacket);
 465
 466        if (pPacket)
 467        {
 468                pPacketInfo->BufferCount = 1;
 469                pPacketInfo->pFirstBuffer = (PNDIS_BUFFER)GET_OS_PKT_DATAPTR(pPacket);
 470                pPacketInfo->PhysicalBufferCount = 1;
 471                pPacketInfo->TotalPacketLength = GET_OS_PKT_LEN(pPacket);
 472
 473                *pSrcBufVA = GET_OS_PKT_DATAPTR(pPacket);
 474                *pSrcBufLen = GET_OS_PKT_LEN(pPacket);
 475                *ppPacket = GET_OS_PKT_NEXT(pPacket);
 476        }
 477        else
 478        {
 479                pPacketInfo->BufferCount = 0;
 480                pPacketInfo->pFirstBuffer = NULL;
 481                pPacketInfo->PhysicalBufferCount = 0;
 482                pPacketInfo->TotalPacketLength = 0;
 483
 484                *pSrcBufVA = NULL;
 485                *pSrcBufLen = 0;
 486                *ppPacket = NULL;
 487        }
 488}
 489
 490
 491PNDIS_PACKET DuplicatePacket(
 492        IN      PRTMP_ADAPTER   pAd,
 493        IN      PNDIS_PACKET    pPacket,
 494        IN      UCHAR                   FromWhichBSSID)
 495{
 496        struct sk_buff  *skb;
 497        PNDIS_PACKET    pRetPacket = NULL;
 498        USHORT                  DataSize;
 499        UCHAR                   *pData;
 500
 501        DataSize = (USHORT) GET_OS_PKT_LEN(pPacket);
 502        pData = (PUCHAR) GET_OS_PKT_DATAPTR(pPacket);
 503
 504
 505        skb = skb_clone(RTPKT_TO_OSPKT(pPacket), MEM_ALLOC_FLAG);
 506        if (skb)
 507        {
 508                skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
 509                pRetPacket = OSPKT_TO_RTPKT(skb);
 510        }
 511
 512
 513        return pRetPacket;
 514
 515}
 516
 517PNDIS_PACKET duplicate_pkt(
 518        IN      PRTMP_ADAPTER   pAd,
 519        IN      PUCHAR                  pHeader802_3,
 520    IN  UINT            HdrLen,
 521        IN      PUCHAR                  pData,
 522        IN      ULONG                   DataSize,
 523        IN      UCHAR                   FromWhichBSSID)
 524{
 525        struct sk_buff  *skb;
 526        PNDIS_PACKET    pPacket = NULL;
 527
 528
 529        if ((skb = __dev_alloc_skb(HdrLen + DataSize + 2, MEM_ALLOC_FLAG)) != NULL)
 530        {
 531                skb_reserve(skb, 2);
 532                NdisMoveMemory(skb_tail_pointer(skb), pHeader802_3, HdrLen);
 533                skb_put(skb, HdrLen);
 534                NdisMoveMemory(skb_tail_pointer(skb), pData, DataSize);
 535                skb_put(skb, DataSize);
 536                skb->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
 537                pPacket = OSPKT_TO_RTPKT(skb);
 538        }
 539
 540        return pPacket;
 541}
 542
 543
 544#define TKIP_TX_MIC_SIZE                8
 545PNDIS_PACKET duplicate_pkt_with_TKIP_MIC(
 546        IN      PRTMP_ADAPTER   pAd,
 547        IN      PNDIS_PACKET    pPacket)
 548{
 549        struct sk_buff  *skb, *newskb;
 550
 551
 552        skb = RTPKT_TO_OSPKT(pPacket);
 553        if (skb_tailroom(skb) < TKIP_TX_MIC_SIZE)
 554        {
 555                // alloc a new skb and copy the packet
 556                newskb = skb_copy_expand(skb, skb_headroom(skb), TKIP_TX_MIC_SIZE, GFP_ATOMIC);
 557                dev_kfree_skb_any(skb);
 558                if (newskb == NULL)
 559                {
 560                        DBGPRINT(RT_DEBUG_ERROR, ("Extend Tx.MIC for packet failed!, dropping packet!\n"));
 561                        return NULL;
 562                }
 563                skb = newskb;
 564        }
 565
 566        return OSPKT_TO_RTPKT(skb);
 567
 568
 569}
 570
 571
 572
 573
 574PNDIS_PACKET ClonePacket(
 575        IN      PRTMP_ADAPTER   pAd,
 576        IN      PNDIS_PACKET    pPacket,
 577        IN      PUCHAR                  pData,
 578        IN      ULONG                   DataSize)
 579{
 580        struct sk_buff  *pRxPkt;
 581        struct sk_buff  *pClonedPkt;
 582
 583        ASSERT(pPacket);
 584        pRxPkt = RTPKT_TO_OSPKT(pPacket);
 585
 586        // clone the packet
 587        pClonedPkt = skb_clone(pRxPkt, MEM_ALLOC_FLAG);
 588
 589        if (pClonedPkt)
 590        {
 591        // set the correct dataptr and data len
 592        pClonedPkt->dev = pRxPkt->dev;
 593        pClonedPkt->data = pData;
 594        pClonedPkt->len = DataSize;
 595        pClonedPkt->tail = pClonedPkt->data + pClonedPkt->len;
 596                ASSERT(DataSize < 1530);
 597        }
 598        return pClonedPkt;
 599}
 600
 601//
 602// change OS packet DataPtr and DataLen
 603//
 604void  update_os_packet_info(
 605        IN      PRTMP_ADAPTER   pAd,
 606        IN      RX_BLK                  *pRxBlk,
 607        IN  UCHAR                       FromWhichBSSID)
 608{
 609        struct sk_buff  *pOSPkt;
 610
 611        ASSERT(pRxBlk->pRxPacket);
 612        pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
 613
 614        pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
 615        pOSPkt->data = pRxBlk->pData;
 616        pOSPkt->len = pRxBlk->DataSize;
 617        pOSPkt->tail = pOSPkt->data + pOSPkt->len;
 618}
 619
 620
 621void wlan_802_11_to_802_3_packet(
 622        IN      PRTMP_ADAPTER   pAd,
 623        IN      RX_BLK                  *pRxBlk,
 624        IN      PUCHAR                  pHeader802_3,
 625        IN  UCHAR                       FromWhichBSSID)
 626{
 627        struct sk_buff  *pOSPkt;
 628
 629        ASSERT(pRxBlk->pRxPacket);
 630        ASSERT(pHeader802_3);
 631
 632        pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
 633
 634        pOSPkt->dev = get_netdev_from_bssid(pAd, FromWhichBSSID);
 635        pOSPkt->data = pRxBlk->pData;
 636        pOSPkt->len = pRxBlk->DataSize;
 637        pOSPkt->tail = pOSPkt->data + pOSPkt->len;
 638
 639        //
 640        // copy 802.3 header
 641        //
 642        //
 643
 644#ifdef CONFIG_STA_SUPPORT
 645        IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
 646                NdisMoveMemory(skb_push(pOSPkt, LENGTH_802_3), pHeader802_3, LENGTH_802_3);
 647#endif // CONFIG_STA_SUPPORT //
 648        }
 649
 650
 651
 652void announce_802_3_packet(
 653        IN      PRTMP_ADAPTER   pAd,
 654        IN      PNDIS_PACKET    pPacket)
 655{
 656
 657        struct sk_buff  *pRxPkt;
 658#ifdef INF_AMAZON_PPA
 659        int             ret = 0;
 660        unsigned int ppa_flags = 0; /* reserved for now */
 661#endif // INF_AMAZON_PPA //
 662
 663        ASSERT(pPacket);
 664
 665        pRxPkt = RTPKT_TO_OSPKT(pPacket);
 666
 667#ifdef CONFIG_STA_SUPPORT
 668#endif // CONFIG_STA_SUPPORT //
 669
 670    /* Push up the protocol stack */
 671#ifdef IKANOS_VX_1X0
 672        IKANOS_DataFrameRx(pAd, pRxPkt->dev, pRxPkt, pRxPkt->len);
 673#else
 674#ifdef INF_AMAZON_SE
 675#ifdef BG_FT_SUPPORT
 676            BG_FTPH_PacketFromApHandle(pRxPkt);
 677            return;
 678#endif // BG_FT_SUPPORT //
 679#endif // INF_AMAZON_SE //
 680        pRxPkt->protocol = eth_type_trans(pRxPkt, pRxPkt->dev);
 681
 682#ifdef INF_AMAZON_PPA
 683        if (ppa_hook_directpath_send_fn && pAd->PPAEnable==TRUE )
 684        {
 685                memset(pRxPkt->head,0,pRxPkt->data-pRxPkt->head-14);
 686                DBGPRINT(RT_DEBUG_TRACE, ("ppa_hook_directpath_send_fn rx :ret:%d headroom:%d dev:%s pktlen:%d<===\n",ret,skb_headroom(pRxPkt)
 687                        ,pRxPkt->dev->name,pRxPkt->len));
 688                hex_dump("rx packet", pRxPkt->data, 32);
 689                ret = ppa_hook_directpath_send_fn(pAd->g_if_id, pRxPkt, pRxPkt->len, ppa_flags);
 690                pRxPkt=NULL;
 691                return;
 692
 693        }
 694#endif // INF_AMAZON_PPA //
 695
 696//#ifdef CONFIG_5VT_ENHANCE
 697//      *(int*)(pRxPkt->cb) = BRIDGE_TAG;
 698//#endif
 699
 700        {
 701                netif_rx(pRxPkt);
 702        }
 703
 704#endif // IKANOS_VX_1X0 //
 705}
 706
 707
 708PRTMP_SCATTER_GATHER_LIST
 709rt_get_sg_list_from_packet(PNDIS_PACKET pPacket, RTMP_SCATTER_GATHER_LIST *sg)
 710{
 711        sg->NumberOfElements = 1;
 712        sg->Elements[0].Address =  GET_OS_PKT_DATAPTR(pPacket);
 713        sg->Elements[0].Length = GET_OS_PKT_LEN(pPacket);
 714        return (sg);
 715}
 716
 717void hex_dump(char *str, unsigned char *pSrcBufVA, unsigned int SrcBufLen)
 718{
 719        unsigned char *pt;
 720        int x;
 721
 722        if (RTDebugLevel < RT_DEBUG_TRACE)
 723                return;
 724
 725        pt = pSrcBufVA;
 726        printk("%s: %p, len = %d\n",str,  pSrcBufVA, SrcBufLen);
 727        for (x=0; x<SrcBufLen; x++)
 728        {
 729                if (x % 16 == 0)
 730                        printk("0x%04x : ", x);
 731                printk("%02x ", ((unsigned char)pt[x]));
 732                if (x%16 == 15) printk("\n");
 733        }
 734        printk("\n");
 735}
 736
 737/*
 738        ========================================================================
 739
 740        Routine Description:
 741                Send log message through wireless event
 742
 743                Support standard iw_event with IWEVCUSTOM. It is used below.
 744
 745                iwreq_data.data.flags is used to store event_flag that is defined by user.
 746                iwreq_data.data.length is the length of the event log.
 747
 748                The format of the event log is composed of the entry's MAC address and
 749                the desired log message (refer to pWirelessEventText).
 750
 751                        ex: 11:22:33:44:55:66 has associated successfully
 752
 753                p.s. The requirement of Wireless Extension is v15 or newer.
 754
 755        ========================================================================
 756*/
 757VOID RTMPSendWirelessEvent(
 758        IN      PRTMP_ADAPTER   pAd,
 759        IN      USHORT                  Event_flag,
 760        IN      PUCHAR                  pAddr,
 761        IN      UCHAR                   BssIdx,
 762        IN      CHAR                    Rssi)
 763{
 764#if WIRELESS_EXT >= 15
 765
 766        //union         iwreq_data      wrqu;
 767        PSTRING pBuf = NULL, pBufPtr = NULL;
 768        USHORT  event, type, BufLen;
 769        UCHAR   event_table_len = 0;
 770
 771        type = Event_flag & 0xFF00;
 772        event = Event_flag & 0x00FF;
 773
 774        switch (type)
 775        {
 776                case IW_SYS_EVENT_FLAG_START:
 777                        event_table_len = IW_SYS_EVENT_TYPE_NUM;
 778                        break;
 779
 780                case IW_SPOOF_EVENT_FLAG_START:
 781                        event_table_len = IW_SPOOF_EVENT_TYPE_NUM;
 782                        break;
 783
 784                case IW_FLOOD_EVENT_FLAG_START:
 785                        event_table_len = IW_FLOOD_EVENT_TYPE_NUM;
 786                        break;
 787        }
 788
 789        if (event_table_len == 0)
 790        {
 791                DBGPRINT(RT_DEBUG_ERROR, ("%s : The type(%0x02x) is not valid.\n", __FUNCTION__, type));
 792                return;
 793        }
 794
 795        if (event >= event_table_len)
 796        {
 797                DBGPRINT(RT_DEBUG_ERROR, ("%s : The event(%0x02x) is not valid.\n", __FUNCTION__, event));
 798                return;
 799        }
 800
 801        //Allocate memory and copy the msg.
 802        if((pBuf = kmalloc(IW_CUSTOM_MAX_LEN, GFP_ATOMIC)) != NULL)
 803        {
 804                //Prepare the payload
 805                memset(pBuf, 0, IW_CUSTOM_MAX_LEN);
 806
 807                pBufPtr = pBuf;
 808
 809                if (pAddr)
 810                        pBufPtr += sprintf(pBufPtr, "(RT2860) STA(%02x:%02x:%02x:%02x:%02x:%02x) ", PRINT_MAC(pAddr));
 811                else if (BssIdx < MAX_MBSSID_NUM)
 812                        pBufPtr += sprintf(pBufPtr, "(RT2860) BSS(ra%d) ", BssIdx);
 813                else
 814                        pBufPtr += sprintf(pBufPtr, "(RT2860) ");
 815
 816                if (type == IW_SYS_EVENT_FLAG_START)
 817                        pBufPtr += sprintf(pBufPtr, "%s", pWirelessSysEventText[event]);
 818                else if (type == IW_SPOOF_EVENT_FLAG_START)
 819                        pBufPtr += sprintf(pBufPtr, "%s (RSSI=%d)", pWirelessSpoofEventText[event], Rssi);
 820                else if (type == IW_FLOOD_EVENT_FLAG_START)
 821                        pBufPtr += sprintf(pBufPtr, "%s", pWirelessFloodEventText[event]);
 822                else
 823                        pBufPtr += sprintf(pBufPtr, "%s", "unknown event");
 824
 825                pBufPtr[pBufPtr - pBuf] = '\0';
 826                BufLen = pBufPtr - pBuf;
 827
 828                RtmpOSWrielessEventSend(pAd, IWEVCUSTOM, Event_flag, NULL, (PUCHAR)pBuf, BufLen);
 829                //DBGPRINT(RT_DEBUG_TRACE, ("%s : %s\n", __FUNCTION__, pBuf));
 830
 831                kfree(pBuf);
 832        }
 833        else
 834                DBGPRINT(RT_DEBUG_ERROR, ("%s : Can't allocate memory for wireless event.\n", __FUNCTION__));
 835#else
 836        DBGPRINT(RT_DEBUG_ERROR, ("%s : The Wireless Extension MUST be v15 or newer.\n", __FUNCTION__));
 837#endif  /* WIRELESS_EXT >= 15 */
 838}
 839
 840
 841
 842
 843#ifdef CONFIG_STA_SUPPORT
 844void send_monitor_packets(
 845        IN      PRTMP_ADAPTER   pAd,
 846        IN      RX_BLK                  *pRxBlk)
 847{
 848    struct sk_buff      *pOSPkt;
 849    wlan_ng_prism2_header *ph;
 850    int rate_index = 0;
 851    USHORT header_len = 0;
 852    UCHAR temp_header[40] = {0};
 853
 854    u_int32_t ralinkrate[256] = {2,4,11,22, 12,18,24,36,48,72,96,  108,   109, 110, 111, 112, 13, 26, 39, 52,78,104, 117, 130, 26, 52, 78,104, 156, 208, 234, 260, 27, 54,81,108,162, 216, 243, 270, // Last 38
 855        54, 108, 162, 216, 324, 432, 486, 540,  14, 29, 43, 57, 87, 115, 130, 144, 29, 59,87,115, 173, 230,260, 288, 30, 60,90,120,180,240,270,300,60,120,180,240,360,480,540,600, 0,1,2,3,4,5,6,7,8,9,10,
 856        11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80};
 857
 858
 859    ASSERT(pRxBlk->pRxPacket);
 860    if (pRxBlk->DataSize < 10)
 861    {
 862        DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too small! (%d)\n", __FUNCTION__, pRxBlk->DataSize));
 863                goto err_free_sk_buff;
 864    }
 865
 866    if (pRxBlk->DataSize + sizeof(wlan_ng_prism2_header) > RX_BUFFER_AGGRESIZE)
 867    {
 868        DBGPRINT(RT_DEBUG_ERROR, ("%s : Size is too large! (%d)\n", __FUNCTION__, pRxBlk->DataSize + sizeof(wlan_ng_prism2_header)));
 869                goto err_free_sk_buff;
 870    }
 871
 872    pOSPkt = RTPKT_TO_OSPKT(pRxBlk->pRxPacket);
 873        pOSPkt->dev = get_netdev_from_bssid(pAd, BSS0);
 874    if (pRxBlk->pHeader->FC.Type == BTYPE_DATA)
 875    {
 876        pRxBlk->DataSize -= LENGTH_802_11;
 877        if ((pRxBlk->pHeader->FC.ToDs == 1) &&
 878            (pRxBlk->pHeader->FC.FrDs == 1))
 879            header_len = LENGTH_802_11_WITH_ADDR4;
 880        else
 881            header_len = LENGTH_802_11;
 882
 883        // QOS
 884        if (pRxBlk->pHeader->FC.SubType & 0x08)
 885        {
 886            header_len += 2;
 887                // Data skip QOS contorl field
 888                pRxBlk->DataSize -=2;
 889        }
 890
 891        // Order bit: A-Ralink or HTC+
 892        if (pRxBlk->pHeader->FC.Order)
 893        {
 894            header_len += 4;
 895                        // Data skip HTC contorl field
 896                        pRxBlk->DataSize -= 4;
 897        }
 898
 899        // Copy Header
 900        if (header_len <= 40)
 901            NdisMoveMemory(temp_header, pRxBlk->pData, header_len);
 902
 903        // skip HW padding
 904        if (pRxBlk->RxD.L2PAD)
 905            pRxBlk->pData += (header_len + 2);
 906        else
 907            pRxBlk->pData += header_len;
 908    } //end if
 909
 910
 911        if (pRxBlk->DataSize < pOSPkt->len) {
 912        skb_trim(pOSPkt,pRxBlk->DataSize);
 913    } else {
 914        skb_put(pOSPkt,(pRxBlk->DataSize - pOSPkt->len));
 915    } //end if
 916
 917    if ((pRxBlk->pData - pOSPkt->data) > 0) {
 918            skb_put(pOSPkt,(pRxBlk->pData - pOSPkt->data));
 919            skb_pull(pOSPkt,(pRxBlk->pData - pOSPkt->data));
 920    } //end if
 921
 922    if (skb_headroom(pOSPkt) < (sizeof(wlan_ng_prism2_header)+ header_len)) {
 923        if (pskb_expand_head(pOSPkt, (sizeof(wlan_ng_prism2_header) + header_len), 0, GFP_ATOMIC)) {
 924                DBGPRINT(RT_DEBUG_ERROR, ("%s : Reallocate header size of sk_buff fail!\n", __FUNCTION__));
 925                        goto err_free_sk_buff;
 926            } //end if
 927    } //end if
 928
 929    if (header_len > 0)
 930        NdisMoveMemory(skb_push(pOSPkt, header_len), temp_header, header_len);
 931
 932    ph = (wlan_ng_prism2_header *) skb_push(pOSPkt, sizeof(wlan_ng_prism2_header));
 933        NdisZeroMemory(ph, sizeof(wlan_ng_prism2_header));
 934
 935    ph->msgcode             = DIDmsg_lnxind_wlansniffrm;
 936        ph->msglen                  = sizeof(wlan_ng_prism2_header);
 937        strcpy((PSTRING) ph->devname, (PSTRING) pAd->net_dev->name);
 938
 939    ph->hosttime.did = DIDmsg_lnxind_wlansniffrm_hosttime;
 940        ph->hosttime.status = 0;
 941        ph->hosttime.len = 4;
 942        ph->hosttime.data = jiffies;
 943
 944        ph->mactime.did = DIDmsg_lnxind_wlansniffrm_mactime;
 945        ph->mactime.status = 0;
 946        ph->mactime.len = 0;
 947        ph->mactime.data = 0;
 948
 949    ph->istx.did = DIDmsg_lnxind_wlansniffrm_istx;
 950        ph->istx.status = 0;
 951        ph->istx.len = 0;
 952        ph->istx.data = 0;
 953
 954    ph->channel.did = DIDmsg_lnxind_wlansniffrm_channel;
 955        ph->channel.status = 0;
 956        ph->channel.len = 4;
 957
 958    ph->channel.data = (u_int32_t)pAd->CommonCfg.Channel;
 959
 960    ph->rssi.did = DIDmsg_lnxind_wlansniffrm_rssi;
 961        ph->rssi.status = 0;
 962        ph->rssi.len = 4;
 963    ph->rssi.data = (u_int32_t)RTMPMaxRssi(pAd, ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI0, RSSI_0), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI1, RSSI_1), ConvertToRssi(pAd, pRxBlk->pRxWI->RSSI2, RSSI_2));;
 964
 965        ph->signal.did = DIDmsg_lnxind_wlansniffrm_signal;
 966        ph->signal.status = 0;
 967        ph->signal.len = 4;
 968        ph->signal.data = 0; //rssi + noise;
 969
 970        ph->noise.did = DIDmsg_lnxind_wlansniffrm_noise;
 971        ph->noise.status = 0;
 972        ph->noise.len = 4;
 973        ph->noise.data = 0;
 974
 975#ifdef DOT11_N_SUPPORT
 976    if (pRxBlk->pRxWI->PHYMODE >= MODE_HTMIX)
 977    {
 978        rate_index = 16 + ((UCHAR)pRxBlk->pRxWI->BW *16) + ((UCHAR)pRxBlk->pRxWI->ShortGI *32) + ((UCHAR)pRxBlk->pRxWI->MCS);
 979    }
 980    else
 981#endif // DOT11_N_SUPPORT //
 982        if (pRxBlk->pRxWI->PHYMODE == MODE_OFDM)
 983        rate_index = (UCHAR)(pRxBlk->pRxWI->MCS) + 4;
 984    else
 985        rate_index = (UCHAR)(pRxBlk->pRxWI->MCS);
 986    if (rate_index < 0)
 987        rate_index = 0;
 988    if (rate_index > 255)
 989        rate_index = 255;
 990
 991        ph->rate.did = DIDmsg_lnxind_wlansniffrm_rate;
 992        ph->rate.status = 0;
 993        ph->rate.len = 4;
 994    ph->rate.data = ralinkrate[rate_index];
 995
 996        ph->frmlen.did = DIDmsg_lnxind_wlansniffrm_frmlen;
 997    ph->frmlen.status = 0;
 998        ph->frmlen.len = 4;
 999        ph->frmlen.data = (u_int32_t)pRxBlk->DataSize;
1000
1001
1002    pOSPkt->pkt_type = PACKET_OTHERHOST;
1003    pOSPkt->protocol = eth_type_trans(pOSPkt, pOSPkt->dev);
1004    pOSPkt->ip_summed = CHECKSUM_NONE;
1005    netif_rx(pOSPkt);
1006
1007    return;
1008
1009err_free_sk_buff:
1010        RELEASE_NDIS_PACKET(pAd, pRxBlk->pRxPacket, NDIS_STATUS_FAILURE);
1011        return;
1012
1013}
1014#endif // CONFIG_STA_SUPPORT //
1015
1016
1017
1018/*******************************************************************************
1019
1020        File open/close related functions.
1021
1022 *******************************************************************************/
1023RTMP_OS_FD RtmpOSFileOpen(char *pPath,  int flag, int mode)
1024{
1025        struct file     *filePtr;
1026
1027        filePtr = filp_open(pPath, flag, 0);
1028        if (IS_ERR(filePtr))
1029        {
1030                DBGPRINT(RT_DEBUG_ERROR, ("%s(): Error %ld opening %s\n", __FUNCTION__, -PTR_ERR(filePtr), pPath));
1031        }
1032
1033        return (RTMP_OS_FD)filePtr;
1034}
1035
1036int RtmpOSFileClose(RTMP_OS_FD osfd)
1037{
1038        filp_close(osfd, NULL);
1039        return 0;
1040}
1041
1042
1043void RtmpOSFileSeek(RTMP_OS_FD osfd, int offset)
1044{
1045        osfd->f_pos = offset;
1046}
1047
1048
1049int RtmpOSFileRead(RTMP_OS_FD osfd, char *pDataPtr, int readLen)
1050{
1051        // The object must have a read method
1052        if (osfd->f_op && osfd->f_op->read)
1053        {
1054                return osfd->f_op->read(osfd,  pDataPtr, readLen, &osfd->f_pos);
1055        }
1056        else
1057        {
1058                DBGPRINT(RT_DEBUG_ERROR, ("no file read method\n"));
1059                return -1;
1060        }
1061}
1062
1063
1064int RtmpOSFileWrite(RTMP_OS_FD osfd, char *pDataPtr, int writeLen)
1065{
1066        return osfd->f_op->write(osfd, pDataPtr, (size_t)writeLen, &osfd->f_pos);
1067}
1068
1069
1070void RtmpOSFSInfoChange(RTMP_OS_FS_INFO *pOSFSInfo, BOOLEAN bSet)
1071{
1072        if (bSet)
1073        {
1074                // Save uid and gid used for filesystem access.
1075                // Set user and group to 0 (root)
1076#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
1077                pOSFSInfo->fsuid= current->fsuid;
1078                pOSFSInfo->fsgid = current->fsgid;
1079                current->fsuid = current->fsgid = 0;
1080#else
1081                pOSFSInfo->fsuid = current_fsuid();
1082                pOSFSInfo->fsgid = current_fsgid();
1083#endif
1084                pOSFSInfo->fs = get_fs();
1085                set_fs(KERNEL_DS);
1086        }
1087        else
1088        {
1089                set_fs(pOSFSInfo->fs);
1090#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
1091                current->fsuid = pOSFSInfo->fsuid;
1092                current->fsgid = pOSFSInfo->fsgid;
1093#endif
1094        }
1095}
1096
1097
1098
1099/*******************************************************************************
1100
1101        Task create/management/kill related functions.
1102
1103 *******************************************************************************/
1104NDIS_STATUS RtmpOSTaskKill(
1105        IN RTMP_OS_TASK *pTask)
1106{
1107        RTMP_ADAPTER *pAd;
1108        int ret = NDIS_STATUS_FAILURE;
1109
1110        pAd = (RTMP_ADAPTER *)pTask->priv;
1111
1112#ifdef KTHREAD_SUPPORT
1113        if (pTask->kthread_task)
1114        {
1115                kthread_stop(pTask->kthread_task);
1116                ret = NDIS_STATUS_SUCCESS;
1117        }
1118#else
1119        CHECK_PID_LEGALITY(pTask->taskPID)
1120        {
1121                printk("Terminate the task(%s) with pid(%d)!\n", pTask->taskName, GET_PID_NUMBER(pTask->taskPID));
1122                mb();
1123                pTask->task_killed = 1;
1124                mb();
1125                ret = KILL_THREAD_PID(pTask->taskPID, SIGTERM, 1);
1126                if (ret)
1127                {
1128                        printk(KERN_WARNING "kill task(%s) with pid(%d) failed(retVal=%d)!\n",
1129                                pTask->taskName, GET_PID_NUMBER(pTask->taskPID), ret);
1130                }
1131                else
1132                {
1133                        wait_for_completion(&pTask->taskComplete);
1134                        pTask->taskPID = THREAD_PID_INIT_VALUE;
1135                        pTask->task_killed = 0;
1136                        ret = NDIS_STATUS_SUCCESS;
1137                }
1138        }
1139#endif
1140
1141        return ret;
1142
1143}
1144
1145
1146INT RtmpOSTaskNotifyToExit(
1147        IN RTMP_OS_TASK *pTask)
1148{
1149
1150#ifndef KTHREAD_SUPPORT
1151        complete_and_exit(&pTask->taskComplete, 0);
1152#endif
1153
1154        return 0;
1155}
1156
1157
1158void RtmpOSTaskCustomize(
1159        IN RTMP_OS_TASK *pTask)
1160{
1161
1162#ifndef KTHREAD_SUPPORT
1163
1164#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1165        daemonize((PSTRING)&pTask->taskName[0]/*"%s",pAd->net_dev->name*/);
1166
1167        allow_signal(SIGTERM);
1168        allow_signal(SIGKILL);
1169        current->flags |= PF_NOFREEZE;
1170#else
1171        unsigned long flags;
1172
1173        daemonize();
1174        reparent_to_init();
1175        strcpy(current->comm, &pTask->taskName[0]);
1176
1177        siginitsetinv(&current->blocked, sigmask(SIGTERM) | sigmask(SIGKILL));
1178
1179        /* Allow interception of SIGKILL only
1180         * Don't allow other signals to interrupt the transmission */
1181#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)
1182        spin_lock_irqsave(&current->sigmask_lock, flags);
1183        flush_signals(current);
1184        recalc_sigpending(current);
1185        spin_unlock_irqrestore(&current->sigmask_lock, flags);
1186#endif
1187#endif
1188
1189    /* signal that we've started the thread */
1190        complete(&pTask->taskComplete);
1191
1192#endif
1193}
1194
1195
1196NDIS_STATUS RtmpOSTaskAttach(
1197        IN RTMP_OS_TASK *pTask,
1198        IN int (*fn)(void *),
1199        IN void *arg)
1200{
1201        NDIS_STATUS status = NDIS_STATUS_SUCCESS;
1202        pid_t pid_number = -1;
1203
1204#ifdef KTHREAD_SUPPORT
1205        pTask->task_killed = 0;
1206        pTask->kthread_task = NULL;
1207        pTask->kthread_task = kthread_run(fn, arg, pTask->taskName);
1208        if (IS_ERR(pTask->kthread_task))
1209                status = NDIS_STATUS_FAILURE;
1210#else
1211        pid_number = kernel_thread(fn, arg, RTMP_OS_MGMT_TASK_FLAGS);
1212        if (pid_number < 0)
1213        {
1214                DBGPRINT (RT_DEBUG_ERROR, ("Attach task(%s) failed!\n", pTask->taskName));
1215                status = NDIS_STATUS_FAILURE;
1216        }
1217        else
1218        {
1219                pTask->taskPID = GET_PID(pid_number);
1220
1221                // Wait for the thread to start
1222                wait_for_completion(&pTask->taskComplete);
1223                status = NDIS_STATUS_SUCCESS;
1224        }
1225#endif
1226        return status;
1227}
1228
1229
1230NDIS_STATUS RtmpOSTaskInit(
1231        IN RTMP_OS_TASK *pTask,
1232        IN PSTRING              pTaskName,
1233        IN VOID                 *pPriv)
1234{
1235        int len;
1236
1237        ASSERT(pTask);
1238
1239#ifndef KTHREAD_SUPPORT
1240        NdisZeroMemory((PUCHAR)(pTask), sizeof(RTMP_OS_TASK));
1241#endif
1242
1243        len = strlen(pTaskName);
1244        len = len > (RTMP_OS_TASK_NAME_LEN -1) ? (RTMP_OS_TASK_NAME_LEN-1) : len;
1245        NdisMoveMemory(&pTask->taskName[0], pTaskName, len);
1246        pTask->priv = pPriv;
1247
1248#ifndef KTHREAD_SUPPORT
1249        RTMP_SEM_EVENT_INIT_LOCKED(&(pTask->taskSema));
1250        pTask->taskPID = THREAD_PID_INIT_VALUE;
1251
1252        init_completion (&pTask->taskComplete);
1253#endif
1254
1255        return NDIS_STATUS_SUCCESS;
1256}
1257
1258
1259void RTMP_IndicateMediaState(
1260        IN      PRTMP_ADAPTER   pAd)
1261{
1262        if (pAd->CommonCfg.bWirelessEvent)
1263        {
1264                if (pAd->IndicateMediaState == NdisMediaStateConnected)
1265                {
1266                        RTMPSendWirelessEvent(pAd, IW_STA_LINKUP_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1267                }
1268                else
1269                {
1270                        RTMPSendWirelessEvent(pAd, IW_STA_LINKDOWN_EVENT_FLAG, pAd->MacTab.Content[BSSID_WCID].Addr, BSS0, 0);
1271                }
1272        }
1273}
1274
1275
1276#if LINUX_VERSION_CODE <= 0x20402       // Red Hat 7.1
1277//static struct net_device *alloc_netdev(int sizeof_priv, const char *mask, void (*setup)(struct net_device *)) //sample
1278struct net_device *alloc_netdev(
1279        int sizeof_priv,
1280        const char *mask,
1281        void (*setup)(struct net_device *))
1282{
1283    struct net_device   *dev;
1284    INT                                 alloc_size;
1285
1286
1287    /* ensure 32-byte alignment of the private area */
1288    alloc_size = sizeof (*dev) + sizeof_priv + 31;
1289
1290    dev = (struct net_device *) kmalloc(alloc_size, GFP_KERNEL);
1291    if (dev == NULL)
1292    {
1293        DBGPRINT(RT_DEBUG_ERROR,
1294                                ("alloc_netdev: Unable to allocate device memory.\n"));
1295        return NULL;
1296    }
1297
1298    memset(dev, 0, alloc_size);
1299
1300    if (sizeof_priv)
1301        dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
1302
1303    setup(dev);
1304    strcpy(dev->name, mask);
1305
1306    return dev;
1307}
1308#endif // LINUX_VERSION_CODE //
1309
1310
1311int RtmpOSWrielessEventSend(
1312        IN RTMP_ADAPTER *pAd,
1313        IN UINT32               eventType,
1314        IN INT                  flags,
1315        IN PUCHAR               pSrcMac,
1316        IN PUCHAR               pData,
1317        IN UINT32               dataLen)
1318{
1319        union iwreq_data    wrqu;
1320
1321       memset(&wrqu, 0, sizeof(wrqu));
1322
1323        if (flags>-1)
1324               wrqu.data.flags = flags;
1325
1326        if (pSrcMac)
1327                memcpy(wrqu.ap_addr.sa_data, pSrcMac, MAC_ADDR_LEN);
1328
1329        if ((pData!= NULL) && (dataLen > 0))
1330                wrqu.data.length = dataLen;
1331
1332       wireless_send_event(pAd->net_dev, eventType, &wrqu, (char *)pData);
1333        return 0;
1334}
1335
1336
1337int RtmpOSNetDevAddrSet(
1338        IN PNET_DEV pNetDev,
1339        IN PUCHAR       pMacAddr)
1340{
1341        struct net_device *net_dev;
1342        RTMP_ADAPTER *pAd;
1343
1344        net_dev = pNetDev;
1345        //pAd = (RTMP_ADAPTER *)net_dev->priv;
1346        pAd=RTMP_OS_NETDEV_GET_PRIV(pNetDev);
1347
1348#ifdef CONFIG_STA_SUPPORT
1349        // work-around for the SuSE due to it has it's own interface name management system.
1350        IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
1351        {
1352                NdisZeroMemory(pAd->StaCfg.dev_name, 16);
1353                NdisMoveMemory(pAd->StaCfg.dev_name, net_dev->name, strlen(net_dev->name));
1354        }
1355#endif // CONFIG_STA_SUPPORT //
1356
1357        NdisMoveMemory(net_dev->dev_addr, pMacAddr, 6);
1358
1359        return 0;
1360}
1361
1362
1363
1364/*
1365  *     Assign the network dev name for created Ralink WiFi interface.
1366  */
1367static int RtmpOSNetDevRequestName(
1368        IN RTMP_ADAPTER *pAd,
1369        IN PNET_DEV dev,
1370        IN PSTRING pPrefixStr,
1371        IN INT  devIdx)
1372{
1373        PNET_DEV                existNetDev;
1374        STRING          suffixName[IFNAMSIZ];
1375        STRING          desiredName[IFNAMSIZ];
1376        int     ifNameIdx, prefixLen, slotNameLen;
1377        int Status;
1378
1379
1380        prefixLen = strlen(pPrefixStr);
1381        ASSERT((prefixLen < IFNAMSIZ));
1382
1383        for (ifNameIdx = devIdx; ifNameIdx < 32; ifNameIdx++)
1384        {
1385                memset(suffixName, 0, IFNAMSIZ);
1386                memset(desiredName, 0, IFNAMSIZ);
1387                strncpy(&desiredName[0], pPrefixStr, prefixLen);
1388
1389#ifdef MULTIPLE_CARD_SUPPORT
1390                if (pAd->MC_RowID >= 0)
1391                        sprintf(suffixName, "%02d_%d", pAd->MC_RowID, ifNameIdx);
1392                else
1393#endif // MULTIPLE_CARD_SUPPORT //
1394                sprintf(suffixName, "%d", ifNameIdx);
1395
1396                slotNameLen = strlen(suffixName);
1397                ASSERT(((slotNameLen + prefixLen) < IFNAMSIZ));
1398                strcat(desiredName, suffixName);
1399
1400                existNetDev = RtmpOSNetDevGetByName(dev, &desiredName[0]);
1401                if (existNetDev == NULL)
1402                        break;
1403                else
1404                        RtmpOSNetDeviceRefPut(existNetDev);
1405        }
1406
1407        if(ifNameIdx < 32)
1408        {
1409                strcpy(&dev->name[0], &desiredName[0]);
1410                Status = NDIS_STATUS_SUCCESS;
1411        }
1412        else
1413        {
1414                DBGPRINT(RT_DEBUG_ERROR,
1415                                        ("Cannot request DevName with preifx(%s) and in range(0~32) as suffix from OS!\n", pPrefixStr));
1416                Status = NDIS_STATUS_FAILURE;
1417        }
1418
1419        return Status;
1420}
1421
1422
1423void RtmpOSNetDevClose(
1424        IN PNET_DEV pNetDev)
1425{
1426        dev_close(pNetDev);
1427}
1428
1429
1430void RtmpOSNetDevFree(PNET_DEV pNetDev)
1431{
1432        ASSERT(pNetDev);
1433
1434#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1435        free_netdev(pNetDev);
1436#else
1437        kfree(pNetDev);
1438#endif
1439}
1440
1441
1442INT RtmpOSNetDevAlloc(
1443        IN PNET_DEV *new_dev_p,
1444        IN UINT32       privDataSize)
1445{
1446        // assign it as null first.
1447        *new_dev_p = NULL;
1448
1449        DBGPRINT(RT_DEBUG_TRACE, ("Allocate a net device with private data size=%d!\n", privDataSize));
1450#if LINUX_VERSION_CODE <= 0x20402 // Red Hat 7.1
1451        *new_dev_p = alloc_netdev(privDataSize, "eth%d", ether_setup);
1452#else
1453        *new_dev_p = alloc_etherdev(privDataSize);
1454#endif // LINUX_VERSION_CODE //
1455
1456        if (*new_dev_p)
1457                return NDIS_STATUS_SUCCESS;
1458        else
1459                return NDIS_STATUS_FAILURE;
1460}
1461
1462
1463PNET_DEV RtmpOSNetDevGetByName(PNET_DEV pNetDev, PSTRING pDevName)
1464{
1465        PNET_DEV        pTargetNetDev = NULL;
1466
1467
1468#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1469
1470#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
1471#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
1472        pTargetNetDev = dev_get_by_name(dev_net(pNetDev), pDevName);
1473#else
1474        ASSERT(pNetDev);
1475        pTargetNetDev = dev_get_by_name(pNetDev->nd_net, pDevName);
1476#endif
1477#else
1478        pTargetNetDev = dev_get_by_name(pDevName);
1479#endif // KERNEL_VERSION(2,6,24) //
1480
1481#else
1482        int     devNameLen;
1483
1484        devNameLen = strlen(pDevName);
1485        ASSERT((devNameLen <= IFNAMSIZ));
1486
1487        for(pTargetNetDev=dev_base; pTargetNetDev!=NULL; pTargetNetDev=pTargetNetDev->next)
1488        {
1489                if (strncmp(pTargetNetDev->name, pDevName, devNameLen) == 0)
1490                        break;
1491        }
1492#endif // KERNEL_VERSION(2,5,0) //
1493
1494        return pTargetNetDev;
1495}
1496
1497
1498void RtmpOSNetDeviceRefPut(PNET_DEV pNetDev)
1499{
1500#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
1501        /*
1502                every time dev_get_by_name is called, and it has returned a valid struct
1503                net_device*, dev_put should be called afterwards, because otherwise the
1504                machine hangs when the device is unregistered (since dev->refcnt > 1).
1505        */
1506        if(pNetDev)
1507                dev_put(pNetDev);
1508#endif // LINUX_VERSION_CODE //
1509}
1510
1511
1512INT RtmpOSNetDevDestory(
1513        IN RTMP_ADAPTER *pAd,
1514        IN PNET_DEV             pNetDev)
1515{
1516
1517        // TODO: Need to fix this
1518        printk("WARNING: This function(%s) not implement yet!!!\n", __FUNCTION__);
1519        return 0;
1520}
1521
1522
1523void RtmpOSNetDevDetach(PNET_DEV pNetDev)
1524{
1525        unregister_netdev(pNetDev);
1526}
1527
1528
1529int RtmpOSNetDevAttach(
1530        IN PNET_DEV pNetDev,
1531        IN RTMP_OS_NETDEV_OP_HOOK *pDevOpHook)
1532{
1533        int ret, rtnl_locked = FALSE;
1534
1535        DBGPRINT(RT_DEBUG_TRACE, ("RtmpOSNetDevAttach()--->\n"));
1536        // If we need hook some callback function to the net device structrue, now do it.
1537        if (pDevOpHook)
1538        {
1539                PRTMP_ADAPTER pAd = RTMP_OS_NETDEV_GET_PRIV(pNetDev);
1540
1541                pNetDev->netdev_ops = pDevOpHook->netdev_ops;
1542
1543                /* OS specific flags, here we used to indicate if we are virtual interface */
1544                pNetDev->priv_flags = pDevOpHook->priv_flags;
1545
1546#if (WIRELESS_EXT < 21) && (WIRELESS_EXT >= 12)
1547                pNetDev->get_wireless_stats = rt28xx_get_wireless_stats;
1548#endif
1549
1550#ifdef CONFIG_STA_SUPPORT
1551#if WIRELESS_EXT >= 12
1552                if (pAd->OpMode == OPMODE_STA)
1553                {
1554                        pNetDev->wireless_handlers = &rt28xx_iw_handler_def;
1555                }
1556#endif //WIRELESS_EXT >= 12
1557#endif // CONFIG_STA_SUPPORT //
1558
1559#ifdef CONFIG_APSTA_MIXED_SUPPORT
1560#if WIRELESS_EXT >= 12
1561                if (pAd->OpMode == OPMODE_AP)
1562                {
1563                        pNetDev->wireless_handlers = &rt28xx_ap_iw_handler_def;
1564                }
1565#endif //WIRELESS_EXT >= 12
1566#endif // CONFIG_APSTA_MIXED_SUPPORT //
1567
1568                // copy the net device mac address to the net_device structure.
1569                NdisMoveMemory(pNetDev->dev_addr, &pDevOpHook->devAddr[0], MAC_ADDR_LEN);
1570
1571                rtnl_locked = pDevOpHook->needProtcted;
1572        }
1573
1574        if (rtnl_locked)
1575                ret = register_netdevice(pNetDev);
1576        else
1577                ret = register_netdev(pNetDev);
1578
1579        DBGPRINT(RT_DEBUG_TRACE, ("<---RtmpOSNetDevAttach(), ret=%d\n", ret));
1580        if (ret == 0)
1581                return NDIS_STATUS_SUCCESS;
1582        else
1583                return NDIS_STATUS_FAILURE;
1584}
1585
1586
1587PNET_DEV RtmpOSNetDevCreate(
1588        IN RTMP_ADAPTER *pAd,
1589        IN INT                  devType,
1590        IN INT                  devNum,
1591        IN INT                  privMemSize,
1592        IN PSTRING              pNamePrefix)
1593{
1594        struct net_device *pNetDev = NULL;
1595        int status;
1596
1597
1598        /* allocate a new network device */
1599        status = RtmpOSNetDevAlloc(&pNetDev, 0 /*privMemSize*/);
1600        if (status != NDIS_STATUS_SUCCESS)
1601        {
1602                /* allocation fail, exit */
1603                DBGPRINT(RT_DEBUG_ERROR, ("Allocate network device fail (%s)...\n", pNamePrefix));
1604                return NULL;
1605        }
1606
1607
1608        /* find a available interface name, max 32 interfaces */
1609        status = RtmpOSNetDevRequestName(pAd, pNetDev, pNamePrefix, devNum);
1610        if (status != NDIS_STATUS_SUCCESS)
1611        {
1612                /* error! no any available ra name can be used! */
1613                DBGPRINT(RT_DEBUG_ERROR, ("Assign interface name (%s with suffix 0~32) failed...\n", pNamePrefix));
1614                RtmpOSNetDevFree(pNetDev);
1615
1616                return NULL;
1617        }
1618        else
1619        {
1620                DBGPRINT(RT_DEBUG_TRACE, ("The name of the new %s interface is %s...\n", pNamePrefix, pNetDev->name));
1621        }
1622
1623        return pNetDev;
1624}
1625
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.