Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.37 555 lines 16 kB view raw
1/** 2@file Transmit.c 3@defgroup tx_functions Transmission 4@section Queueing 5@dot 6digraph transmit1 { 7node[shape=box] 8edge[weight=5;color=red] 9bcm_transmit->reply_to_arp_request[label="ARP"] 10bcm_transmit->GetPacketQueueIndex[label="IP Packet"] 11GetPacketQueueIndex->IpVersion4[label="IPV4"] 12GetPacketQueueIndex->IpVersion6[label="IPV6"] 13} 14 15@enddot 16 17@section De-Queueing 18@dot 19digraph transmit2 { 20node[shape=box] 21edge[weight=5;color=red] 22interrupt_service_thread->transmit_packets 23tx_pkt_hdler->transmit_packets 24transmit_packets->CheckAndSendPacketFromIndex 25transmit_packets->UpdateTokenCount 26CheckAndSendPacketFromIndex->PruneQueue 27CheckAndSendPacketFromIndex->IsPacketAllowedForFlow 28CheckAndSendPacketFromIndex->SendControlPacket[label="control pkt"] 29SendControlPacket->bcm_cmd53 30CheckAndSendPacketFromIndex->SendPacketFromQueue[label="data pkt"] 31SendPacketFromQueue->SetupNextSend->bcm_cmd53 32} 33@enddot 34*/ 35 36#include "headers.h" 37 38/******************************************************************* 39* Function - bcm_transmit() 40* 41* Description - This is the main transmit function for our virtual 42* interface(veth0). It handles the ARP packets. It 43* clones this packet and then Queue it to a suitable 44* Queue. Then calls the transmit_packet(). 45* 46* Parameter - skb - Pointer to the socket buffer structure 47* dev - Pointer to the virtual net device structure 48* 49* Returns - zero (success) or -ve value (failure) 50* 51*********************************************************************/ 52 53INT bcm_transmit(struct sk_buff *skb, /**< skb */ 54 struct net_device *dev /**< net device pointer */ 55 ) 56{ 57 PMINI_ADAPTER Adapter = NULL; 58 USHORT qindex=0; 59 struct timeval tv; 60 UINT pkt_type = 0; 61 UINT calltransmit = 0; 62 63 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "\n%s====>\n",__FUNCTION__); 64 65 memset(&tv, 0, sizeof(tv)); 66 /* Check for valid parameters */ 67 if(skb == NULL || dev==NULL) 68 { 69 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL, "Got NULL skb or dev\n"); 70 return -EINVAL; 71 } 72 73 Adapter = GET_BCM_ADAPTER(dev); 74 if(!Adapter) 75 { 76 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Got Invalid Adapter\n"); 77 return -EINVAL; 78 } 79 if(Adapter->device_removed == TRUE || !Adapter->LinkUpStatus) 80 { 81 if(!netif_queue_stopped(dev)) { 82 netif_carrier_off(dev); 83 netif_stop_queue(dev); 84 } 85 return STATUS_FAILURE; 86 } 87 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Packet size : %d\n", skb->len); 88 89 /*Add Ethernet CS check here*/ 90 if(Adapter->TransferMode == IP_PACKET_ONLY_MODE ) 91 { 92 pkt_type = ntohs(*(PUSHORT)(skb->data + 12)); 93 /* Get the queue index where the packet is to be queued */ 94 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Getting the Queue Index....."); 95 96 qindex = GetPacketQueueIndex(Adapter,skb); 97 98 if((SHORT)INVALID_QUEUE_INDEX==(SHORT)qindex) 99 { 100 if(pkt_type == ETH_ARP_FRAME) 101 { 102 /* 103 Reply directly to ARP request packet 104 ARP Spoofing only if NO ETH CS rule matches for it 105 */ 106 BCM_DEBUG_PRINT (Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ARP OPCODE = %02x", 107 108 (*(PUCHAR)(skb->data + 21))); 109 110 reply_to_arp_request(skb); 111 112 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX,TX_OSAL_DBG, DBG_LVL_ALL,"After reply_to_arp_request \n"); 113 114 } 115 else 116 { 117 BCM_DEBUG_PRINT (Adapter, DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, 118 "Invalid queue index, dropping pkt\n"); 119 120 bcm_kfree_skb(skb); 121 } 122 return STATUS_SUCCESS; 123 } 124 125 if(Adapter->PackInfo[qindex].uiCurrentPacketsOnHost >= SF_MAX_ALLOWED_PACKETS_TO_BACKUP) 126 { 127 atomic_inc(&Adapter->TxDroppedPacketCount); 128 bcm_kfree_skb(skb); 129 return STATUS_SUCCESS; 130 } 131 132 /* Now Enqueue the packet */ 133 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "bcm_transmit Enqueueing the Packet To Queue %d",qindex); 134 spin_lock(&Adapter->PackInfo[qindex].SFQueueLock); 135 Adapter->PackInfo[qindex].uiCurrentBytesOnHost += skb->len; 136 Adapter->PackInfo[qindex].uiCurrentPacketsOnHost++; 137 138 *((B_UINT32 *)skb->cb + SKB_CB_LATENCY_OFFSET ) = jiffies; 139 ENQUEUEPACKET(Adapter->PackInfo[qindex].FirstTxQueue, 140 Adapter->PackInfo[qindex].LastTxQueue, skb); 141 atomic_inc(&Adapter->TotalPacketCount); 142 spin_unlock(&Adapter->PackInfo[qindex].SFQueueLock); 143 do_gettimeofday(&tv); 144 145 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL,"ENQ: \n"); 146 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "Pkt Len = %d, sec: %ld, usec: %ld\n", 147 (skb->len-ETH_HLEN), tv.tv_sec, tv.tv_usec); 148 149#ifdef BCM_SHM_INTERFACE 150 spin_lock(&Adapter->txtransmitlock); 151 if(Adapter->txtransmit_running == 0) 152 { 153 Adapter->txtransmit_running = 1; 154 calltransmit = 1; 155 } 156 else 157 calltransmit = 0; 158 159 spin_unlock(&Adapter->txtransmitlock); 160#endif 161 if(calltransmit == 1) 162 transmit_packets(Adapter); 163 else 164 { 165 if(!atomic_read(&Adapter->TxPktAvail)) 166 { 167 atomic_set(&Adapter->TxPktAvail, 1); 168#ifdef BCM_SHM_INTERFACE 169 virtual_mail_box_interrupt(); 170#endif 171 wake_up(&Adapter->tx_packet_wait_queue); 172 } 173 } 174 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_OSAL_DBG, DBG_LVL_ALL, "<===="); 175 } 176 else 177 bcm_kfree_skb(skb); 178 179 return STATUS_SUCCESS; 180} 181 182 183/** 184@ingroup ctrl_pkt_functions 185This function dispatches control packet to the h/w interface 186@return zero(success) or -ve value(failure) 187*/ 188INT SendControlPacket(PMINI_ADAPTER Adapter, /**<Logical Adapter*/ 189 char *pControlPacket/**<Control Packet*/ 190 ) 191{ 192 PLEADER PLeader = NULL; 193 struct timeval tv; 194 memset(&tv, 0, sizeof(tv)); 195 196 197 198 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "========>"); 199 200 PLeader=(PLEADER)pControlPacket; 201 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Tx"); 202 if(!pControlPacket || !Adapter) 203 { 204 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Got NULL Control Packet or Adapter"); 205 return STATUS_FAILURE; 206 } 207 if((atomic_read( &Adapter->CurrNumFreeTxDesc ) < 208 ((PLeader->PLength-1)/MAX_DEVICE_DESC_SIZE)+1)) 209 { 210 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "NO FREE DESCRIPTORS TO SEND CONTROL PACKET"); 211 if(Adapter->bcm_jiffies == 0) 212 { 213 Adapter->bcm_jiffies = jiffies; 214 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "UPDATED TIME(hex): %lu", 215 Adapter->bcm_jiffies); 216 } 217 return STATUS_FAILURE; 218 } 219 220 /* Update the netdevice statistics */ 221 /* Dump Packet */ 222 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Status: %x", PLeader->Status); 223 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader VCID: %x",PLeader->Vcid); 224 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Leader Length: %x",PLeader->PLength); 225 if(Adapter->device_removed) 226 return 0; 227#ifndef BCM_SHM_INTERFACE 228 Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 229 pControlPacket, (PLeader->PLength + LEADER_SIZE)); 230#else 231 tx_pkts_to_firmware(pControlPacket,(PLeader->PLength + LEADER_SIZE),1); 232 233 if(PLeader->Status==IDLE_MESSAGE) 234 { 235 if(((CONTROL_MESSAGE*)PLeader)->szData[0] == GO_TO_IDLE_MODE_PAYLOAD && 236 ((CONTROL_MESSAGE*)PLeader)->szData[1] == TARGET_CAN_GO_TO_IDLE_MODE) 237 { 238 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Idle Mode Ack Sent to the Device\n"); 239 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Host Entering into Idle Mode\n"); 240 do_gettimeofday(&tv); 241 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); 242 if(Adapter->bDoSuspend != TRUE) 243 { 244 Adapter->IdleMode = TRUE; 245 Adapter->bPreparingForLowPowerMode = FALSE ; 246 } 247 } 248 } 249 if((PLeader->Status == LINK_UP_CONTROL_REQ) && 250 ((PUCHAR)pControlPacket)[sizeof(LEADER)] == LINK_UP_ACK && 251 ((PUCHAR)pControlPacket)[sizeof(LEADER)+1] == 252 LINK_SHUTDOWN_REQ_FROM_FIRMWARE && 253 ((PUCHAR)pControlPacket)[sizeof(LEADER)+2] == SHUTDOWN_ACK_FROM_DRIVER) 254 { 255 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "Shut Down ACK Sent and Host entering Shut State \n"); 256 if(Adapter->bDoSuspend != TRUE) 257 { 258 Adapter->bShutStatus = TRUE; 259 Adapter->bPreparingForLowPowerMode = FALSE; 260 Adapter->bTriedToWakeUpFromlowPowerMode = FALSE; 261 } 262 263 } 264#endif 265 266 ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_packets++; 267 ((PLINUX_DEP_DATA)Adapter->pvOsDepData)->netstats.tx_bytes+= 268 PLeader->PLength; 269 atomic_dec(&Adapter->CurrNumFreeTxDesc); 270 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_CONTROL, DBG_LVL_ALL, "<========="); 271 return STATUS_SUCCESS; 272} 273static LEADER Leader={0}; 274/** 275@ingroup tx_functions 276This function despatches the IP packets with the given vcid 277to the target via the host h/w interface. 278@return zero(success) or -ve value(failure) 279*/ 280INT SetupNextSend(PMINI_ADAPTER Adapter, /**<Logical Adapter*/ 281 struct sk_buff *Packet, /**<data buffer*/ 282 USHORT Vcid) /**<VCID for this packet*/ 283{ 284 int status=0; 285#ifdef GDMA_INTERFACE 286 int dontfree = 0; 287#endif 288 BOOLEAN bHeaderSupressionEnabled = FALSE; 289 B_UINT16 uiClassifierRuleID; 290 int QueueIndex = NO_OF_QUEUES + 1; 291 292 if(!Adapter || !Packet) 293 { 294 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Got NULL Adapter or Packet"); 295 return -EINVAL; 296 } 297 if(Packet->len > MAX_DEVICE_DESC_SIZE) 298 { 299 status = STATUS_FAILURE; 300 goto errExit; 301 } 302 303 /* Get the Classifier Rule ID */ 304 uiClassifierRuleID = *((UINT32*) (Packet->cb)+SKB_CB_CLASSIFICATION_OFFSET); 305 QueueIndex = SearchVcid( Adapter,Vcid); 306 if(QueueIndex < NO_OF_QUEUES) 307 { 308 bHeaderSupressionEnabled = 309 Adapter->PackInfo[QueueIndex].bHeaderSuppressionEnabled; 310 bHeaderSupressionEnabled = 311 bHeaderSupressionEnabled & Adapter->bPHSEnabled; 312 } 313 if(Adapter->device_removed) 314 { 315 status = STATUS_FAILURE; 316 goto errExit; 317 } 318 319 status = PHSTransmit(Adapter, &Packet, Vcid, uiClassifierRuleID, bHeaderSupressionEnabled, 320 (UINT *)&Packet->len, Adapter->PackInfo[QueueIndex].bEthCSSupport); 321 322 if(status != STATUS_SUCCESS) 323 { 324 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "PHS Transmit failed..\n"); 325 goto errExit; 326 } 327 328 Leader.Vcid = Vcid; 329 330 if(TCP_ACK == *((UINT32*) (Packet->cb) + SKB_CB_TCPACK_OFFSET )) 331 { 332 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Sending TCP ACK\n"); 333 Leader.Status = LEADER_STATUS_TCP_ACK; 334 } 335 else 336 { 337 Leader.Status = LEADER_STATUS; 338 } 339 340 if(Adapter->PackInfo[QueueIndex].bEthCSSupport) 341 { 342 Leader.PLength = Packet->len; 343 if(skb_headroom(Packet) < LEADER_SIZE) 344 { 345 if((status = skb_cow(Packet,LEADER_SIZE))) 346 { 347 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL,"bcm_transmit : Failed To Increase headRoom\n"); 348 goto errExit; 349 } 350 } 351 skb_push(Packet, LEADER_SIZE); 352 memcpy(Packet->data, &Leader, LEADER_SIZE); 353 } 354 355 else 356 { 357 Leader.PLength = Packet->len - ETH_HLEN; 358 memcpy((LEADER*)skb_pull(Packet, (ETH_HLEN - LEADER_SIZE)), &Leader, LEADER_SIZE); 359 } 360 361 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Packet->len = %d", Packet->len); 362 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Vcid = %d", Vcid); 363 364#ifndef BCM_SHM_INTERFACE 365 status = Adapter->interface_transmit(Adapter->pvInterfaceAdapter, 366 Packet->data, (Leader.PLength + LEADER_SIZE)); 367#else 368 status = tx_pkts_to_firmware(Packet,Packet->len,0); 369#endif 370 if(status) 371 { 372 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, NEXT_SEND, DBG_LVL_ALL, "Tx Failed..\n"); 373 } 374 else 375 { 376 Adapter->PackInfo[QueueIndex].uiTotalTxBytes += Leader.PLength; 377 atomic_add(Leader.PLength, &Adapter->GoodTxByteCount); 378 atomic_inc(&Adapter->TxTotalPacketCount); 379#ifdef GDMA_INTERFACE 380 dontfree = 1; 381#endif 382 } 383 384 atomic_dec(&Adapter->CurrNumFreeTxDesc); 385 386errExit: 387 388 if(STATUS_SUCCESS == status) 389 { 390 Adapter->PackInfo[QueueIndex].uiCurrentTokenCount -= Leader.PLength << 3; 391 Adapter->PackInfo[QueueIndex].uiSentBytes += (Packet->len); 392 Adapter->PackInfo[QueueIndex].uiSentPackets++; 393 Adapter->PackInfo[QueueIndex].NumOfPacketsSent++; 394 395 atomic_dec(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount); 396#ifdef BCM_SHM_INTERFACE 397 if(atomic_read(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount) < 0) 398 { 399 atomic_set(&Adapter->PackInfo[QueueIndex].uiPerSFTxResourceCount, 0); 400 } 401#endif 402 Adapter->PackInfo[QueueIndex].uiThisPeriodSentBytes += Leader.PLength; 403 } 404 405 406#ifdef GDMA_INTERFACE 407 if(!dontfree){ 408 bcm_kfree_skb(Packet); 409 } 410#else 411 bcm_kfree_skb(Packet); 412#endif 413 return status; 414} 415 416/** 417@ingroup tx_functions 418Transmit thread 419*/ 420int tx_pkt_handler(PMINI_ADAPTER Adapter /**< pointer to adapter object*/ 421 ) 422{ 423#ifndef BCM_SHM_INTERFACE 424 int status = 0; 425#endif 426 427 UINT calltransmit = 1; 428 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Entring to wait for signal from the interrupt service thread!Adapter = %p",Adapter); 429 430 431 while(1) 432 { 433 if(Adapter->LinkUpStatus){ 434 wait_event_timeout(Adapter->tx_packet_wait_queue, 435 ((atomic_read(&Adapter->TxPktAvail) && 436 (MINIMUM_PENDING_DESCRIPTORS < 437 atomic_read(&Adapter->CurrNumFreeTxDesc)) && 438 (Adapter->device_removed == FALSE))) || 439 (1 == Adapter->downloadDDR) || kthread_should_stop() 440#ifndef BCM_SHM_INTERFACE 441 || (TRUE == Adapter->bEndPointHalted) 442#endif 443 , msecs_to_jiffies(10)); 444 } 445 else{ 446 wait_event(Adapter->tx_packet_wait_queue, 447 ((atomic_read(&Adapter->TxPktAvail) && 448 (MINIMUM_PENDING_DESCRIPTORS < 449 atomic_read(&Adapter->CurrNumFreeTxDesc)) && 450 (Adapter->device_removed == FALSE))) || 451 (1 == Adapter->downloadDDR) || kthread_should_stop() 452#ifndef BCM_SHM_INTERFACE 453 || (TRUE == Adapter->bEndPointHalted) 454#endif 455 ); 456 } 457 458 if(kthread_should_stop() || Adapter->device_removed) 459 { 460 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Exiting the tx thread..\n"); 461 Adapter->transmit_packet_thread = NULL; 462 return 0; 463 } 464 465#ifndef BCM_SHM_INTERFACE 466 467 if(Adapter->downloadDDR == 1) 468 { 469 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Downloading DDR Settings\n"); 470 Adapter->downloadDDR +=1; 471 status = download_ddr_settings(Adapter); 472 if(status) 473 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "DDR DOWNLOAD FAILED!\n"); 474 continue; 475 } 476 477 //Check end point for halt/stall. 478 if(Adapter->bEndPointHalted == TRUE) 479 { 480 Bcm_clear_halt_of_endpoints(Adapter); 481 Adapter->bEndPointHalted = FALSE; 482 StartInterruptUrb((PS_INTERFACE_ADAPTER)(Adapter->pvInterfaceAdapter)); 483 } 484 485 if(Adapter->LinkUpStatus && !Adapter->IdleMode) 486 { 487 if(atomic_read(&Adapter->TotalPacketCount)) 488 { 489 update_per_sf_desc_cnts(Adapter); 490 } 491 } 492#endif 493 494 if( atomic_read(&Adapter->CurrNumFreeTxDesc) && 495 Adapter->LinkStatus == SYNC_UP_REQUEST && 496 !Adapter->bSyncUpRequestSent) 497 { 498 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Calling LinkMessage"); 499 LinkMessage(Adapter); 500 } 501 502 if((Adapter->IdleMode || Adapter->bShutStatus) && atomic_read(&Adapter->TotalPacketCount)) 503 { 504 BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "Device in Low Power mode...waking up"); 505 Adapter->usIdleModePattern = ABORT_IDLE_MODE; 506 Adapter->bWakeUpDevice = TRUE; 507 wake_up(&Adapter->process_rx_cntrlpkt); 508 } 509 510#ifdef BCM_SHM_INTERFACE 511 spin_lock_bh(&Adapter->txtransmitlock); 512 if(Adapter->txtransmit_running == 0) 513 { 514 Adapter->txtransmit_running = 1; 515 calltransmit = 1; 516 } 517 else 518 calltransmit = 0; 519 spin_unlock_bh(&Adapter->txtransmitlock); 520#endif 521 522 if(calltransmit) 523 transmit_packets(Adapter); 524 525 atomic_set(&Adapter->TxPktAvail, 0); 526 } 527 return 0; 528} 529 530#ifdef BCM_SHM_INTERFACE 531extern PMINI_ADAPTER psAdaptertest; 532void virtual_mail_box_interrupt(void) 533{ 534 535#ifndef GDMA_INTERFACE 536 PUINT ptr = (PUINT)CPE_VIRTUAL_MAILBOX_REG; 537 UINT intval = (UINT)((*ptr & 0xFF00) >> 8); 538 if (intval != 0) 539 { 540 atomic_set(&psAdaptertest->CurrNumFreeTxDesc, intval); 541 atomic_set (&psAdaptertest->uiMBupdate, TRUE); 542 543 //make it to 0 544 *ptr = *ptr & 0xffff00ff; 545 } 546#endif 547} 548unsigned int total_tx_pkts_pending(void) 549{ 550 return atomic_read(&psAdaptertest->TotalPacketCount); 551} 552 553#endif 554 555