/**
 * @brief This function adds the card. it will probe the
 * card, allocate the wlan_priv and initialize the device. 
 *  
 *  @param card    A pointer to card
 *  @return        A pointer to wlan_private structure
 */
wlan_private *
wlan_add_card(void *card)
{
    struct net_device *dev = NULL;
    wlan_private *priv = NULL;

    ENTER();

    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
        goto exit_sem_err;

    /* Allocate an Ethernet device and register it */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
    if (!(dev = init_etherdev(dev, sizeof(wlan_private)))) {
#else
    if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
#endif
        PRINTM(MSG, "Init ethernet device failed!\n");
        goto exit_add_err;
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
    /* Allocate device name */
    if (dev_alloc_name(dev, "mlan%d") < 0) {
        PRINTM(ERROR, "Could not allocate device name!\n");
        goto err_kmalloc;
    }
#endif

    priv = (wlan_private *) netdev_priv(dev);

    /* allocate buffer for wlan_adapter */
    if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
        PRINTM(MSG, "Allocate buffer for wlan_adapter failed!\n");
        goto err_kmalloc;
    }

    /* init wlan_adapter */
    memset(priv->adapter, 0, sizeof(wlan_adapter));

    priv->wlan_dev.netdev = dev;
    priv->wlan_dev.card = card;
    ((struct sdio_mmc_card *) card)->priv = priv;
    wlanpriv = priv; //XXX FB global var a virer ?

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
    SET_MODULE_OWNER(dev);
#endif

    /* Setup the OS Interface to our functions */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
    dev->open = wlan_open;
    dev->hard_start_xmit = wlan_hard_start_xmit;
    dev->stop = wlan_close;
    dev->do_ioctl = wlan_do_ioctl;
    dev->set_mac_address = wlan_set_mac_address;
    dev->set_multicast_list = wlan_set_multicast_list;
    dev->tx_timeout = wlan_tx_timeout;
    dev->get_stats = wlan_get_stats;
#else
    dev->netdev_ops = &wlan_netdev_ops;
#endif
    dev->watchdog_timeo = MRVDRV_DEFAULT_WATCHDOG_TIMEOUT;
    dev->hard_header_len += sizeof(TxPD);
    dev->hard_header_len += SDIO_HEADER_LEN;
    dev->hard_header_len += HEADER_ALIGNMENT;

#ifdef  WIRELESS_EXT
#if WIRELESS_EXT < 21
    dev->get_wireless_stats = wlan_get_wireless_stats;
#endif
    dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
    dev->features |= NETIF_F_DYNALLOC;
#endif
    dev->flags |= IFF_BROADCAST | IFF_MULTICAST;

    /* init SW */
    if (wlan_init_sw(priv)) {
        PRINTM(FATAL, "Software Init Failed\n");
        goto err_kmalloc;
    }

    PRINTM(INFO, "Starting kthread...\n");
    priv->MainThread.priv = priv;
    wlan_create_thread(wlan_service_main_thread,
                       &priv->MainThread, "wlan_main_service");

    ConfigureThreadPriority();

#ifdef REASSOCIATION
    priv->ReassocThread.priv = priv;
    wlan_create_thread(wlan_reassociation_thread,
                       &priv->ReassocThread, "wlan_reassoc_service");
#endif /* REASSOCIATION */

    while ((priv->MainThread.pid == 0)
#ifdef REASSOCIATION
           || (priv->ReassocThread.pid == 0)
#endif
        ) {
        os_sched_timeout(2);
    }

    /* 
     * Register the device. Fill up the private data structure with
     * relevant information from the card and request for the required
     * IRQ. 
     */

    if (sbi_register_dev(priv) < 0) {
        PRINTM(FATAL, "Failed to register wlan device!\n");
        goto err_registerdev;
    }

    SET_NETDEV_DEV(dev, priv->hotplug_device);

    /* init FW and HW */
    if (wlan_init_fw(priv)) {
        PRINTM(FATAL, "Firmware Init Failed\n");
        goto err_init_fw;
    }
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33)
    SET_NETDEV_DEVTYPE(dev, &wlan_type);
#endif

#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    if (register_netdev(dev)) {
        printk(KERN_ERR "Cannot register network device!\n");
        goto err_init_fw;
    }
#endif
    os_carrier_off(priv);
    os_stop_queue(priv);

    PRINTM(INFO, "%s: WLAN 802.11 Adapter revision 0x%02X\n",
           dev->name, priv->adapter->chip_rev);

#ifdef CONFIG_PROC_FS
    wlan_proc_entry(priv, dev);
#ifdef PROC_DEBUG
    wlan_debug_entry(priv, dev);
#endif
#endif /* CONFIG_PROC_FS */

    OS_REL_SEMAPHORE(&AddRemoveCardSem);
    LEAVE();
    return priv;

  err_init_fw:
    sbi_unregister_dev(priv);

  err_registerdev:
    priv->adapter->SurpriseRemoved = TRUE;
    if (priv->MainThread.pid) {
        /* Stop the thread servicing the interrupts */
        wake_up_interruptible(&priv->MainThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->MainThread);
#endif
    }
#ifdef REASSOCIATION
    if (priv->ReassocThread.pid) {
        wake_up_interruptible(&priv->ReassocThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->ReassocThread);
#endif
    }
#endif /* REASSOCIATION */

    /* waiting for main thread quit */
    while (priv->MainThread.pid
#ifdef REASSOCIATION
           || priv->ReassocThread.pid
#endif
        ) {
        os_sched_timeout(2);
    }
  err_kmalloc:
    if (dev->reg_state == NETREG_REGISTERED)
        unregister_netdev(dev);
    wlan_free_adapter(priv);
    priv->wlan_dev.netdev = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    free_netdev(dev);
#endif
    ((struct sdio_mmc_card *) card)->priv = NULL;
    wlanpriv = NULL;

  exit_add_err:
    OS_REL_SEMAPHORE(&AddRemoveCardSem);
  exit_sem_err:
    LEAVE();
    return NULL;
}

/** 
 *  @brief This function removes the card.
 *  
 *  @param card    A pointer to card
 *  @return        WLAN_STATUS_SUCCESS
 */
int
wlan_remove_card(void *card)
{
    wlan_private *priv = ((struct sdio_mmc_card *) card)->priv;
    wlan_adapter *Adapter = NULL;
    struct net_device *dev;
    union iwreq_data wrqu;

    ENTER();

    if (OS_ACQ_SEMAPHORE_BLOCK(&AddRemoveCardSem))
        goto exit_sem_err;

    if (!priv || !(Adapter = priv->adapter))
        goto exit_remove;

    Adapter->SurpriseRemoved = TRUE;

#ifdef REASSOCIATION
    if (Adapter->ReassocTimerIsSet == TRUE) {
        wlan_cancel_timer(&Adapter->MrvDrvTimer);
        Adapter->ReassocTimerIsSet = FALSE;
    }
#endif

    if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
        Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
        memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
        wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
        wlan_clean_txrx(priv);
    }

    /* Release all pending commands */
    wlan_clear_pending_cmd(priv);

    dev = priv->wlan_dev.netdev;
    /* Last reference is our one */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)
    PRINTM(INFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
#else
    PRINTM(INFO, "refcnt = %d\n", netdev_refcnt_read(dev));
#endif

    PRINTM(INFO, "netdev_finish_unregister: %s\n", dev->name);
    if (dev->reg_state == NETREG_REGISTERED)
        unregister_netdev(dev);
    PRINTM(INFO, "Unregister finish\n");

    if (priv->MainThread.pid) {
        /* Stop the thread servicing the interrupts */
        wake_up_interruptible(&priv->MainThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->MainThread);
#endif
    }
#ifdef REASSOCIATION
    if (priv->ReassocThread.pid) {
        wake_up_interruptible(&priv->ReassocThread.waitQ);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
        wlan_terminate_thread(&priv->ReassocThread);
#endif
    }
#endif /* REASSOCIATION */

    /* waiting for thread quit */
    while (priv->MainThread.pid
#ifdef REASSOCIATION
           || priv->ReassocThread.pid
#endif
        ) {
        os_sched_timeout(1);
    }

    wake_up_interruptible(&Adapter->HS_wait_q);

    if (Adapter->IsDeepSleep == TRUE) {
        Adapter->IsDeepSleep = FALSE;
        wake_up_interruptible(&Adapter->ds_awake_q);
    }

#ifdef CONFIG_PROC_FS
#ifdef PROC_DEBUG
    wlan_debug_remove(priv);
#endif
    wlan_proc_remove(priv);
#endif

    PRINTM(INFO, "unregister device\n");
    sbi_unregister_dev(priv);

    PRINTM(INFO, "Free Adapter\n");
    wlan_free_adapter(priv);
    priv->wlan_dev.netdev = NULL;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
    free_netdev(dev);
#endif
    wlanpriv = NULL;

  exit_remove:
    OS_REL_SEMAPHORE(&AddRemoveCardSem);

  exit_sem_err:
    LEAVE();
    return WLAN_STATUS_SUCCESS;
}
Exemple #2
0
//static 
wlan_private *
wlan_add_card(void *card)
{
    //struct net_device *dev = NULL;
    wlan_private *priv = NULL;
	//struct eth_drv_sc *dev;

    ENTER();

    /* probe the card */
    if (sbi_probe_card(card) < 0) {
        diag_printf("NO card found!\n");
        return NULL;
    }
#if 0
    /* Allocate an Ethernet device and register it */
    if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
        diag_printf("Init ethernet device failed!\n");
        return NULL;
    }
#endif

    priv = (wlan_private *)((cyg_uint32)&w99702_priv_data0 | NON_CACHE_FLAG);

    /* allocate buffer for wlan_adapter */
    MALLOC(priv->adapter, wlan_adapter *, sizeof(wlan_adapter), 0, M_NOWAIT);
    if(!priv->adapter)
    {
        diag_printf("Allocate buffer for wlan_adapter failed!\n");
        goto err_kmalloc;
    }
	priv->adapter = (wlan_adapter *)((unsigned int)priv->adapter | NON_CACHE_FLAG);
    /* init wlan_adapter */
    memset(priv->adapter, 0, sizeof(wlan_adapter));

    priv->wlan_dev.netdev = &w99702_netdev;
    priv->wlan_dev.card = card;
   // wlanpriv = priv;

   // SET_MODULE_OWNER(dev);

 #if 0
    /* Setup the OS Interface to our functions */
    dev->open = wlan_open;
    dev->hard_start_xmit = wlan_hard_start_xmit;
    dev->stop = wlan_close;
    dev->do_ioctl = wlan_do_ioctl;
    dev->set_mac_address = wlan_set_mac_address;

#define	WLAN_WATCHDOG_TIMEOUT	(2 * HZ)

    dev->tx_timeout = wlan_tx_timeout;
    dev->get_stats = wlan_get_stats;
    dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT;

#ifdef	WIRELESS_EXT
    dev->get_wireless_stats = wlan_get_wireless_stats;
    dev->wireless_handlers = (struct iw_handler_def *) &wlan_handler_def;
#endif
#define NETIF_F_DYNALLOC 16
    dev->features |= NETIF_F_DYNALLOC;
    dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
    dev->set_multicast_list = wlan_set_multicast_list;

#endif//clyu



#ifdef MFG_CMD_SUPPORT
    /* Required for the mfg command */
    //init_waitqueue_head(&priv->adapter->mfg_cmd_q);
    cyg_cond_init(&priv->adapter->mfg_cond_q, &priv->adapter->mfg_mutex);
#endif

    //init_waitqueue_head(&priv->adapter->ds_awake_q);
    cyg_cond_init(&priv->adapter->ds_cond_q, &priv->adapter->ds_mutex);

#ifdef ENABLE_PM
    if (!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback)))
        diag_printf("Failed to register PM callback\n");
#endif

    INIT_LIST_HEAD(&priv->adapter->CmdFreeQ);
    INIT_LIST_HEAD(&priv->adapter->CmdPendingQ);

    diag_printf("Starting kthread...\n");
    priv->MainThread.priv = priv;
	
	cyg_thread_create(WIRELESS_THREAD_PRIORITY,          // Priority
                      wlan_service_main_thread,                   // entry
                      (cyg_addrword_t)&w99702_sc,                    // entry parameter
                      "pxa270m card support",                // Name
                      &thread_stack[0],         // Stack
                      sizeof(thread_stack),                            // Size
                      &thread_handle,    // Handle
                      &thread_data       // Thread data structure
            );
    priv->MainThread.task = thread_handle;
    cyg_thread_resume(thread_handle);    // Start it
	
//    ConfigureThreadPriority();

#ifdef REASSOCIATION
    priv->ReassocThread.priv = priv;
   /*
    wlan_create_thread(wlan_reassociation_thread,
                       &priv->ReassocThread, "wlan_reassoc_service");*/
	
	cyg_thread_create(WIRELESS_THREAD_PRIORITY,          // Priority
                      wlan_reassociation_thread,                   // entry
                      (cyg_addrword_t)&w99702_sc,                    // entry parameter
                      "wlan_reassoc_service",                // Name
                      &reassoc_stack[0],         // Stack
                      sizeof(reassoc_stack),                            // Size
                      &reassoc_handle,    // Handle
                      &reassoc_data       // Thread data structure
            );
	priv->ReassocThread.task = reassoc_handle;
    cyg_thread_resume(reassoc_handle);    // Start it
	
#endif /* REASSOCIATION */

    /*
     * Register the device. Fillup the private data structure with
     * relevant information from the card and request for the required
     * IRQ. 
     */

    if (sbi_register_dev(priv) < 0) {
        diag_printf("Failed to register wlan device!\n");
        goto err_registerdev;
    }
#if 0
    diag_printf("%s: Marvell Wlan 802.11 Adapter "
           "revision 0x%02X at IRQ %i\n", dev->name,
           priv->adapter->chip_rev, dev->irq);
#endif
    //wlan_proc_entry(priv, dev);
#ifdef PROC_DEBUG
    wlan_debug_entry(priv, dev);
#endif

#if 0
    /* Get the CIS Table */
    sbi_get_cis_info(priv);
#endif

    /* init FW and HW */
    if (wlan_init_fw(priv)) {
        diag_printf("Firmware Init Failed\n");
        goto err_init_fw;
    }
#if 0
    if (register_netdev(dev)) {
        printk(KERN_ERR "Cannot register network device!\n");
        goto err_init_fw;
    }
#endif

    LEAVE();
    return priv;

  err_init_fw:
    sbi_unregister_dev(priv);

  err_registerdev:
    /* Stop the thread servicing the interrupts */
    //wake_up_interruptible(&priv->MainThread.waitQ);

    cyg_flag_setbits( &priv->MainThread.waitQ_flag_q, 1 ); 
    wlan_terminate_thread(&priv->MainThread);

#ifdef REASSOCIATION
    //wake_up_interruptible(&priv->ReassocThread.waitQ);

    cyg_flag_setbits( &priv->ReassocThread.waitQ_flag_q, 1 ); 
    wlan_terminate_thread(&priv->ReassocThread);
#endif /* REASSOCIATION */
  err_kmalloc:
   // unregister_netdev(dev);
    FREE(priv->adapter, 0);
    //wlanpriv = NULL;

    LEAVE();
    return NULL;
}