📄 sm_drv.c
字号:
mask &= ~SM_FRAMERX; } } if(mask & SM_TRAP) { struct s_sm_conf t; int32_t result; t.length = sizeof(long); t.data = kmalloc(t.length, GFP_ATOMIC); spin_lock_bh(&lp->sm_lock); result = prism_softmac_trap(lp->sm_context, &t); spin_unlock_bh(&lp->sm_lock); if(result == SM_EOVERFLOW) { kfree(t.data); t.data = kmalloc(t.length, GFP_ATOMIC); if(t.data != NULL) { spin_lock_bh(&lp->sm_lock); result = prism_softmac_trap(lp->sm_context, &t); spin_unlock_bh(&lp->sm_lock); } else { printk(KERN_ERR "%s: could not allocate trap data\n", driver_name); goto trap_error; } } if(result >= SM_ENONE) { mask |= result; if(t.flags & SM_CONF_OPSET) { /* This is a unsolicitated trap */ result = handle_sm_trap(dev, &t); if(result >= SM_ENONE) mask |= result; kfree(t.data); } else { /* This is a response to a GET operation */ memcpy(&lp->getresp, &t, sizeof(struct s_sm_conf)); /* Wake up the app that requested this info. * This will also free t.data. */ wake_up(&lp->getresp_waitq); } } else { mask &= ~SM_TRAP; kfree(t.data); } } trap_error: if(mask & SM_IC) { if(lp->device_state == DEVSTATE_ACTIVE || lp->device_state == DEVSTATE_BOOTING) tasklet_hi_schedule(&lp->tasklet); mask &= ~SM_IC; } }}/****************************************************************************** * Kernel API functions ******************************************************************************//* Create the net device instance that will be associated to the host interface */struct net_device *sm_drv_netdev_create(int ioaddr, int irq){ struct net_local *lp; struct net_device * netdev; DEBUG(DBG_CALLS, "sm_drv_netdev_create\n"); netdev = alloc_netdev(sizeof (struct net_local), "wlan%d", ether_setup); if (!netdev) { printk(KERN_ERR "net device not allocated\n"); return netdev; } netdev->base_addr = ioaddr; netdev->irq = irq; netdev->open = &sm_drv_open; netdev->stop = &sm_drv_close; netdev->hard_start_xmit = &sm_drv_transmit; netdev->get_stats = &sm_drv_statistics; netdev->wireless_handlers = (struct iw_handler_def *) &sm_drv_we_handler_def; netdev->watchdog_timeo = SM_DRV_TX_TIMEOUT; netdev->tx_timeout = &sm_drv_tx_timeout; netdev->type = ARPHRD_ETHER; lp = netdev->priv; memset(lp, 0, sizeof(struct net_local)); spin_lock_init(&lp->sm_lock); init_waitqueue_head(&lp->conf_waitq); init_waitqueue_head(&lp->getresp_waitq); /* Init the Softmac timer */ init_timer(&lp->softmac_timer); lp->softmac_timer.function = driver_timer_expired; lp->softmac_timer.data = (unsigned long)netdev; /* Init the scan timer */ init_timer(&lp->scan_timer); lp->scan_timer.function = send_scan_complete_timer; lp->scan_timer.data = (unsigned long)netdev; return netdev;}extern struct platform_device wlan_omap_device;extern unsigned int driver_type;int sm_drv_open(struct net_device *dev){ struct net_local *lp = dev->priv; DEBUG(DBG_CALLS, "sm_drv_open\n"); if (cx3110x_spi_start(dev) < 0) goto err_out; lp->sm_pda = sm_drv_spi_get_pda(&(wlan_omap_device.dev)); if (!lp->sm_pda) goto err_mcbsp_free_out; lp->device_state = DEVSTATE_BOOTING; lp->bss_type = DOT11_BSSTYPE_INFRA; if (sm_drv_spi_request_irq(dev) < 0) goto err_mcbsp_free_out; /* We bring the interface up */ if (lp->hif_up(dev) < 0) goto err_mcbsp_irq_free_out; /* Wait for the chip to receive its first interrupt */ wait_for_completion_interruptible(&softmac_init_comp); if (lp->sm_mode == SM_MODE_PROMISCUOUS) { uint32_t commit = 0; lp->bss_type = DOT11_BSSTYPE_NONE; if (sm_drv_oid_set(dev, GEN_OID_COMMIT, (void*)&commit, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; goto start_tcp_queue; } if (driver_type == SM_DRIVER_TYPE_UMAC) { uint32_t scan_mode = SCAN_MODE_PASSIVE; uint32_t authen = DOT11_AUTH_BOTH; uint32_t wwr_mode = DOT11_WWR_MODE_11D; /* We don't need 802.11h */ uint32_t dot11d_conformance_mode = DOT11_CONFORMANCE_FAST; uint32_t profile = DOT11_PROFILE_MIXED; uint32_t bgr_scan_disable = 0; int32_t scan_threshold = -75; uint32_t tx_lifetime = 4096, rx_lifetime = 4096; struct obj_scan scan_params = {-1, 80, 200, 20000, 80, 140}; uint32_t commit = 0; if (sm_drv_oid_set(dev, DOT11_OID_AUTHENABLE, (void *)&authen, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_SCANMODE, (void*)&scan_mode, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_WWRMODE, (void*)&wwr_mode, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_CONFORMANCEMODE, (void*)&dot11d_conformance_mode, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_PROFILES, (void*)&profile, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_AUTOSCANDISABLE, (void*)&bgr_scan_disable, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_SCANTHRESHOLD, (void*)&scan_threshold, sizeof(int32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_MAXTXLIFETIME, (void*)&tx_lifetime, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_MAXRXLIFETIME, (void*)&rx_lifetime, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; if (sm_drv_oid_set(dev, DOT11_OID_SCAN, (void*)&scan_params, sizeof(struct obj_scan)) < 0) goto err_mcbsp_irq_free_out; /* WWR mode needs to be commited */ if (sm_drv_oid_set(dev, GEN_OID_COMMIT, (void*)&commit, sizeof(uint32_t)) < 0) goto err_mcbsp_irq_free_out; } start_tcp_queue: netif_start_queue(dev); return 0; err_mcbsp_irq_free_out: sm_drv_spi_free_irq(dev); err_mcbsp_free_out: cx3110x_spi_stop(dev); err_out: return -ENXIO;}int sm_drv_close(struct net_device *dev){ struct net_local *lp = dev->priv; struct spi_hif_local_data *hif_lp = HIF_LP(lp); DEBUG(DBG_CALLS, "sm_drv_close \n"); sm_drv_disassociate(dev); netif_stop_queue(dev); /* Disable all device interrupts */ lp->hif_cli(dev); if(lp->device_state == DEVSTATE_ACTIVE || lp->device_state == DEVSTATE_BOOTING) lp->device_state = DEVSTATE_IDLE; flush_scheduled_work(); DEBUG(DBG_ALL, "Shut down SoftMAC\n"); hif_lp->initial_packets = 0; if (lp->sm_initialization) { /* shut down SoftMAC */ lp->sm_descr.mtu = 0; lp->sm_initialization = 0; hif_lp->upload_state = UPLOAD_STATE_BOOTING; prism_softmac_destroy(lp->sm_context); } lp->hif_down(dev); sm_drv_spi_free_irq(dev); cx3110x_spi_stop(dev); return 0;}int sm_drv_transmit(struct sk_buff *skb, struct net_device *dev){ struct s_sm_frame *frame; struct net_local *lp = dev->priv; int32_t callb_mask; DEBUG(DBG_CALLS, "sm_drv_transmit\n"); again: if(lp->queued_tx_frame) { frame = lp->queued_tx_frame; } else { frame = skb_to_frame(dev, skb); if(!frame) { printk(KERN_ERR "sm_drv_transmit: Could not allocate frame for skb\n"); dev_kfree_skb(skb); lp->stats.tx_errors++; goto out; } } spin_lock_bh(&lp->sm_lock); callb_mask = prism_softmac_frame_tx( lp->sm_context, frame ); spin_unlock_bh(&lp->sm_lock); if(callb_mask < 0) { if(callb_mask == SM_EOVERFLOW) { printk("sm_drv_transmit: Overflow, stopping TX queue\n"); printk(KERN_WARNING "sm_drv_transmit: Overflow, stopping TX queue\n"); /* We have to accept the packet, otherwise it gets lost. So we * temporarily store it and stop the queue. We retry this packet * once we have a sm_frame_tx_done */ lp->queued_tx_frame = frame; netif_stop_queue(dev); } else { printk("sm_drv_transmit: sm_frame_tx returned error %d\n", callb_mask); /* a normal frame failed, increment the parents device error counter */ lp->stats.tx_errors++; /* Free the frame and the sk_buff */ frame_skb_free(dev, frame); if(lp->queued_tx_frame) { lp->queued_tx_frame = NULL; } } goto out; } dev->trans_start = jiffies; handle_sm_callback(dev, callb_mask); /* If we transmitted a queued frame, now try to transmit the current frame */ if(lp->queued_tx_frame) { lp->queued_tx_frame = NULL; goto again; } out: return 0;}void sm_drv_tx_timeout(struct net_device *dev){ struct net_local *lp = dev->priv; struct net_device_stats *statistics = &lp->stats; DEBUG(DBG_CALLS, "sm_drv_tx_timeout \n"); /* increment the transmit error counter */ statistics->tx_errors++; netif_wake_queue(dev); return;}struct net_device_stats *sm_drv_statistics(struct net_device *dev){ struct net_local *lp = dev->priv; DEBUG(DBG_CALLS, "sm_drv_statistics \n"); return &lp->stats;}int sm_drv_reset(struct net_device *dev, uint8_t sm_mode){ struct net_local *lp = dev->priv; int ret; if(lp->device_state == DEVSTATE_IDLE) { printk(KERN_INFO "sm_srv_reset: Cannot reset device in Idle state\n"); return -1; } lp->sm_mode = sm_mode; ret = sm_drv_close(dev); if(ret == 0) { ret = sm_drv_open(dev); } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -