text: #include "headers.h"
  
  static void handle_control_packet(struct bcm_interface_adapter *interface,
  				  struct bcm_mini_adapter *ad,
  				  struct bcm_leader *leader,
  				  struct sk_buff *skb,
  				  struct urb *urb)
  {
  	BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL,
  			"Received control pkt...");
  	*(PUSHORT)skb->data = leader->Status;
  	memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
  	       (sizeof(struct bcm_leader)), leader->PLength);
  	skb->len = leader->PLength + sizeof(USHORT);
  
  	spin_lock(&ad->control_queue_lock);
  	ENQUEUEPACKET(ad->RxControlHead, ad->RxControlTail, skb);
  	spin_unlock(&ad->control_queue_lock);
  
  	atomic_inc(&ad->cntrlpktCnt);
  	wake_up(&ad->process_rx_cntrlpkt);
  }
  
  static void format_eth_hdr_to_stack(struct bcm_interface_adapter *interface,
  				    struct bcm_mini_adapter *ad,
  				    struct bcm_leader *p_leader,
  				    struct sk_buff *skb,
  				    struct urb *urb,
  				    UINT ui_index,
  				    int queue_index,
  				    bool b_header_supression_endabled)
  {
  	/*
  	 * Data Packet, Format a proper Ethernet Header
  	 * and give it to the stack
  	 */
  	BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA,
  			DBG_LVL_ALL, "Received Data pkt...");
  	skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
  	memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer +
  	       sizeof(struct bcm_leader), p_leader->PLength);
  	skb->dev = ad->dev;
  
  	/* currently skb->len has extra ETH_HLEN bytes in the beginning */
  	skb_put(skb, p_leader->PLength + ETH_HLEN);
  	ad->PackInfo[queue_index].uiTotalRxBytes += p_leader->PLength;
  	ad->PackInfo[queue_index].uiThisPeriodRxBytes += p_leader->PLength;
  	BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX, RX_DATA,
  			DBG_LVL_ALL, "Received Data pkt of len :0x%X",
  			p_leader->PLength);
  
  	if (netif_running(ad->dev)) {
  		/* Moving ahead by ETH_HLEN to the data ptr as received from FW */
  		skb_pull(skb, ETH_HLEN);
  		PHSReceive(ad, p_leader->Vcid, skb, &skb->len,
  			   NULL, b_header_supression_endabled);
  
  		if (!ad->PackInfo[queue_index].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;
  			p_leader->PLength += ETH_HLEN;
  		}
  
  		skb->protocol = eth_type_trans(skb, ad->dev);
  		netif_rx(skb);
  	} else {
  		BCM_DEBUG_PRINT(interface->psAdapter, DBG_TYPE_RX,
  				RX_DATA, DBG_LVL_ALL,
  				"i/f not up hance freeing SKB...");
  		dev_kfree_skb(skb);
  	}
  
  	++ad->dev->stats.rx_packets;
  	ad->dev->stats.rx_bytes += p_leader->PLength;
  
  	for (ui_index = 0; ui_index < MIBS_MAX_HIST_ENTRIES; ui_index++) {
  		if ((p_leader->PLength <=
  		    MIBS_PKTSIZEHIST_RANGE*(ui_index+1)) &&
  			(p_leader->PLength > MIBS_PKTSIZEHIST_RANGE*(ui_index)))
  
  			ad->aRxPktSizeHist[ui_index]++;
  	}
  }
  
  static int SearchVcid(struct bcm_mini_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;
  
  }
  
  
  static struct bcm_usb_rcb *
  GetBulkInRcb(struct bcm_interface_adapter *psIntfAdapter)
  {
  	struct bcm_usb_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 available for receive (BULK IN- end point)*/
  static void read_bulk_callback(struct urb *urb)
  {
  	struct sk_buff *skb = NULL;
  	bool bHeaderSupressionEnabled = false;
  	int QueueIndex = NO_OF_QUEUES + 1;
  	UINT uiIndex = 0;
  	struct bcm_usb_rcb *pRcb = (struct bcm_usb_rcb *)urb->context;
  	struct bcm_interface_adapter *psIntfAdapter = pRcb->psIntfAdapter;
  	struct bcm_mini_adapter *Adapter = psIntfAdapter->psAdapter;
  	struct bcm_leader *pLeader = urb->transfer_buffer;
  
  	if (unlikely(netif_msg_rx_status(Adapter)))
  		pr_info(PFX "%s: rx urb status %d length %d\n",
  			Adapter->dev->name, urb->status, urb->actual_length);
  
  	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) {
  		if (netif_msg_rx_err(Adapter))
  			pr_info(PFX "%s: corrupted leader length...%d\n",
  				Adapter->dev->name, pLeader->PLength);
  		++Adapter->dev->stats.rx_dropped;
  		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);
  	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))) {
  		handle_control_packet(psIntfAdapter, Adapter, pLeader, skb,
  				      urb);
  	} else {
  		format_eth_hdr_to_stack(psIntfAdapter, Adapter, pLeader, skb,
  					urb, uiIndex, QueueIndex,
  					bHeaderSupressionEnabled);
  	}
  	Adapter->PrevNumRecvDescs++;
  	pRcb->bUsed = false;
  	atomic_dec(&psIntfAdapter->uNumRcbUsed);
  }
  
  static int ReceiveRcb(struct bcm_interface_adapter *psIntfAdapter,
  		      struct bcm_usb_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 Receiving
  						data packet/control packets from the device.
  
  Input parameters:		IN struct bcm_mini_adapter *Adapter   - Miniport Adapter Context
  
  
  
  Return:				TRUE  - If Rx was successful.
  					Other - If an error occurred.
  */
  
  bool InterfaceRx(struct bcm_interface_adapter *psIntfAdapter)
  {
  	USHORT RxDescCount = NUM_RX_DESC -
  		atomic_read(&psIntfAdapter->uNumRcbUsed);
  
  	struct bcm_usb_rcb *pRcb = NULL;
  
  	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;
  		}
  		ReceiveRcb(psIntfAdapter, pRcb);
  		RxDescCount--;
  	}
  	return TRUE;
  }
  
  