linux/drivers/staging/winbond/wb35rx.c
<<
>>
Prefs
   1//============================================================================
   2//  Copyright (c) 1996-2002 Winbond Electronic Corporation
   3//
   4//  Module Name:
   5//    Wb35Rx.c
   6//
   7//  Abstract:
   8//    Processing the Rx message from down layer
   9//
  10//============================================================================
  11#include <linux/usb.h>
  12
  13#include "core.h"
  14#include "sysdef.h"
  15#include "wb35rx_f.h"
  16
  17static void packet_came(struct ieee80211_hw *hw, char *pRxBufferAddress, int PacketSize)
  18{
  19        struct wbsoft_priv *priv = hw->priv;
  20        struct sk_buff *skb;
  21        struct ieee80211_rx_status rx_status = {0};
  22
  23        if (!priv->enabled)
  24                return;
  25
  26        skb = dev_alloc_skb(PacketSize);
  27        if (!skb) {
  28                printk("Not enough memory for packet, FIXME\n");
  29                return;
  30        }
  31
  32        memcpy(skb_put(skb, PacketSize),
  33               pRxBufferAddress,
  34               PacketSize);
  35
  36/*
  37        rx_status.rate = 10;
  38        rx_status.channel = 1;
  39        rx_status.freq = 12345;
  40        rx_status.phymode = MODE_IEEE80211B;
  41*/
  42
  43        memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
  44        ieee80211_rx_irqsafe(hw, skb);
  45}
  46
  47static void Wb35Rx_adjust(struct wb35_descriptor *pRxDes)
  48{
  49        u32 *   pRxBufferAddress;
  50        u32     DecryptionMethod;
  51        u32     i;
  52        u16     BufferSize;
  53
  54        DecryptionMethod = pRxDes->R01.R01_decryption_method;
  55        pRxBufferAddress = pRxDes->buffer_address[0];
  56        BufferSize = pRxDes->buffer_size[0];
  57
  58        // Adjust the last part of data. Only data left
  59        BufferSize -= 4; // For CRC-32
  60        if (DecryptionMethod)
  61                BufferSize -= 4;
  62        if (DecryptionMethod == 3) // For CCMP
  63                BufferSize -= 4;
  64
  65        // Adjust the IV field which after 802.11 header and ICV field.
  66        if (DecryptionMethod == 1) // For WEP
  67        {
  68                for( i=6; i>0; i-- )
  69                        pRxBufferAddress[i] = pRxBufferAddress[i-1];
  70                pRxDes->buffer_address[0] = pRxBufferAddress + 1;
  71                BufferSize -= 4; // 4 byte for IV
  72        }
  73        else if( DecryptionMethod ) // For TKIP and CCMP
  74        {
  75                for (i=7; i>1; i--)
  76                        pRxBufferAddress[i] = pRxBufferAddress[i-2];
  77                pRxDes->buffer_address[0] = pRxBufferAddress + 2;//Update the descriptor, shift 8 byte
  78                BufferSize -= 8; // 8 byte for IV + ICV
  79        }
  80        pRxDes->buffer_size[0] = BufferSize;
  81}
  82
  83static u16 Wb35Rx_indicate(struct ieee80211_hw *hw)
  84{
  85        struct wbsoft_priv *priv = hw->priv;
  86        struct hw_data * pHwData = &priv->sHwData;
  87        struct wb35_descriptor  RxDes;
  88        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
  89        u8 *            pRxBufferAddress;
  90        u16             PacketSize;
  91        u16             stmp, BufferSize, stmp2 = 0;
  92        u32             RxBufferId;
  93
  94        // Only one thread be allowed to run into the following
  95        do {
  96                RxBufferId = pWb35Rx->RxProcessIndex;
  97                if (pWb35Rx->RxOwner[ RxBufferId ]) //Owner by VM
  98                        break;
  99
 100                pWb35Rx->RxProcessIndex++;
 101                pWb35Rx->RxProcessIndex %= MAX_USB_RX_BUFFER_NUMBER;
 102
 103                pRxBufferAddress = pWb35Rx->pDRx;
 104                BufferSize = pWb35Rx->RxBufferSize[ RxBufferId ];
 105
 106                // Parse the bulkin buffer
 107                while (BufferSize >= 4) {
 108                        if ((cpu_to_le32(*(u32 *)pRxBufferAddress) & 0x0fffffff) == RX_END_TAG) //Is ending? 921002.9.a
 109                                break;
 110
 111                        // Get the R00 R01 first
 112                        RxDes.R00.value = le32_to_cpu(*(u32 *)pRxBufferAddress);
 113                        PacketSize = (u16)RxDes.R00.R00_receive_byte_count;
 114                        RxDes.R01.value = le32_to_cpu(*((u32 *)(pRxBufferAddress+4)));
 115                        // For new DMA 4k
 116                        if ((PacketSize & 0x03) > 0)
 117                                PacketSize -= 4;
 118
 119                        // Basic check for Rx length. Is length valid?
 120                        if (PacketSize > MAX_PACKET_SIZE) {
 121                                #ifdef _PE_RX_DUMP_
 122                                printk("Serious ERROR : Rx data size too long, size =%d\n", PacketSize);
 123                                #endif
 124
 125                                pWb35Rx->EP3vm_state = VM_STOP;
 126                                pWb35Rx->Ep3ErrorCount2++;
 127                                break;
 128                        }
 129
 130                        // Start to process Rx buffer
 131//                      RxDes.Descriptor_ID = RxBufferId; // Due to synchronous indicate, the field doesn't necessary to use.
 132                        BufferSize -= 8; //subtract 8 byte for 35's USB header length
 133                        pRxBufferAddress += 8;
 134
 135                        RxDes.buffer_address[0] = pRxBufferAddress;
 136                        RxDes.buffer_size[0] = PacketSize;
 137                        RxDes.buffer_number = 1;
 138                        RxDes.buffer_start_index = 0;
 139                        RxDes.buffer_total_size = RxDes.buffer_size[0];
 140                        Wb35Rx_adjust(&RxDes);
 141
 142                        packet_came(hw, pRxBufferAddress, PacketSize);
 143
 144                        // Move RxBuffer point to the next
 145                        stmp = PacketSize + 3;
 146                        stmp &= ~0x03; // 4n alignment
 147                        pRxBufferAddress += stmp;
 148                        BufferSize -= stmp;
 149                        stmp2 += stmp;
 150                }
 151
 152                // Reclaim resource
 153                pWb35Rx->RxOwner[ RxBufferId ] = 1;
 154        } while (true);
 155
 156        return stmp2;
 157}
 158
 159static void Wb35Rx(struct ieee80211_hw *hw);
 160
 161static void Wb35Rx_Complete(struct urb *urb)
 162{
 163        struct ieee80211_hw *hw = urb->context;
 164        struct wbsoft_priv *priv = hw->priv;
 165        struct hw_data * pHwData = &priv->sHwData;
 166        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
 167        u8 *            pRxBufferAddress;
 168        u32             SizeCheck;
 169        u16             BulkLength;
 170        u32             RxBufferId;
 171        R00_DESCRIPTOR  R00;
 172
 173        // Variable setting
 174        pWb35Rx->EP3vm_state = VM_COMPLETED;
 175        pWb35Rx->EP3VM_status = urb->status;//Store the last result of Irp
 176
 177        RxBufferId = pWb35Rx->CurrentRxBufferId;
 178
 179        pRxBufferAddress = pWb35Rx->pDRx;
 180        BulkLength = (u16)urb->actual_length;
 181
 182        // The IRP is completed
 183        pWb35Rx->EP3vm_state = VM_COMPLETED;
 184
 185        if (pHwData->SurpriseRemove || pHwData->HwStop) // Must be here, or RxBufferId is invalid
 186                goto error;
 187
 188        if (pWb35Rx->rx_halt)
 189                goto error;
 190
 191        // Start to process the data only in successful condition
 192        pWb35Rx->RxOwner[ RxBufferId ] = 0; // Set the owner to driver
 193        R00.value = le32_to_cpu(*(u32 *)pRxBufferAddress);
 194
 195        // The URB is completed, check the result
 196        if (pWb35Rx->EP3VM_status != 0) {
 197                #ifdef _PE_USB_STATE_DUMP_
 198                printk("EP3 IoCompleteRoutine return error\n");
 199                #endif
 200                pWb35Rx->EP3vm_state = VM_STOP;
 201                goto error;
 202        }
 203
 204        // 20060220 For recovering. check if operating in single USB mode
 205        if (!HAL_USB_MODE_BURST(pHwData)) {
 206                SizeCheck = R00.R00_receive_byte_count;  //20060926 anson's endian
 207                if ((SizeCheck & 0x03) > 0)
 208                        SizeCheck -= 4;
 209                SizeCheck = (SizeCheck + 3) & ~0x03;
 210                SizeCheck += 12; // 8 + 4 badbeef
 211                if ((BulkLength > 1600) ||
 212                        (SizeCheck > 1600) ||
 213                        (BulkLength != SizeCheck) ||
 214                        (BulkLength == 0)) { // Add for fail Urb
 215                        pWb35Rx->EP3vm_state = VM_STOP;
 216                        pWb35Rx->Ep3ErrorCount2++;
 217                }
 218        }
 219
 220        // Indicating the receiving data
 221        pWb35Rx->ByteReceived += BulkLength;
 222        pWb35Rx->RxBufferSize[ RxBufferId ] = BulkLength;
 223
 224        if (!pWb35Rx->RxOwner[ RxBufferId ])
 225                Wb35Rx_indicate(hw);
 226
 227        kfree(pWb35Rx->pDRx);
 228        // Do the next receive
 229        Wb35Rx(hw);
 230        return;
 231
 232error:
 233        pWb35Rx->RxOwner[ RxBufferId ] = 1; // Set the owner to hardware
 234        atomic_dec(&pWb35Rx->RxFireCounter);
 235        pWb35Rx->EP3vm_state = VM_STOP;
 236}
 237
 238// This function cannot reentrain
 239static void Wb35Rx(struct ieee80211_hw *hw)
 240{
 241        struct wbsoft_priv *priv = hw->priv;
 242        struct hw_data * pHwData = &priv->sHwData;
 243        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
 244        u8 *    pRxBufferAddress;
 245        struct urb *urb = pWb35Rx->RxUrb;
 246        int     retv;
 247        u32     RxBufferId;
 248
 249        //
 250        // Issuing URB
 251        //
 252        if (pHwData->SurpriseRemove || pHwData->HwStop)
 253                goto error;
 254
 255        if (pWb35Rx->rx_halt)
 256                goto error;
 257
 258        // Get RxBuffer's ID
 259        RxBufferId = pWb35Rx->RxBufferId;
 260        if (!pWb35Rx->RxOwner[RxBufferId]) {
 261                // It's impossible to run here.
 262                #ifdef _PE_RX_DUMP_
 263                printk("Rx driver fifo unavailable\n");
 264                #endif
 265                goto error;
 266        }
 267
 268        // Update buffer point, then start to bulkin the data from USB
 269        pWb35Rx->RxBufferId++;
 270        pWb35Rx->RxBufferId %= MAX_USB_RX_BUFFER_NUMBER;
 271
 272        pWb35Rx->CurrentRxBufferId = RxBufferId;
 273
 274        pWb35Rx->pDRx = kzalloc(MAX_USB_RX_BUFFER, GFP_ATOMIC);
 275        if (!pWb35Rx->pDRx) {
 276                printk("w35und: Rx memory alloc failed\n");
 277                goto error;
 278        }
 279        pRxBufferAddress = pWb35Rx->pDRx;
 280
 281        usb_fill_bulk_urb(urb, pHwData->WbUsb.udev,
 282                          usb_rcvbulkpipe(pHwData->WbUsb.udev, 3),
 283                          pRxBufferAddress, MAX_USB_RX_BUFFER,
 284                          Wb35Rx_Complete, hw);
 285
 286        pWb35Rx->EP3vm_state = VM_RUNNING;
 287
 288        retv = usb_submit_urb(urb, GFP_ATOMIC);
 289
 290        if (retv != 0) {
 291                printk("Rx URB sending error\n");
 292                goto error;
 293        }
 294        return;
 295
 296error:
 297        // VM stop
 298        pWb35Rx->EP3vm_state = VM_STOP;
 299        atomic_dec(&pWb35Rx->RxFireCounter);
 300}
 301
 302void Wb35Rx_start(struct ieee80211_hw *hw)
 303{
 304        struct wbsoft_priv *priv = hw->priv;
 305        struct hw_data * pHwData = &priv->sHwData;
 306        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
 307
 308        // Allow only one thread to run into the Wb35Rx() function
 309        if (atomic_inc_return(&pWb35Rx->RxFireCounter) == 1) {
 310                pWb35Rx->EP3vm_state = VM_RUNNING;
 311                Wb35Rx(hw);
 312        } else
 313                atomic_dec(&pWb35Rx->RxFireCounter);
 314}
 315
 316//=====================================================================================
 317static void Wb35Rx_reset_descriptor(  struct hw_data * pHwData )
 318{
 319        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
 320        u32     i;
 321
 322        pWb35Rx->ByteReceived = 0;
 323        pWb35Rx->RxProcessIndex = 0;
 324        pWb35Rx->RxBufferId = 0;
 325        pWb35Rx->EP3vm_state = VM_STOP;
 326        pWb35Rx->rx_halt = 0;
 327
 328        // Initial the Queue. The last buffer is reserved for used if the Rx resource is unavailable.
 329        for( i=0; i<MAX_USB_RX_BUFFER_NUMBER; i++ )
 330                pWb35Rx->RxOwner[i] = 1;
 331}
 332
 333unsigned char Wb35Rx_initial(struct hw_data * pHwData)
 334{
 335        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
 336
 337        // Initial the Buffer Queue
 338        Wb35Rx_reset_descriptor( pHwData );
 339
 340        pWb35Rx->RxUrb = usb_alloc_urb(0, GFP_ATOMIC);
 341        return (!!pWb35Rx->RxUrb);
 342}
 343
 344void Wb35Rx_stop(struct hw_data * pHwData)
 345{
 346        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
 347
 348        // Canceling the Irp if already sends it out.
 349        if (pWb35Rx->EP3vm_state == VM_RUNNING) {
 350                usb_unlink_urb( pWb35Rx->RxUrb ); // Only use unlink, let Wb35Rx_destroy to free them
 351                #ifdef _PE_RX_DUMP_
 352                printk("EP3 Rx stop\n");
 353                #endif
 354        }
 355}
 356
 357// Needs process context
 358void Wb35Rx_destroy(struct hw_data * pHwData)
 359{
 360        struct wb35_rx *pWb35Rx = &pHwData->Wb35Rx;
 361
 362        do {
 363                msleep(10); // Delay for waiting function enter 940623.1.a
 364        } while (pWb35Rx->EP3vm_state != VM_STOP);
 365        msleep(10); // Delay for waiting function exit 940623.1.b
 366
 367        if (pWb35Rx->RxUrb)
 368                usb_free_urb( pWb35Rx->RxUrb );
 369        #ifdef _PE_RX_DUMP_
 370        printk("Wb35Rx_destroy OK\n");
 371        #endif
 372}
 373
 374