/** * @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; }
//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; }