1/******************************************************************************* 2 * Agere Systems Inc. 3 * Wireless device driver for Linux (wlags49). 4 * 5 * Copyright (c) 1998-2003 Agere Systems Inc. 6 * All rights reserved. 7 * http://www.agere.com 8 * 9 * Initially developed by TriplePoint, Inc. 10 * http://www.triplepoint.com 11 * 12 *------------------------------------------------------------------------------ 13 * 14 * This file contains processing and initialization specific to PCI/miniPCI 15 * devices. 16 * 17 *------------------------------------------------------------------------------ 18 * 19 * SOFTWARE LICENSE 20 * 21 * This software is provided subject to the following terms and conditions, 22 * which you should read carefully before using the software. Using this 23 * software indicates your acceptance of these terms and conditions. If you do 24 * not agree with these terms and conditions, do not use the software. 25 * 26 * Copyright � 2003 Agere Systems Inc. 27 * All rights reserved. 28 * 29 * Redistribution and use in source or binary forms, with or without 30 * modifications, are permitted provided that the following conditions are met: 31 * 32 * . Redistributions of source code must retain the above copyright notice, this 33 * list of conditions and the following Disclaimer as comments in the code as 34 * well as in the documentation and/or other materials provided with the 35 * distribution. 36 * 37 * . Redistributions in binary form must reproduce the above copyright notice, 38 * this list of conditions and the following Disclaimer in the documentation 39 * and/or other materials provided with the distribution. 40 * 41 * . Neither the name of Agere Systems Inc. nor the names of the contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * Disclaimer 46 * 47 * THIS SOFTWARE IS PROVIDED �AS IS� AND ANY EXPRESS OR IMPLIED WARRANTIES, 48 * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF 49 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ANY 50 * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN 51 * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY 52 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 54 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 55 * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 57 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 58 * DAMAGE. 59 * 60 ******************************************************************************/ 61 62/******************************************************************************* 63 * include files 64 ******************************************************************************/ 65#include <wireless/wl_version.h> 66 67#include <linux/module.h> 68#include <linux/kernel.h> 69#include <linux/errno.h> 70#include <linux/pci.h> 71#include <linux/init.h> 72#include <linux/sched.h> 73#include <linux/ptrace.h> 74#include <linux/ctype.h> 75#include <linux/string.h> 76//#include <linux/timer.h> 77#include <linux/interrupt.h> 78#include <linux/in.h> 79#include <linux/delay.h> 80#include <asm/system.h> 81#include <asm/io.h> 82#include <asm/irq.h> 83#include <asm/bitops.h> 84#include <asm/uaccess.h> 85 86#include <linux/ethtool.h> 87#include <linux/netdevice.h> 88#include <linux/etherdevice.h> 89#include <linux/skbuff.h> 90#include <linux/if_arp.h> 91#include <linux/ioport.h> 92 93#include <hcf/debug.h> 94 95#include <hcf.h> 96#include <dhf.h> 97#include <hcfdef.h> 98 99#include <wireless/wl_if.h> 100#include <wireless/wl_internal.h> 101#include <wireless/wl_util.h> 102#include <wireless/wl_main.h> 103#include <wireless/wl_netdev.h> 104#include <wireless/wl_pci.h> 105 106 107/******************************************************************************* 108 * global variables 109 ******************************************************************************/ 110#if DBG 111extern dbg_info_t *DbgInfo; 112#endif // DBG 113 114/* define the PCI device Table Cardname and id tables */ 115enum hermes_pci_versions { 116 CH_Agere_Systems_Mini_PCI_V1 = 0, 117}; 118 119static struct pci_device_id wl_pci_tbl[] __devinitdata = { 120 { PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_0, 121 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 }, 122 { PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_1, 123 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 }, 124 { PCI_VENDOR_ID_WL_LKM, PCI_DEVICE_ID_WL_LKM_2, 125 PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_Agere_Systems_Mini_PCI_V1 }, 126 127 { } /* Terminating entry */ 128}; 129 130MODULE_DEVICE_TABLE(pci, wl_pci_tbl); 131 132/******************************************************************************* 133 * function prototypes 134 ******************************************************************************/ 135int __devinit wl_pci_probe( struct pci_dev *pdev, 136 const struct pci_device_id *ent ); 137void __devexit wl_pci_remove(struct pci_dev *pdev); 138int wl_pci_setup( struct pci_dev *pdev ); 139void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev ); 140 141#ifdef ENABLE_DMA 142int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp ); 143int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp ); 144int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp, 145 DESC_STRCT **desc ); 146int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp, 147 DESC_STRCT **desc ); 148int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp, 149 DESC_STRCT **desc ); 150int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp, 151 DESC_STRCT **desc ); 152int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, 153 DESC_STRCT **desc, int size ); 154int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, 155 DESC_STRCT **desc ); 156int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp, 157 DESC_STRCT **desc ); 158int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp, 159 DESC_STRCT **desc ); 160int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp, 161 DESC_STRCT *desc, int size ); 162int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp, 163 DESC_STRCT *desc ); 164 165void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp ); 166#endif // ENABLE_DMA 167 168/******************************************************************************* 169 * PCI module function registration 170 ******************************************************************************/ 171static struct pci_driver wl_driver = 172{ 173 name: MODULE_NAME, 174 id_table: wl_pci_tbl, 175 probe: wl_pci_probe, 176 remove: __devexit_p(wl_pci_remove), 177 suspend: NULL, 178 resume: NULL, 179}; 180 181/******************************************************************************* 182 * wl_adapter_init_module() 183 ******************************************************************************* 184 * 185 * DESCRIPTION: 186 * 187 * Called by init_module() to perform PCI-specific driver initialization. 188 * 189 * PARAMETERS: 190 * 191 * N/A 192 * 193 * RETURNS: 194 * 195 * 0 196 * 197 ******************************************************************************/ 198int wl_adapter_init_module( void ) 199{ 200 int result; 201 /*------------------------------------------------------------------------*/ 202 203 DBG_FUNC( "wl_adapter_init_module()" ); 204 DBG_ENTER( DbgInfo ); 205 DBG_TRACE( DbgInfo, "wl_adapter_init_module() -- PCI\n" ); 206 207 result = pci_register_driver( &wl_driver ); //;?replace with pci_module_init, Rubini pg 490 208 //;? why not do something with the result 209 210 DBG_LEAVE( DbgInfo ); 211 return 0; 212} // wl_adapter_init_module 213/*============================================================================*/ 214 215/******************************************************************************* 216 * wl_adapter_cleanup_module() 217 ******************************************************************************* 218 * 219 * DESCRIPTION: 220 * 221 * Called by cleanup_module() to perform PCI-specific driver cleanup. 222 * 223 * PARAMETERS: 224 * 225 * N/A 226 * 227 * RETURNS: 228 * 229 * N/A 230 * 231 ******************************************************************************/ 232void wl_adapter_cleanup_module( void ) 233{ 234 //;?how comes wl_adapter_cleanup_module is located in a seemingly pci specific module 235 DBG_FUNC( "wl_adapter_cleanup_module" ); 236 DBG_ENTER( DbgInfo ); 237 238 //;?DBG_TRACE below feels like nearly redundant in the light of DBG_ENTER above 239 DBG_TRACE( DbgInfo, "wl_adapter_cleanup_module() -- PCI\n" ); 240 241 pci_unregister_driver( &wl_driver ); 242 243 DBG_LEAVE( DbgInfo ); 244 return; 245} // wl_adapter_cleanup_module 246/*============================================================================*/ 247 248/******************************************************************************* 249 * wl_adapter_insert() 250 ******************************************************************************* 251 * 252 * DESCRIPTION: 253 * 254 * Called by wl_pci_probe() to continue the process of device insertion. 255 * 256 * PARAMETERS: 257 * 258 * dev - a pointer to the device's net_device structure 259 * 260 * RETURNS: 261 * 262 * TRUE or FALSE 263 * 264 ******************************************************************************/ 265int wl_adapter_insert( struct net_device *dev ) 266{ 267 int result = FALSE; 268 /*------------------------------------------------------------------------*/ 269 270 DBG_FUNC( "wl_adapter_insert" ); 271 DBG_ENTER( DbgInfo ); 272 273 DBG_TRACE( DbgInfo, "wl_adapter_insert() -- PCI\n" ); 274 275 if( dev == NULL ) { 276 DBG_ERROR( DbgInfo, "net_device pointer is NULL!!!\n" ); 277 } else if( dev->priv == NULL ) { 278 DBG_ERROR( DbgInfo, "wl_private pointer is NULL!!!\n" ); 279 } else if( wl_insert( dev ) ) { /* Perform remaining device initialization */ 280 result = TRUE; 281 } else { 282 DBG_TRACE( DbgInfo, "wl_insert() FAILED\n" ); 283 } 284 DBG_LEAVE( DbgInfo ); 285 return result; 286} // wl_adapter_insert 287/*============================================================================*/ 288 289/******************************************************************************* 290 * wl_adapter_open() 291 ******************************************************************************* 292 * 293 * DESCRIPTION: 294 * 295 * Open the device. 296 * 297 * PARAMETERS: 298 * 299 * dev - a pointer to the device's net_device structure 300 * 301 * RETURNS: 302 * 303 * an HCF status code 304 * 305 ******************************************************************************/ 306int wl_adapter_open( struct net_device *dev ) 307{ 308 int result = 0; 309 int hcf_status = HCF_SUCCESS; 310 /*------------------------------------------------------------------------*/ 311 312 DBG_FUNC( "wl_adapter_open" ); 313 DBG_ENTER( DbgInfo ); 314 315 DBG_TRACE( DbgInfo, "wl_adapter_open() -- PCI\n" ); 316 317 hcf_status = wl_open( dev ); 318 319 if( hcf_status != HCF_SUCCESS ) { 320 result = -ENODEV; 321 } 322 323 DBG_LEAVE( DbgInfo ); 324 return result; 325} // wl_adapter_open 326/*============================================================================*/ 327 328/******************************************************************************* 329 * wl_adapter_close() 330 ******************************************************************************* 331 * 332 * DESCRIPTION: 333 * 334 * Close the device 335 * 336 * PARAMETERS: 337 * 338 * dev - a pointer to the device's net_device structure 339 * 340 * RETURNS: 341 * 342 * 0 343 * 344 ******************************************************************************/ 345int wl_adapter_close( struct net_device *dev ) 346{ 347 DBG_FUNC( "wl_adapter_close" ); 348 DBG_ENTER( DbgInfo ); 349 350 DBG_TRACE( DbgInfo, "wl_adapter_close() -- PCI\n" ); 351 DBG_TRACE( DbgInfo, "%s: Shutting down adapter.\n", dev->name ); 352 353 wl_close( dev ); 354 355 DBG_LEAVE( DbgInfo ); 356 return 0; 357} // wl_adapter_close 358/*============================================================================*/ 359 360/******************************************************************************* 361 * wl_adapter_is_open() 362 ******************************************************************************* 363 * 364 * DESCRIPTION: 365 * 366 * Check whether this device is open. Returns 367 * 368 * PARAMETERS: 369 * 370 * dev - a pointer to the device's net_device structure 371 * 372 * RETURNS: 373 * 374 * nonzero if device is open. 375 * 376 ******************************************************************************/ 377int wl_adapter_is_open( struct net_device *dev ) 378{ 379 /* This function is used in PCMCIA to check the status of the 'open' field 380 in the dev_link_t structure associated with a network device. There 381 doesn't seem to be an analog to this for PCI, and checking the status 382 contained in the net_device structure doesn't have the same effect. 383 For now, return TRUE, but find out if this is necessary for PCI. */ 384 385 return TRUE; 386} // wl_adapter_is_open 387/*============================================================================*/ 388 389/******************************************************************************* 390 * wl_pci_probe() 391 ******************************************************************************* 392 * 393 * DESCRIPTION: 394 * 395 * Registered in the pci_driver structure, this function is called when the 396 * PCI subsystem finds a new PCI device which matches the infomation contained 397 * in the pci_device_id table. 398 * 399 * PARAMETERS: 400 * 401 * pdev - a pointer to the device's pci_dev structure 402 * ent - this device's entry in the pci_device_id table 403 * 404 * RETURNS: 405 * 406 * 0 on success 407 * errno value otherwise 408 * 409 ******************************************************************************/ 410int __devinit wl_pci_probe( struct pci_dev *pdev, 411 const struct pci_device_id *ent ) 412{ 413 int result; 414 /*------------------------------------------------------------------------*/ 415 416 DBG_FUNC( "wl_pci_probe" ); 417 DBG_ENTER( DbgInfo ); 418 DBG_PRINT( "%s\n", VERSION_INFO ); 419 420 result = wl_pci_setup( pdev ); 421 422 DBG_LEAVE( DbgInfo ); 423 424 return result; 425} // wl_pci_probe 426/*============================================================================*/ 427 428/******************************************************************************* 429 * wl_pci_remove() 430 ******************************************************************************* 431 * 432 * DESCRIPTION: 433 * 434 * Registered in the pci_driver structure, this function is called when the 435 * PCI subsystem detects that a PCI device which matches the infomation 436 * contained in the pci_device_id table has been removed. 437 * 438 * PARAMETERS: 439 * 440 * pdev - a pointer to the device's pci_dev structure 441 * 442 * RETURNS: 443 * 444 * N/A 445 * 446 ******************************************************************************/ 447void __devexit wl_pci_remove(struct pci_dev *pdev) 448{ 449 struct net_device *dev = NULL; 450 /*------------------------------------------------------------------------*/ 451 452 DBG_FUNC( "wl_pci_remove" ); 453 DBG_ENTER( DbgInfo ); 454 455 /* Make sure the pci_dev pointer passed in is valid */ 456 if( pdev == NULL ) { 457 DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" ); 458 return; 459 } 460 461 dev = (struct net_device *)pci_get_drvdata( pdev ); 462 if( dev == NULL ) { 463 DBG_ERROR( DbgInfo, "Could not retrieve net_device structure\n" ); 464 return; 465 } 466 467 /* Perform device cleanup */ 468 wl_remove( dev ); 469 free_irq( dev->irq, dev ); 470 471#ifdef ENABLE_DMA 472 wl_pci_dma_free( pdev, dev->priv ); 473#endif 474 475 wl_device_dealloc( dev ); 476 477 DBG_LEAVE( DbgInfo ); 478 return; 479} // wl_pci_remove 480/*============================================================================*/ 481 482/******************************************************************************* 483 * wl_pci_setup() 484 ******************************************************************************* 485 * 486 * DESCRIPTION: 487 * 488 * Called by wl_pci_probe() to begin a device's initialization process. 489 * 490 * PARAMETERS: 491 * 492 * pdev - a pointer to the device's pci_dev structure 493 * 494 * RETURNS: 495 * 496 * 0 on success 497 * errno value otherwise 498 * 499 ******************************************************************************/ 500int wl_pci_setup( struct pci_dev *pdev ) 501{ 502 int result = 0; 503 struct net_device *dev = NULL; 504 struct wl_private *lp = NULL; 505 /*------------------------------------------------------------------------*/ 506 507 DBG_FUNC( "wl_pci_setup" ); 508 DBG_ENTER( DbgInfo ); 509 510 /* Make sure the pci_dev pointer passed in is valid */ 511 if( pdev == NULL ) { 512 DBG_ERROR( DbgInfo, "PCI subsys passed in an invalid pci_dev pointer\n" ); 513 return -ENODEV; 514 } 515 516 result = pci_enable_device( pdev ); 517 if( result != 0 ) { 518 DBG_ERROR( DbgInfo, "pci_enable_device() failed\n" ); 519 DBG_LEAVE( DbgInfo ); 520 return result; 521 } 522 523 /* We found our device! Let's register it with the system */ 524 DBG_TRACE( DbgInfo, "Found our device, now registering\n" ); 525 dev = wl_device_alloc( ); 526 if( dev == NULL ) { 527 DBG_ERROR( DbgInfo, "Could not register device!!!\n" ); 528 DBG_LEAVE( DbgInfo ); 529 return -ENOMEM; 530 } 531 532 /* Make sure that space was allocated for our private adapter struct */ 533 if( dev->priv == NULL ) { 534 DBG_ERROR( DbgInfo, "Private adapter struct was not allocated!!!\n" ); 535 DBG_LEAVE( DbgInfo ); 536 return -ENOMEM; 537 } 538 539#ifdef ENABLE_DMA 540 /* Allocate DMA Descriptors */ 541 if( wl_pci_dma_alloc( pdev, dev->priv ) < 0 ) { 542 DBG_ERROR( DbgInfo, "Could not allocate DMA descriptor memory!!!\n" ); 543 DBG_LEAVE( DbgInfo ); 544 return -ENOMEM; 545 } 546#endif 547 548 /* Register our private adapter structure with PCI */ 549 pci_set_drvdata( pdev, dev ); 550 551 /* Fill out bus specific information in the net_device struct */ 552 dev->irq = pdev->irq; 553 SET_MODULE_OWNER( dev ); 554 555 DBG_TRACE( DbgInfo, "Device Base Address: %#03lx\n", pdev->resource[0].start ); 556 dev->base_addr = pdev->resource[0].start; 557 558 /* Initialize our device here */ 559 if( !wl_adapter_insert( dev )) { 560 DBG_ERROR( DbgInfo, "wl_adapter_insert() FAILED!!!\n" ); 561 wl_device_dealloc( dev ); 562 DBG_LEAVE( DbgInfo ); 563 return -EINVAL; 564 } 565 566 /* Register our ISR */ 567 DBG_TRACE( DbgInfo, "Registering ISR...\n" ); 568 569 result = request_irq(dev->irq, wl_isr, SA_SHIRQ, dev->name, dev); 570 if( result ) { 571 DBG_WARNING( DbgInfo, "Could not register ISR!!!\n" ); 572 DBG_LEAVE( DbgInfo ); 573 return result; 574 } 575 576 /* Make sure interrupts are enabled properly for CardBus */ 577 lp = dev->priv; 578 579 if( lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_CARDBUS || 580 lp->hcfCtx.IFB_BusType == CFG_NIC_BUS_TYPE_PCI ) { 581 DBG_TRACE( DbgInfo, "This is a PCI/CardBus card, enable interrupts\n" ); 582 wl_pci_enable_cardbus_interrupts( pdev ); 583 } 584 585 /* Enable bus mastering */ 586 pci_set_master( pdev ); 587 588 DBG_LEAVE( DbgInfo ); 589 return 0; 590} // wl_pci_setup 591/*============================================================================*/ 592 593/******************************************************************************* 594 * wl_pci_enable_cardbus_interrupts() 595 ******************************************************************************* 596 * 597 * DESCRIPTION: 598 * 599 * Called by wl_pci_setup() to enable interrupts on a CardBus device. This 600 * is done by writing bit 15 to the function event mask register. This 601 * CardBus-specific register is located in BAR2 (counting from BAR0), in memory 602 * space at byte offset 1f4 (7f4 for WARP). 603 * 604 * PARAMETERS: 605 * 606 * pdev - a pointer to the device's pci_dev structure 607 * 608 * RETURNS: 609 * 610 * N/A 611 * 612 ******************************************************************************/ 613void wl_pci_enable_cardbus_interrupts( struct pci_dev *pdev ) 614{ 615 u32 bar2_reg; 616 u32 mem_addr_bus; 617 u32 func_evt_mask_reg; 618 void *mem_addr_kern = NULL; 619 /*------------------------------------------------------------------------*/ 620 621 DBG_FUNC( "wl_pci_enable_cardbus_interrupts" ); 622 DBG_ENTER( DbgInfo ); 623 624 /* Initialize to known bad values */ 625 bar2_reg = 0xdeadbeef; 626 mem_addr_bus = 0xdeadbeef; 627 628 /* Read the BAR2 register; this register contains the base address of the 629 memory region where the function event mask register lives */ 630 pci_read_config_dword( pdev, PCI_BASE_ADDRESS_2, &bar2_reg ); 631 mem_addr_bus = bar2_reg & PCI_BASE_ADDRESS_MEM_MASK; 632 633 /* Once the base address is obtained, remap the memory region to kernel 634 space so we can retrieve the register */ 635 mem_addr_kern = ioremap( mem_addr_bus, 0x200 ); 636 637#ifdef HERMES25 638#define REG_OFFSET 0x07F4 639#else 640#define REG_OFFSET 0x01F4 641#endif // HERMES25 642 643#define BIT15 0x8000 644 645 /* Retrieve the functional event mask register, enable interrupts by 646 setting Bit 15, and write back the value */ 647 func_evt_mask_reg = *(u32 *)( mem_addr_kern + REG_OFFSET ); 648 func_evt_mask_reg |= BIT15; 649 *(u32 *)( mem_addr_kern + REG_OFFSET ) = func_evt_mask_reg; 650 651 /* Once complete, unmap the region and exit */ 652 iounmap( mem_addr_kern ); 653 654 DBG_LEAVE( DbgInfo ); 655 return; 656} // wl_pci_enable_cardbus_interrupts 657/*============================================================================*/ 658 659#ifdef ENABLE_DMA 660/******************************************************************************* 661 * wl_pci_dma_alloc() 662 ******************************************************************************* 663 * 664 * DESCRIPTION: 665 * 666 * Allocates all resources needed for PCI/CardBus DMA operation 667 * 668 * PARAMETERS: 669 * 670 * pdev - a pointer to the device's pci_dev structure 671 * lp - the device's private adapter structure 672 * 673 * RETURNS: 674 * 675 * 0 on success 676 * errno value otherwise 677 * 678 ******************************************************************************/ 679int wl_pci_dma_alloc( struct pci_dev *pdev, struct wl_private *lp ) 680{ 681 int i; 682 int status = 0; 683 /*------------------------------------------------------------------------*/ 684 685 DBG_FUNC( "wl_pci_dma_alloc" ); 686 DBG_ENTER( DbgInfo ); 687 688// lp->dma.tx_rsc_ind = lp->dma.rx_rsc_ind = 0; 689// 690// /* Alloc for the Tx chain and its reclaim descriptor */ 691// for( i = 0; i < NUM_TX_DESC; i++ ) { 692// status = wl_pci_dma_alloc_tx_packet( pdev, lp, &lp->dma.tx_packet[i] ); 693// if( status == 0 ) { 694// DBG_PRINT( "lp->dma.tx_packet[%d] : 0x%p\n", i, lp->dma.tx_packet[i] ); 695// DBG_PRINT( "lp->dma.tx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.tx_packet[i]->next_desc_addr ); 696// lp->dma.tx_rsc_ind++; 697// } else { 698// DBG_ERROR( DbgInfo, "Could not alloc DMA Tx Packet\n" ); 699// break; 700// } 701// } 702// if( status == 0 ) { 703// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.tx_reclaim_desc ); 704// DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc ); 705// } 706// /* Alloc for the Rx chain and its reclaim descriptor */ 707// if( status == 0 ) { 708// for( i = 0; i < NUM_RX_DESC; i++ ) { 709// status = wl_pci_dma_alloc_rx_packet( pdev, lp, &lp->dma.rx_packet[i] ); 710// if( status == 0 ) { 711// DBG_PRINT( "lp->dma.rx_packet[%d] : 0x%p\n", i, lp->dma.rx_packet[i] ); 712// DBG_PRINT( "lp->dma.rx_packet[%d]->next_desc_addr : 0x%p\n", i, lp->dma.rx_packet[i]->next_desc_addr ); 713// lp->dma.rx_rsc_ind++; 714// } else { 715// DBG_ERROR( DbgInfo, "Could not alloc DMA Rx Packet\n" ); 716// break; 717// } 718// } 719// } 720// if( status == 0 ) { 721// status = wl_pci_dma_alloc_desc( pdev, lp, &lp->dma.rx_reclaim_desc ); 722// DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc ); 723// } 724// /* Store status, as host should not call HCF functions if this fails */ 725// lp->dma.status = status; //;?all useages of dma.status have been commented out 726// DBG_LEAVE( DbgInfo ); 727 return status; 728} // wl_pci_dma_alloc 729/*============================================================================*/ 730 731/******************************************************************************* 732 * wl_pci_dma_free() 733 ******************************************************************************* 734 * 735 * DESCRIPTION: 736 * 737 * Deallocated all resources needed for PCI/CardBus DMA operation 738 * 739 * PARAMETERS: 740 * 741 * pdev - a pointer to the device's pci_dev structure 742 * lp - the device's private adapter structure 743 * 744 * RETURNS: 745 * 746 * 0 on success 747 * errno value otherwise 748 * 749 ******************************************************************************/ 750int wl_pci_dma_free( struct pci_dev *pdev, struct wl_private *lp ) 751{ 752 int i; 753 int status = 0; 754 /*------------------------------------------------------------------------*/ 755 756 DBG_FUNC( "wl_pci_dma_free" ); 757 DBG_ENTER( DbgInfo ); 758 759 /* Reclaim all Rx packets that were handed over to the HCF */ 760 /* Do I need to do this? Before this free is called, I've already disabled 761 the port which will call wl_pci_dma_hcf_reclaim */ 762 //if( lp->dma.status == 0 ) 763 //{ 764 // wl_pci_dma_hcf_reclaim( lp ); 765 //} 766 767 /* Free everything needed for DMA Rx */ 768 for( i = 0; i < NUM_RX_DESC; i++ ) { 769 if( lp->dma.rx_packet[i] ) { 770 status = wl_pci_dma_free_rx_packet( pdev, lp, &lp->dma.rx_packet[i] ); 771 if( status != 0 ) { 772 DBG_WARNING( DbgInfo, "Problem freeing Rx packet\n" ); 773 } 774 } 775 } 776 lp->dma.rx_rsc_ind = 0; 777 778 if( lp->dma.rx_reclaim_desc ) { 779 status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.rx_reclaim_desc ); 780 if( status != 0 ) { 781 DBG_WARNING( DbgInfo, "Problem freeing Rx reclaim descriptor\n" ); 782 } 783 } 784 785 /* Free everything needed for DMA Tx */ 786 for( i = 0; i < NUM_TX_DESC; i++ ) { 787 if( lp->dma.tx_packet[i] ) { 788 status = wl_pci_dma_free_tx_packet( pdev, lp, &lp->dma.tx_packet[i] ); 789 if( status != 0 ) { 790 DBG_WARNING( DbgInfo, "Problem freeing Tx packet\n" ); 791 } 792 } 793 } 794 lp->dma.tx_rsc_ind = 0; 795 796 if( lp->dma.tx_reclaim_desc ) { 797 status = wl_pci_dma_free_desc( pdev, lp, &lp->dma.tx_reclaim_desc ); 798 if( status != 0 ) { 799 DBG_WARNING( DbgInfo, "Problem freeing Tx reclaim descriptor\n" ); 800 } 801 } 802 803 DBG_LEAVE( DbgInfo ); 804 return status; 805} // wl_pci_dma_free 806 807/*============================================================================*/ 808 809/******************************************************************************* 810 * wl_pci_dma_alloc_tx_packet() 811 ******************************************************************************* 812 * 813 * DESCRIPTION: 814 * 815 * Allocates a single Tx packet, consisting of several descriptors and 816 * buffers. Data to transmit is first copied into the 'payload' buffer 817 * before being transmitted. 818 * 819 * PARAMETERS: 820 * 821 * pdev - a pointer to the device's pci_dev structure 822 * lp - the device's private adapter structure 823 * desc - a pointer which will reference the descriptor to be alloc'd. 824 * 825 * RETURNS: 826 * 827 * 0 on success 828 * errno value otherwise 829 * 830 ******************************************************************************/ 831int wl_pci_dma_alloc_tx_packet( struct pci_dev *pdev, struct wl_private *lp, 832 DESC_STRCT **desc ) 833{ 834// int status = 0; 835// /*------------------------------------------------------------------------*/ 836// 837// if( desc == NULL ) { 838// status = -EFAULT; 839// } 840// if( status == 0 ) { 841// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp, desc, 842// HCF_DMA_TX_BUF1_SIZE ); 843// 844// if( status == 0 ) { 845// status = wl_pci_dma_alloc_desc_and_buf( pdev, lp, 846// &( (*desc)->next_desc_addr ), 847// HCF_MAX_PACKET_SIZE ); 848// } 849// } 850// if( status == 0 ) { 851// (*desc)->next_desc_phys_addr = (*desc)->next_desc_addr->desc_phys_addr; 852// } 853// return status; 854} // wl_pci_dma_alloc_tx_packet 855/*============================================================================*/ 856 857/******************************************************************************* 858 * wl_pci_dma_free_tx_packet() 859 ******************************************************************************* 860 * 861 * DESCRIPTION: 862 * 863 * Frees a single Tx packet, described in the corresponding alloc function. 864 * 865 * PARAMETERS: 866 * 867 * pdev - a pointer to the device's pci_dev structure 868 * lp - the device's private adapter structure 869 * desc - a pointer which will reference the descriptor to be alloc'd. 870 * 871 * RETURNS: 872 * 873 * 0 on success 874 * errno value otherwise 875 * 876 ******************************************************************************/ 877int wl_pci_dma_free_tx_packet( struct pci_dev *pdev, struct wl_private *lp, 878 DESC_STRCT **desc ) 879{ 880 int status = 0; 881 /*------------------------------------------------------------------------*/ 882 883 if( *desc == NULL ) { 884 DBG_PRINT( "Null descriptor\n" ); 885 status = -EFAULT; 886 } 887 //;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2 888 //descriptors, make this robust 889 if( status == 0 && (*desc)->next_desc_addr ) { 890 status = wl_pci_dma_free_desc_and_buf( pdev, lp, &(*desc)->next_desc_addr ); 891 } 892 if( status == 0 ) { 893 status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc ); 894 } 895 return status; 896} // wl_pci_dma_free_tx_packet 897/*============================================================================*/ 898 899/******************************************************************************* 900 * wl_pci_dma_alloc_rx_packet() 901 ******************************************************************************* 902 * 903 * DESCRIPTION: 904 * 905 * Allocates a single Rx packet, consisting of two descriptors and one 906 * contiguous buffer. THe buffer starts with the hermes-specific header. 907 * One descriptor points at the start, the other at offset 0x3a of the 908 * buffer. 909 * 910 * PARAMETERS: 911 * 912 * pdev - a pointer to the device's pci_dev structure 913 * lp - the device's private adapter structure 914 * desc - a pointer which will reference the descriptor to be alloc'd. 915 * 916 * RETURNS: 917 * 918 * 0 on success 919 * errno value otherwise 920 * 921 ******************************************************************************/ 922int wl_pci_dma_alloc_rx_packet( struct pci_dev *pdev, struct wl_private *lp, 923 DESC_STRCT **desc ) 924{ 925 int status = 0; 926 DESC_STRCT *p; 927 /*------------------------------------------------------------------------*/ 928 929// if( desc == NULL ) { 930// status = -EFAULT; 931// } 932// //;?the "limited" NDIS strategy, assuming a frame consists ALWAYS out of 2 933// //descriptors, make this robust 934// if( status == 0 ) { 935// status = wl_pci_dma_alloc_desc( pdev, lp, desc ); 936// } 937// if( status == 0 ) { 938// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, HCF_MAX_PACKET_SIZE ); 939// } 940// if( status == 0 ) { 941// status = wl_pci_dma_alloc_desc( pdev, lp, &p ); 942// } 943// if( status == 0 ) { 944// /* Size of 1st descriptor becomes 0x3a bytes */ 945// SET_BUF_SIZE( *desc, HCF_DMA_RX_BUF1_SIZE ); 946// 947// /* Make 2nd descriptor point at offset 0x3a of the buffer */ 948// SET_BUF_SIZE( p, ( HCF_MAX_PACKET_SIZE - HCF_DMA_RX_BUF1_SIZE )); 949// p->buf_addr = (*desc)->buf_addr + HCF_DMA_RX_BUF1_SIZE; 950// p->buf_phys_addr = (*desc)->buf_phys_addr + HCF_DMA_RX_BUF1_SIZE; 951// p->next_desc_addr = NULL; 952// 953// /* Chain 2nd descriptor to 1st descriptor */ 954// (*desc)->next_desc_addr = p; 955// (*desc)->next_desc_phys_addr = p->desc_phys_addr; 956// } 957 958 return status; 959} // wl_pci_dma_alloc_rx_packet 960/*============================================================================*/ 961 962/******************************************************************************* 963 * wl_pci_dma_free_rx_packet() 964 ******************************************************************************* 965 * 966 * DESCRIPTION: 967 * 968 * Frees a single Rx packet, described in the corresponding alloc function. 969 * 970 * PARAMETERS: 971 * 972 * pdev - a pointer to the device's pci_dev structure 973 * lp - the device's private adapter structure 974 * desc - a pointer which will reference the descriptor to be alloc'd. 975 * 976 * RETURNS: 977 * 978 * 0 on success 979 * errno value otherwise 980 * 981 ******************************************************************************/ 982int wl_pci_dma_free_rx_packet( struct pci_dev *pdev, struct wl_private *lp, 983 DESC_STRCT **desc ) 984{ 985 int status = 0; 986 DESC_STRCT *p; 987 /*------------------------------------------------------------------------*/ 988 989 if( *desc == NULL ) { 990 status = -EFAULT; 991 } 992 if( status == 0 ) { 993 p = (*desc)->next_desc_addr; 994 995 /* Free the 2nd descriptor */ 996 if( p != NULL ) { 997 p->buf_addr = NULL; 998 p->buf_phys_addr = 0; 999 1000 status = wl_pci_dma_free_desc( pdev, lp, &p ); 1001 } 1002 } 1003 1004 /* Free the buffer and 1st descriptor */ 1005 if( status == 0 ) { 1006 SET_BUF_SIZE( *desc, HCF_MAX_PACKET_SIZE ); 1007 status = wl_pci_dma_free_desc_and_buf( pdev, lp, desc ); 1008 } 1009 return status; 1010} // wl_pci_dma_free_rx_packet 1011/*============================================================================*/ 1012 1013/******************************************************************************* 1014 * wl_pci_dma_alloc_desc_and_buf() 1015 ******************************************************************************* 1016 * 1017 * DESCRIPTION: 1018 * 1019 * Allocates a DMA descriptor and buffer, and associates them with one 1020 * another. 1021 * 1022 * PARAMETERS: 1023 * 1024 * pdev - a pointer to the device's pci_dev structure 1025 * lp - the device's private adapter structure 1026 * desc - a pointer which will reference the descriptor to be alloc'd 1027 * 1028 * RETURNS: 1029 * 1030 * 0 on success 1031 * errno value otherwise 1032 * 1033 ******************************************************************************/ 1034int wl_pci_dma_alloc_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, 1035 DESC_STRCT **desc, int size ) 1036{ 1037 int status = 0; 1038 /*------------------------------------------------------------------------*/ 1039 1040// if( desc == NULL ) { 1041// status = -EFAULT; 1042// } 1043// if( status == 0 ) { 1044// status = wl_pci_dma_alloc_desc( pdev, lp, desc ); 1045// 1046// if( status == 0 ) { 1047// status = wl_pci_dma_alloc_buf( pdev, lp, *desc, size ); 1048// } 1049// } 1050 return status; 1051} // wl_pci_dma_alloc_desc_and_buf 1052/*============================================================================*/ 1053 1054/******************************************************************************* 1055 * wl_pci_dma_free_desc_and_buf() 1056 ******************************************************************************* 1057 * 1058 * DESCRIPTION: 1059 * 1060 * Frees a DMA descriptor and associated buffer. 1061 * 1062 * PARAMETERS: 1063 * 1064 * pdev - a pointer to the device's pci_dev structure 1065 * lp - the device's private adapter structure 1066 * desc - a pointer which will reference the descriptor to be alloc'd 1067 * 1068 * RETURNS: 1069 * 1070 * 0 on success 1071 * errno value otherwise 1072 * 1073 ******************************************************************************/ 1074int wl_pci_dma_free_desc_and_buf( struct pci_dev *pdev, struct wl_private *lp, 1075 DESC_STRCT **desc ) 1076{ 1077 int status = 0; 1078 /*------------------------------------------------------------------------*/ 1079 1080 if( desc == NULL ) { 1081 status = -EFAULT; 1082 } 1083 if( status == 0 && *desc == NULL ) { 1084 status = -EFAULT; 1085 } 1086 if( status == 0 ) { 1087 status = wl_pci_dma_free_buf( pdev, lp, *desc ); 1088 1089 if( status == 0 ) { 1090 status = wl_pci_dma_free_desc( pdev, lp, desc ); 1091 } 1092 } 1093 return status; 1094} // wl_pci_dma_free_desc_and_buf 1095/*============================================================================*/ 1096 1097/******************************************************************************* 1098 * wl_pci_dma_alloc_desc() 1099 ******************************************************************************* 1100 * 1101 * DESCRIPTION: 1102 * 1103 * Allocates one DMA descriptor in cache coherent memory. 1104 * 1105 * PARAMETERS: 1106 * 1107 * pdev - a pointer to the device's pci_dev structure 1108 * lp - the device's private adapter structure 1109 * 1110 * RETURNS: 1111 * 1112 * 0 on success 1113 * errno value otherwise 1114 * 1115 ******************************************************************************/ 1116int wl_pci_dma_alloc_desc( struct pci_dev *pdev, struct wl_private *lp, 1117 DESC_STRCT **desc ) 1118{ 1119// int status = 0; 1120// dma_addr_t pa; 1121// /*------------------------------------------------------------------------*/ 1122// 1123// DBG_FUNC( "wl_pci_dma_alloc_desc" ); 1124// DBG_ENTER( DbgInfo ); 1125// 1126// if( desc == NULL ) { 1127// status = -EFAULT; 1128// } 1129// if( status == 0 ) { 1130// *desc = pci_alloc_consistent( pdev, sizeof( DESC_STRCT ), &pa ); 1131// } 1132// if( *desc == NULL ) { 1133// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" ); 1134// status = -ENOMEM; 1135// } else { 1136// memset( *desc, 0, sizeof( DESC_STRCT )); 1137// (*desc)->desc_phys_addr = cpu_to_le32( pa ); 1138// } 1139// DBG_LEAVE( DbgInfo ); 1140// return status; 1141} // wl_pci_dma_alloc_desc 1142/*============================================================================*/ 1143 1144/******************************************************************************* 1145 * wl_pci_dma_free_desc() 1146 ******************************************************************************* 1147 * 1148 * DESCRIPTION: 1149 * 1150 * Frees one DMA descriptor in cache coherent memory. 1151 * 1152 * PARAMETERS: 1153 * 1154 * pdev - a pointer to the device's pci_dev structure 1155 * lp - the device's private adapter structure 1156 * 1157 * RETURNS: 1158 * 1159 * 0 on success 1160 * errno value otherwise 1161 * 1162 ******************************************************************************/ 1163int wl_pci_dma_free_desc( struct pci_dev *pdev, struct wl_private *lp, 1164 DESC_STRCT **desc ) 1165{ 1166 int status = 0; 1167 /*------------------------------------------------------------------------*/ 1168 1169 if( *desc == NULL ) { 1170 status = -EFAULT; 1171 } 1172 if( status == 0 ) { 1173 pci_free_consistent( pdev, sizeof( DESC_STRCT ), *desc, 1174 (*desc)->desc_phys_addr ); 1175 } 1176 *desc = NULL; 1177 return status; 1178} // wl_pci_dma_free_desc 1179/*============================================================================*/ 1180 1181/******************************************************************************* 1182 * wl_pci_dma_alloc_buf() 1183 ******************************************************************************* 1184 * 1185 * DESCRIPTION: 1186 * 1187 * Allocates one DMA buffer in cache coherent memory, and associates a DMA 1188 * descriptor with this buffer. 1189 * 1190 * PARAMETERS: 1191 * 1192 * pdev - a pointer to the device's pci_dev structure 1193 * lp - the device's private adapter structure 1194 * 1195 * RETURNS: 1196 * 1197 * 0 on success 1198 * errno value otherwise 1199 * 1200 ******************************************************************************/ 1201int wl_pci_dma_alloc_buf( struct pci_dev *pdev, struct wl_private *lp, 1202 DESC_STRCT *desc, int size ) 1203{ 1204 int status = 0; 1205 dma_addr_t pa; 1206 /*------------------------------------------------------------------------*/ 1207 1208// DBG_FUNC( "wl_pci_dma_alloc_buf" ); 1209// DBG_ENTER( DbgInfo ); 1210// 1211// if( desc == NULL ) { 1212// status = -EFAULT; 1213// } 1214// if( status == 0 && desc->buf_addr != NULL ) { 1215// status = -EFAULT; 1216// } 1217// if( status == 0 ) { 1218// desc->buf_addr = pci_alloc_consistent( pdev, size, &pa ); 1219// } 1220// if( desc->buf_addr == NULL ) { 1221// DBG_ERROR( DbgInfo, "pci_alloc_consistent() failed\n" ); 1222// status = -ENOMEM; 1223// } else { 1224// desc->buf_phys_addr = cpu_to_le32( pa ); 1225// SET_BUF_SIZE( desc, size ); 1226// } 1227// DBG_LEAVE( DbgInfo ); 1228 return status; 1229} // wl_pci_dma_alloc_buf 1230/*============================================================================*/ 1231 1232/******************************************************************************* 1233 * wl_pci_dma_free_buf() 1234 ******************************************************************************* 1235 * 1236 * DESCRIPTION: 1237 * 1238 * Allocates one DMA buffer in cache coherent memory, and associates a DMA 1239 * descriptor with this buffer. 1240 * 1241 * PARAMETERS: 1242 * 1243 * pdev - a pointer to the device's pci_dev structure 1244 * lp - the device's private adapter structure 1245 * 1246 * RETURNS: 1247 * 1248 * 0 on success 1249 * errno value otherwise 1250 * 1251 ******************************************************************************/ 1252int wl_pci_dma_free_buf( struct pci_dev *pdev, struct wl_private *lp, 1253 DESC_STRCT *desc ) 1254{ 1255 int status = 0; 1256 /*------------------------------------------------------------------------*/ 1257 1258 if( desc == NULL ) { 1259 status = -EFAULT; 1260 } 1261 if( status == 0 && desc->buf_addr == NULL ) { 1262 status = -EFAULT; 1263 } 1264 if( status == 0 ) { 1265 pci_free_consistent( pdev, GET_BUF_SIZE( desc ), desc->buf_addr, 1266 desc->buf_phys_addr ); 1267 1268 desc->buf_addr = 0; 1269 desc->buf_phys_addr = 0; 1270 SET_BUF_SIZE( desc, 0 ); 1271 } 1272 return status; 1273} // wl_pci_dma_free_buf 1274/*============================================================================*/ 1275 1276/******************************************************************************* 1277 * wl_pci_dma_hcf_supply() 1278 ******************************************************************************* 1279 * 1280 * DESCRIPTION: 1281 * 1282 * Supply HCF with DMA-related resources. These consist of: 1283 * - buffers and descriptors for receive purposes 1284 * - one 'reclaim' descriptor for the transmit path, used to fulfill a 1285 * certain H25 DMA engine requirement 1286 * - one 'reclaim' descriptor for the receive path, used to fulfill a 1287 * certain H25 DMA engine requirement 1288 * 1289 * This function is called at start-of-day or at re-initialization. 1290 * 1291 * PARAMETERS: 1292 * 1293 * lp - the device's private adapter structure 1294 * 1295 * RETURNS: 1296 * 1297 * 0 on success 1298 * errno value otherwise 1299 * 1300 ******************************************************************************/ 1301void wl_pci_dma_hcf_supply( struct wl_private *lp ) 1302{ 1303 int i; 1304 /*------------------------------------------------------------------------*/ 1305 1306 DBG_FUNC( "wl_pci_dma_hcf_supply" ); 1307 DBG_ENTER( DbgInfo ); 1308 1309 //if( lp->dma.status == 0 ); 1310 //{ 1311 /* Hand over the Rx/Tx reclaim descriptors to the HCF */ 1312 if( lp->dma.tx_reclaim_desc ) { 1313 DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc ); 1314 hcf_dma_tx_put( &lp->hcfCtx, lp->dma.tx_reclaim_desc, 0 ); 1315 lp->dma.tx_reclaim_desc = NULL; 1316 DBG_PRINT( "lp->dma.tx_reclaim_desc: 0x%p\n", lp->dma.tx_reclaim_desc ); 1317 } 1318 if( lp->dma.rx_reclaim_desc ) { 1319 DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc ); 1320 hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_reclaim_desc ); 1321 lp->dma.rx_reclaim_desc = NULL; 1322 DBG_PRINT( "lp->dma.rx_reclaim_desc: 0x%p\n", lp->dma.rx_reclaim_desc ); 1323 } 1324 /* Hand over the Rx descriptor chain to the HCF */ 1325 for( i = 0; i < NUM_RX_DESC; i++ ) { 1326 DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] ); 1327 hcf_dma_rx_put( &lp->hcfCtx, lp->dma.rx_packet[i] ); 1328 lp->dma.rx_packet[i] = NULL; 1329 DBG_PRINT( "lp->dma.rx_packet[%d]: 0x%p\n", i, lp->dma.rx_packet[i] ); 1330 } 1331 //} 1332 1333 DBG_LEAVE( DbgInfo ); 1334 return; 1335} // wl_pci_dma_hcf_supply 1336/*============================================================================*/ 1337 1338/******************************************************************************* 1339 * wl_pci_dma_hcf_reclaim() 1340 ******************************************************************************* 1341 * 1342 * DESCRIPTION: 1343 * 1344 * Return DMA-related resources from the HCF. These consist of: 1345 * - buffers and descriptors for receive purposes 1346 * - buffers and descriptors for transmit purposes 1347 * - one 'reclaim' descriptor for the transmit path, used to fulfill a 1348 * certain H25 DMA engine requirement 1349 * - one 'reclaim' descriptor for the receive path, used to fulfill a 1350 * certain H25 DMA engine requirement 1351 * 1352 * This function is called at end-of-day or at re-initialization. 1353 * 1354 * PARAMETERS: 1355 * 1356 * lp - the device's private adapter structure 1357 * 1358 * RETURNS: 1359 * 1360 * 0 on success 1361 * errno value otherwise 1362 * 1363 ******************************************************************************/ 1364void wl_pci_dma_hcf_reclaim( struct wl_private *lp ) 1365{ 1366 int i; 1367 /*------------------------------------------------------------------------*/ 1368 1369 DBG_FUNC( "wl_pci_dma_hcf_reclaim" ); 1370 DBG_ENTER( DbgInfo ); 1371 1372 wl_pci_dma_hcf_reclaim_rx( lp ); 1373 for( i = 0; i < NUM_RX_DESC; i++ ) { 1374 DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] ); 1375// if( lp->dma.rx_packet[i] == NULL ) { 1376// DBG_PRINT( "wl_pci_dma_hcf_reclaim: rx_packet[%d] NULL\n", i ); 1377// } 1378 } 1379 1380 wl_pci_dma_hcf_reclaim_tx( lp ); 1381 for( i = 0; i < NUM_TX_DESC; i++ ) { 1382 DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] ); 1383// if( lp->dma.tx_packet[i] == NULL ) { 1384// DBG_PRINT( "wl_pci_dma_hcf_reclaim: tx_packet[%d] NULL\n", i ); 1385// } 1386 } 1387 1388 DBG_LEAVE( DbgInfo ); 1389 return; 1390} // wl_pci_dma_hcf_reclaim 1391/*============================================================================*/ 1392 1393/******************************************************************************* 1394 * wl_pci_dma_hcf_reclaim_rx() 1395 ******************************************************************************* 1396 * 1397 * DESCRIPTION: 1398 * 1399 * Reclaim Rx packets that have already been processed by the HCF. 1400 * 1401 * PARAMETERS: 1402 * 1403 * lp - the device's private adapter structure 1404 * 1405 * RETURNS: 1406 * 1407 * 0 on success 1408 * errno value otherwise 1409 * 1410 ******************************************************************************/ 1411void wl_pci_dma_hcf_reclaim_rx( struct wl_private *lp ) 1412{ 1413 int i; 1414 DESC_STRCT *p; 1415 /*------------------------------------------------------------------------*/ 1416 1417 DBG_FUNC( "wl_pci_dma_hcf_reclaim_rx" ); 1418 DBG_ENTER( DbgInfo ); 1419 1420 //if( lp->dma.status == 0 ) 1421 //{ 1422 while ( ( p = hcf_dma_rx_get( &lp->hcfCtx ) ) != NULL ) { 1423 if( p && p->buf_addr == NULL ) { 1424 /* A reclaim descriptor is being given back by the HCF. Reclaim 1425 descriptors have a NULL buf_addr */ 1426 lp->dma.rx_reclaim_desc = p; 1427 DBG_PRINT( "reclaim_descriptor: 0x%p\n", p ); 1428 continue; 1429 } 1430 for( i = 0; i < NUM_RX_DESC; i++ ) { 1431 if( lp->dma.rx_packet[i] == NULL ) { 1432 break; 1433 } 1434 } 1435 /* An Rx buffer descriptor is being given back by the HCF */ 1436 lp->dma.rx_packet[i] = p; 1437 lp->dma.rx_rsc_ind++; 1438 DBG_PRINT( "rx_packet[%d] 0x%p\n", i, lp->dma.rx_packet[i] ); 1439 } 1440 //} 1441 DBG_LEAVE( DbgInfo ); 1442} // wl_pci_dma_hcf_reclaim_rx 1443/*============================================================================*/ 1444 1445/******************************************************************************* 1446 * wl_pci_dma_get_tx_packet() 1447 ******************************************************************************* 1448 * 1449 * DESCRIPTION: 1450 * 1451 * Obtains a Tx descriptor from the chain to use for Tx. 1452 * 1453 * PARAMETERS: 1454 * 1455 * lp - a pointer to the device's wl_private structure. 1456 * 1457 * RETURNS: 1458 * 1459 * A pointer to the retrieved descriptor 1460 * 1461 ******************************************************************************/ 1462DESC_STRCT * wl_pci_dma_get_tx_packet( struct wl_private *lp ) 1463{ 1464 int i; 1465 DESC_STRCT *desc = NULL; 1466 /*------------------------------------------------------------------------*/ 1467 1468 for( i = 0; i < NUM_TX_DESC; i++ ) { 1469 if( lp->dma.tx_packet[i] ) { 1470 break; 1471 } 1472 } 1473 1474 if( i != NUM_TX_DESC ) { 1475 desc = lp->dma.tx_packet[i]; 1476 1477 lp->dma.tx_packet[i] = NULL; 1478 lp->dma.tx_rsc_ind--; 1479 1480 memset( desc->buf_addr, 0, HCF_DMA_TX_BUF1_SIZE ); 1481 } 1482 1483 return desc; 1484} // wl_pci_dma_get_tx_packet 1485/*============================================================================*/ 1486 1487/******************************************************************************* 1488 * wl_pci_dma_put_tx_packet() 1489 ******************************************************************************* 1490 * 1491 * DESCRIPTION: 1492 * 1493 * Returns a Tx descriptor to the chain. 1494 * 1495 * PARAMETERS: 1496 * 1497 * lp - a pointer to the device's wl_private structure. 1498 * desc - a pointer to the descriptor to return. 1499 * 1500 * RETURNS: 1501 * 1502 * N/A 1503 * 1504 ******************************************************************************/ 1505void wl_pci_dma_put_tx_packet( struct wl_private *lp, DESC_STRCT *desc ) 1506{ 1507 int i; 1508 /*------------------------------------------------------------------------*/ 1509 1510 for( i = 0; i < NUM_TX_DESC; i++ ) { 1511 if( lp->dma.tx_packet[i] == NULL ) { 1512 break; 1513 } 1514 } 1515 1516 if( i != NUM_TX_DESC ) { 1517 lp->dma.tx_packet[i] = desc; 1518 lp->dma.tx_rsc_ind++; 1519 } 1520} // wl_pci_dma_put_tx_packet 1521/*============================================================================*/ 1522 1523/******************************************************************************* 1524 * wl_pci_dma_hcf_reclaim_tx() 1525 ******************************************************************************* 1526 * 1527 * DESCRIPTION: 1528 * 1529 * Reclaim Tx packets that have either been processed by the HCF due to a 1530 * port disable or a Tx completion. 1531 * 1532 * PARAMETERS: 1533 * 1534 * lp - the device's private adapter structure 1535 * 1536 * RETURNS: 1537 * 1538 * 0 on success 1539 * errno value otherwise 1540 * 1541 ******************************************************************************/ 1542void wl_pci_dma_hcf_reclaim_tx( struct wl_private *lp ) 1543{ 1544 int i; 1545 DESC_STRCT *p; 1546 /*------------------------------------------------------------------------*/ 1547 1548 DBG_FUNC( "wl_pci_dma_hcf_reclaim_tx" ); 1549 DBG_ENTER( DbgInfo ); 1550 1551 //if( lp->dma.status == 0 ) 1552 //{ 1553 while ( ( p = hcf_dma_tx_get( &lp->hcfCtx ) ) != NULL ) { 1554 1555 if( p != NULL && p->buf_addr == NULL ) { 1556 /* A Reclaim descriptor is being given back by the HCF. Reclaim 1557 descriptors have a NULL buf_addr */ 1558 lp->dma.tx_reclaim_desc = p; 1559 DBG_PRINT( "reclaim_descriptor: 0x%p\n", p ); 1560 continue; 1561 } 1562 for( i = 0; i < NUM_TX_DESC; i++ ) { 1563 if( lp->dma.tx_packet[i] == NULL ) { 1564 break; 1565 } 1566 } 1567 /* An Rx buffer descriptor is being given back by the HCF */ 1568 lp->dma.tx_packet[i] = p; 1569 lp->dma.tx_rsc_ind++; 1570 DBG_PRINT( "tx_packet[%d] 0x%p\n", i, lp->dma.tx_packet[i] ); 1571 } 1572 //} 1573 1574 if( lp->netif_queue_on == FALSE ) { 1575 netif_wake_queue( lp->dev ); 1576 WL_WDS_NETIF_WAKE_QUEUE( lp ); 1577 lp->netif_queue_on = TRUE; 1578 } 1579 DBG_LEAVE( DbgInfo ); 1580 return; 1581} // wl_pci_dma_hcf_reclaim_tx 1582/*============================================================================*/ 1583#endif // ENABLE_DMA 1584