aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2005-06-18 19:27:33 -0400
committerJeff Garzik <jgarzik@pobox.com>2005-06-27 00:23:54 -0400
commit620554e406e3cc01434c658a1e597162d7e56fd6 (patch)
treec78c04de8b3809927de6ac0721a3cf5d2a4de8a6 /drivers/net/wireless/orinoco.c
parent5d558b7f36cc577d31b770d8987681ec6e6545e7 (diff)
[PATCH] orinoco: wireless API 15 support
(patch from Moustafa Youssef, updated by Jim Carter and Pavel Roskin).
Diffstat (limited to 'drivers/net/wireless/orinoco.c')
-rw-r--r--drivers/net/wireless/orinoco.c1118
1 files changed, 547 insertions, 571 deletions
diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c
index 7cf3b9822792..0e1edce91021 100644
--- a/drivers/net/wireless/orinoco.c
+++ b/drivers/net/wireless/orinoco.c
@@ -463,6 +463,7 @@
463#include <linux/if_arp.h> 463#include <linux/if_arp.h>
464#include <linux/etherdevice.h> 464#include <linux/etherdevice.h>
465#include <linux/wireless.h> 465#include <linux/wireless.h>
466#include <net/iw_handler.h>
466#include <net/ieee80211.h> 467#include <net/ieee80211.h>
467 468
468#include <asm/uaccess.h> 469#include <asm/uaccess.h>
@@ -538,6 +539,10 @@ MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer
538 | HERMES_EV_WTERR | HERMES_EV_INFO \ 539 | HERMES_EV_WTERR | HERMES_EV_INFO \
539 | HERMES_EV_INFDROP ) 540 | HERMES_EV_INFDROP )
540 541
542#define MAX_RID_LEN 1024
543
544static const struct iw_handler_def orinoco_handler_def;
545
541/********************************************************************/ 546/********************************************************************/
542/* Data tables */ 547/* Data tables */
543/********************************************************************/ 548/********************************************************************/
@@ -605,7 +610,6 @@ struct hermes_rx_descriptor {
605/* Function prototypes */ 610/* Function prototypes */
606/********************************************************************/ 611/********************************************************************/
607 612
608static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
609static int __orinoco_program_rids(struct net_device *dev); 613static int __orinoco_program_rids(struct net_device *dev);
610static void __orinoco_set_multicast_list(struct net_device *dev); 614static void __orinoco_set_multicast_list(struct net_device *dev);
611 615
@@ -1870,55 +1874,6 @@ __orinoco_set_multicast_list(struct net_device *dev)
1870 dev->flags &= ~IFF_PROMISC; 1874 dev->flags &= ~IFF_PROMISC;
1871} 1875}
1872 1876
1873static int orinoco_reconfigure(struct net_device *dev)
1874{
1875 struct orinoco_private *priv = netdev_priv(dev);
1876 struct hermes *hw = &priv->hw;
1877 unsigned long flags;
1878 int err = 0;
1879
1880 if (priv->broken_disableport) {
1881 schedule_work(&priv->reset_work);
1882 return 0;
1883 }
1884
1885 if (orinoco_lock(priv, &flags) != 0)
1886 return -EBUSY;
1887
1888 err = hermes_disable_port(hw, 0);
1889 if (err) {
1890 printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
1891 dev->name);
1892 priv->broken_disableport = 1;
1893 goto out;
1894 }
1895
1896 err = __orinoco_program_rids(dev);
1897 if (err) {
1898 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
1899 dev->name);
1900 goto out;
1901 }
1902
1903 err = hermes_enable_port(hw, 0);
1904 if (err) {
1905 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
1906 dev->name);
1907 goto out;
1908 }
1909
1910 out:
1911 if (err) {
1912 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
1913 schedule_work(&priv->reset_work);
1914 err = 0;
1915 }
1916
1917 orinoco_unlock(priv, &flags);
1918 return err;
1919
1920}
1921
1922/* This must be called from user context, without locks held - use 1877/* This must be called from user context, without locks held - use
1923 * schedule_work() */ 1878 * schedule_work() */
1924static void orinoco_reset(struct net_device *dev) 1879static void orinoco_reset(struct net_device *dev)
@@ -2458,7 +2413,7 @@ struct net_device *alloc_orinocodev(int sizeof_card,
2458 dev->watchdog_timeo = HZ; /* 1 second timeout */ 2413 dev->watchdog_timeo = HZ; /* 1 second timeout */
2459 dev->get_stats = orinoco_get_stats; 2414 dev->get_stats = orinoco_get_stats;
2460 dev->get_wireless_stats = orinoco_get_wireless_stats; 2415 dev->get_wireless_stats = orinoco_get_wireless_stats;
2461 dev->do_ioctl = orinoco_ioctl; 2416 dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
2462 dev->change_mtu = orinoco_change_mtu; 2417 dev->change_mtu = orinoco_change_mtu;
2463 dev->set_multicast_list = orinoco_set_multicast_list; 2418 dev->set_multicast_list = orinoco_set_multicast_list;
2464 /* we use the default eth_mac_addr for setting the MAC addr */ 2419 /* we use the default eth_mac_addr for setting the MAC addr */
@@ -2491,24 +2446,6 @@ void free_orinocodev(struct net_device *dev)
2491/* Wireless extensions */ 2446/* Wireless extensions */
2492/********************************************************************/ 2447/********************************************************************/
2493 2448
2494static int orinoco_hw_get_bssid(struct orinoco_private *priv,
2495 char buf[ETH_ALEN])
2496{
2497 hermes_t *hw = &priv->hw;
2498 int err = 0;
2499 unsigned long flags;
2500
2501 if (orinoco_lock(priv, &flags) != 0)
2502 return -EBUSY;
2503
2504 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
2505 ETH_ALEN, NULL, buf);
2506
2507 orinoco_unlock(priv, &flags);
2508
2509 return err;
2510}
2511
2512static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, 2449static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
2513 char buf[IW_ESSID_MAX_SIZE+1]) 2450 char buf[IW_ESSID_MAX_SIZE+1])
2514{ 2451{
@@ -2634,140 +2571,201 @@ static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
2634 return 0; 2571 return 0;
2635} 2572}
2636 2573
2637static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq) 2574static int orinoco_ioctl_getname(struct net_device *dev,
2575 struct iw_request_info *info,
2576 char *name,
2577 char *extra)
2638{ 2578{
2639 struct orinoco_private *priv = netdev_priv(dev); 2579 struct orinoco_private *priv = netdev_priv(dev);
2640 int err = 0;
2641 int mode;
2642 struct iw_range range;
2643 int numrates; 2580 int numrates;
2644 int i, k; 2581 int err;
2582
2583 err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
2584
2585 if (!err && (numrates > 2))
2586 strcpy(name, "IEEE 802.11b");
2587 else
2588 strcpy(name, "IEEE 802.11-DS");
2589
2590 return 0;
2591}
2592
2593static int orinoco_ioctl_getwap(struct net_device *dev,
2594 struct iw_request_info *info,
2595 struct sockaddr *ap_addr,
2596 char *extra)
2597{
2598 struct orinoco_private *priv = netdev_priv(dev);
2599
2600 hermes_t *hw = &priv->hw;
2601 int err = 0;
2645 unsigned long flags; 2602 unsigned long flags;
2646 2603
2647 TRACE_ENTER(dev->name); 2604 if (orinoco_lock(priv, &flags) != 0)
2605 return -EBUSY;
2648 2606
2649 if (!access_ok(VERIFY_WRITE, rrq->pointer, sizeof(range))) 2607 ap_addr->sa_family = ARPHRD_ETHER;
2650 return -EFAULT; 2608 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
2609 ETH_ALEN, NULL, ap_addr->sa_data);
2651 2610
2652 rrq->length = sizeof(range); 2611 orinoco_unlock(priv, &flags);
2612
2613 return err;
2614}
2615
2616static int orinoco_ioctl_setmode(struct net_device *dev,
2617 struct iw_request_info *info,
2618 u32 *mode,
2619 char *extra)
2620{
2621 struct orinoco_private *priv = netdev_priv(dev);
2622 int err = -EINPROGRESS; /* Call commit handler */
2623 unsigned long flags;
2624
2625 if (priv->iw_mode == *mode)
2626 return 0;
2653 2627
2654 if (orinoco_lock(priv, &flags) != 0) 2628 if (orinoco_lock(priv, &flags) != 0)
2655 return -EBUSY; 2629 return -EBUSY;
2656 2630
2657 mode = priv->iw_mode; 2631 switch (*mode) {
2632 case IW_MODE_ADHOC:
2633 if (!priv->has_ibss && !priv->has_port3)
2634 err = -EOPNOTSUPP;
2635 break;
2636
2637 case IW_MODE_INFRA:
2638 break;
2639
2640 default:
2641 err = -EOPNOTSUPP;
2642 break;
2643 }
2644
2645 if (err == -EINPROGRESS) {
2646 priv->iw_mode = *mode;
2647 set_port_type(priv);
2648 }
2649
2658 orinoco_unlock(priv, &flags); 2650 orinoco_unlock(priv, &flags);
2659 2651
2660 memset(&range, 0, sizeof(range)); 2652 return err;
2653}
2654
2655static int orinoco_ioctl_getmode(struct net_device *dev,
2656 struct iw_request_info *info,
2657 u32 *mode,
2658 char *extra)
2659{
2660 struct orinoco_private *priv = netdev_priv(dev);
2661 2661
2662 /* Much of this shamelessly taken from wvlan_cs.c. No idea 2662 *mode = priv->iw_mode;
2663 * what it all means -dgibson */ 2663 return 0;
2664 range.we_version_compiled = WIRELESS_EXT; 2664}
2665 range.we_version_source = 11;
2666 2665
2667 range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ 2666static int orinoco_ioctl_getiwrange(struct net_device *dev,
2667 struct iw_request_info *info,
2668 struct iw_point *rrq,
2669 char *extra)
2670{
2671 struct orinoco_private *priv = netdev_priv(dev);
2672 int err = 0;
2673 struct iw_range *range = (struct iw_range *) extra;
2674 int numrates;
2675 int i, k;
2676
2677 TRACE_ENTER(dev->name);
2678
2679 rrq->length = sizeof(struct iw_range);
2680 memset(range, 0, sizeof(struct iw_range));
2681
2682 range->we_version_compiled = WIRELESS_EXT;
2683 range->we_version_source = 14;
2668 2684
2669 /* Set available channels/frequencies */ 2685 /* Set available channels/frequencies */
2670 range.num_channels = NUM_CHANNELS; 2686 range->num_channels = NUM_CHANNELS;
2671 k = 0; 2687 k = 0;
2672 for (i = 0; i < NUM_CHANNELS; i++) { 2688 for (i = 0; i < NUM_CHANNELS; i++) {
2673 if (priv->channel_mask & (1 << i)) { 2689 if (priv->channel_mask & (1 << i)) {
2674 range.freq[k].i = i + 1; 2690 range->freq[k].i = i + 1;
2675 range.freq[k].m = channel_frequency[i] * 100000; 2691 range->freq[k].m = channel_frequency[i] * 100000;
2676 range.freq[k].e = 1; 2692 range->freq[k].e = 1;
2677 k++; 2693 k++;
2678 } 2694 }
2679 2695
2680 if (k >= IW_MAX_FREQUENCIES) 2696 if (k >= IW_MAX_FREQUENCIES)
2681 break; 2697 break;
2682 } 2698 }
2683 range.num_frequency = k; 2699 range->num_frequency = k;
2700 range->sensitivity = 3;
2684 2701
2685 range.sensitivity = 3; 2702 if (priv->has_wep) {
2703 range->max_encoding_tokens = ORINOCO_MAX_KEYS;
2704 range->encoding_size[0] = SMALL_KEY_SIZE;
2705 range->num_encoding_sizes = 1;
2686 2706
2687 if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){ 2707 if (priv->has_big_wep) {
2708 range->encoding_size[1] = LARGE_KEY_SIZE;
2709 range->num_encoding_sizes = 2;
2710 }
2711 }
2712
2713 if ((priv->iw_mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
2688 /* Quality stats meaningless in ad-hoc mode */ 2714 /* Quality stats meaningless in ad-hoc mode */
2689 range.max_qual.qual = 0;
2690 range.max_qual.level = 0;
2691 range.max_qual.noise = 0;
2692 range.avg_qual.qual = 0;
2693 range.avg_qual.level = 0;
2694 range.avg_qual.noise = 0;
2695 } else { 2715 } else {
2696 range.max_qual.qual = 0x8b - 0x2f; 2716 range->max_qual.qual = 0x8b - 0x2f;
2697 range.max_qual.level = 0x2f - 0x95 - 1; 2717 range->max_qual.level = 0x2f - 0x95 - 1;
2698 range.max_qual.noise = 0x2f - 0x95 - 1; 2718 range->max_qual.noise = 0x2f - 0x95 - 1;
2699 /* Need to get better values */ 2719 /* Need to get better values */
2700 range.avg_qual.qual = 0x24; 2720 range->avg_qual.qual = 0x24;
2701 range.avg_qual.level = 0xC2; 2721 range->avg_qual.level = 0xC2;
2702 range.avg_qual.noise = 0x9E; 2722 range->avg_qual.noise = 0x9E;
2703 } 2723 }
2704 2724
2705 err = orinoco_hw_get_bitratelist(priv, &numrates, 2725 err = orinoco_hw_get_bitratelist(priv, &numrates,
2706 range.bitrate, IW_MAX_BITRATES); 2726 range->bitrate, IW_MAX_BITRATES);
2707 if (err) 2727 if (err)
2708 return err; 2728 return err;
2709 range.num_bitrates = numrates; 2729 range->num_bitrates = numrates;
2710 2730
2711 /* Set an indication of the max TCP throughput in bit/s that we can 2731 /* Set an indication of the max TCP throughput in bit/s that we can
2712 * expect using this interface. May be use for QoS stuff... 2732 * expect using this interface. May be use for QoS stuff...
2713 * Jean II */ 2733 * Jean II */
2714 if(numrates > 2) 2734 if (numrates > 2)
2715 range.throughput = 5 * 1000 * 1000; /* ~5 Mb/s */ 2735 range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
2716 else 2736 else
2717 range.throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */ 2737 range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
2718 2738
2719 range.min_rts = 0; 2739 range->min_rts = 0;
2720 range.max_rts = 2347; 2740 range->max_rts = 2347;
2721 range.min_frag = 256; 2741 range->min_frag = 256;
2722 range.max_frag = 2346; 2742 range->max_frag = 2346;
2723 2743
2724 if (orinoco_lock(priv, &flags) != 0) 2744 range->min_pmp = 0;
2725 return -EBUSY; 2745 range->max_pmp = 65535000;
2726 if (priv->has_wep) { 2746 range->min_pmt = 0;
2727 range.max_encoding_tokens = ORINOCO_MAX_KEYS; 2747 range->max_pmt = 65535 * 1000; /* ??? */
2728 2748 range->pmp_flags = IW_POWER_PERIOD;
2729 range.encoding_size[0] = SMALL_KEY_SIZE; 2749 range->pmt_flags = IW_POWER_TIMEOUT;
2730 range.num_encoding_sizes = 1; 2750 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
2731 2751
2732 if (priv->has_big_wep) { 2752 range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
2733 range.encoding_size[1] = LARGE_KEY_SIZE; 2753 range->retry_flags = IW_RETRY_LIMIT;
2734 range.num_encoding_sizes = 2; 2754 range->r_time_flags = IW_RETRY_LIFETIME;
2735 } 2755 range->min_retry = 0;
2736 } else { 2756 range->max_retry = 65535; /* ??? */
2737 range.num_encoding_sizes = 0; 2757 range->min_r_time = 0;
2738 range.max_encoding_tokens = 0; 2758 range->max_r_time = 65535 * 1000; /* ??? */
2739 }
2740 orinoco_unlock(priv, &flags);
2741
2742 range.min_pmp = 0;
2743 range.max_pmp = 65535000;
2744 range.min_pmt = 0;
2745 range.max_pmt = 65535 * 1000; /* ??? */
2746 range.pmp_flags = IW_POWER_PERIOD;
2747 range.pmt_flags = IW_POWER_TIMEOUT;
2748 range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
2749
2750 range.num_txpower = 1;
2751 range.txpower[0] = 15; /* 15dBm */
2752 range.txpower_capa = IW_TXPOW_DBM;
2753
2754 range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
2755 range.retry_flags = IW_RETRY_LIMIT;
2756 range.r_time_flags = IW_RETRY_LIFETIME;
2757 range.min_retry = 0;
2758 range.max_retry = 65535; /* ??? */
2759 range.min_r_time = 0;
2760 range.max_r_time = 65535 * 1000; /* ??? */
2761
2762 if (copy_to_user(rrq->pointer, &range, sizeof(range)))
2763 return -EFAULT;
2764 2759
2765 TRACE_EXIT(dev->name); 2760 TRACE_EXIT(dev->name);
2766 2761
2767 return 0; 2762 return 0;
2768} 2763}
2769 2764
2770static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq) 2765static int orinoco_ioctl_setiwencode(struct net_device *dev,
2766 struct iw_request_info *info,
2767 struct iw_point *erq,
2768 char *keybuf)
2771{ 2769{
2772 struct orinoco_private *priv = netdev_priv(dev); 2770 struct orinoco_private *priv = netdev_priv(dev);
2773 int index = (erq->flags & IW_ENCODE_INDEX) - 1; 2771 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
@@ -2775,8 +2773,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
2775 int enable = priv->wep_on; 2773 int enable = priv->wep_on;
2776 int restricted = priv->wep_restrict; 2774 int restricted = priv->wep_restrict;
2777 u16 xlen = 0; 2775 u16 xlen = 0;
2778 int err = 0; 2776 int err = -EINPROGRESS; /* Call commit handler */
2779 char keybuf[ORINOCO_MAX_KEY_SIZE];
2780 unsigned long flags; 2777 unsigned long flags;
2781 2778
2782 if (! priv->has_wep) 2779 if (! priv->has_wep)
@@ -2789,9 +2786,6 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
2789 2786
2790 if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep ) 2787 if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
2791 return -E2BIG; 2788 return -E2BIG;
2792
2793 if (copy_from_user(keybuf, erq->pointer, erq->length))
2794 return -EFAULT;
2795 } 2789 }
2796 2790
2797 if (orinoco_lock(priv, &flags) != 0) 2791 if (orinoco_lock(priv, &flags) != 0)
@@ -2865,12 +2859,14 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *er
2865 return err; 2859 return err;
2866} 2860}
2867 2861
2868static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq) 2862static int orinoco_ioctl_getiwencode(struct net_device *dev,
2863 struct iw_request_info *info,
2864 struct iw_point *erq,
2865 char *keybuf)
2869{ 2866{
2870 struct orinoco_private *priv = netdev_priv(dev); 2867 struct orinoco_private *priv = netdev_priv(dev);
2871 int index = (erq->flags & IW_ENCODE_INDEX) - 1; 2868 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
2872 u16 xlen = 0; 2869 u16 xlen = 0;
2873 char keybuf[ORINOCO_MAX_KEY_SIZE];
2874 unsigned long flags; 2870 unsigned long flags;
2875 2871
2876 if (! priv->has_wep) 2872 if (! priv->has_wep)
@@ -2899,51 +2895,47 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *er
2899 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); 2895 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
2900 2896
2901 orinoco_unlock(priv, &flags); 2897 orinoco_unlock(priv, &flags);
2902
2903 if (erq->pointer) {
2904 if (copy_to_user(erq->pointer, keybuf, xlen))
2905 return -EFAULT;
2906 }
2907
2908 return 0; 2898 return 0;
2909} 2899}
2910 2900
2911static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq) 2901static int orinoco_ioctl_setessid(struct net_device *dev,
2902 struct iw_request_info *info,
2903 struct iw_point *erq,
2904 char *essidbuf)
2912{ 2905{
2913 struct orinoco_private *priv = netdev_priv(dev); 2906 struct orinoco_private *priv = netdev_priv(dev);
2914 char essidbuf[IW_ESSID_MAX_SIZE+1];
2915 unsigned long flags; 2907 unsigned long flags;
2916 2908
2917 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it 2909 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
2918 * anyway... - Jean II */ 2910 * anyway... - Jean II */
2919 2911
2920 memset(&essidbuf, 0, sizeof(essidbuf)); 2912 /* Hum... Should not use Wireless Extension constant (may change),
2921 2913 * should use our own... - Jean II */
2922 if (erq->flags) { 2914 if (erq->length > IW_ESSID_MAX_SIZE)
2923 /* iwconfig includes the NUL in the specified length */ 2915 return -E2BIG;
2924 if (erq->length > IW_ESSID_MAX_SIZE+1)
2925 return -E2BIG;
2926
2927 if (copy_from_user(&essidbuf, erq->pointer, erq->length))
2928 return -EFAULT;
2929
2930 essidbuf[IW_ESSID_MAX_SIZE] = '\0';
2931 }
2932 2916
2933 if (orinoco_lock(priv, &flags) != 0) 2917 if (orinoco_lock(priv, &flags) != 0)
2934 return -EBUSY; 2918 return -EBUSY;
2935 2919
2936 memcpy(priv->desired_essid, essidbuf, sizeof(priv->desired_essid)); 2920 /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
2921 memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
2922
2923 /* If not ANY, get the new ESSID */
2924 if (erq->flags) {
2925 memcpy(priv->desired_essid, essidbuf, erq->length);
2926 }
2937 2927
2938 orinoco_unlock(priv, &flags); 2928 orinoco_unlock(priv, &flags);
2939 2929
2940 return 0; 2930 return -EINPROGRESS; /* Call commit handler */
2941} 2931}
2942 2932
2943static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq) 2933static int orinoco_ioctl_getessid(struct net_device *dev,
2934 struct iw_request_info *info,
2935 struct iw_point *erq,
2936 char *essidbuf)
2944{ 2937{
2945 struct orinoco_private *priv = netdev_priv(dev); 2938 struct orinoco_private *priv = netdev_priv(dev);
2946 char essidbuf[IW_ESSID_MAX_SIZE+1];
2947 int active; 2939 int active;
2948 int err = 0; 2940 int err = 0;
2949 unsigned long flags; 2941 unsigned long flags;
@@ -2957,51 +2949,46 @@ static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
2957 } else { 2949 } else {
2958 if (orinoco_lock(priv, &flags) != 0) 2950 if (orinoco_lock(priv, &flags) != 0)
2959 return -EBUSY; 2951 return -EBUSY;
2960 memcpy(essidbuf, priv->desired_essid, sizeof(essidbuf)); 2952 memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE + 1);
2961 orinoco_unlock(priv, &flags); 2953 orinoco_unlock(priv, &flags);
2962 } 2954 }
2963 2955
2964 erq->flags = 1; 2956 erq->flags = 1;
2965 erq->length = strlen(essidbuf) + 1; 2957 erq->length = strlen(essidbuf) + 1;
2966 if (erq->pointer)
2967 if (copy_to_user(erq->pointer, essidbuf, erq->length))
2968 return -EFAULT;
2969 2958
2970 TRACE_EXIT(dev->name); 2959 TRACE_EXIT(dev->name);
2971 2960
2972 return 0; 2961 return 0;
2973} 2962}
2974 2963
2975static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq) 2964static int orinoco_ioctl_setnick(struct net_device *dev,
2965 struct iw_request_info *info,
2966 struct iw_point *nrq,
2967 char *nickbuf)
2976{ 2968{
2977 struct orinoco_private *priv = netdev_priv(dev); 2969 struct orinoco_private *priv = netdev_priv(dev);
2978 char nickbuf[IW_ESSID_MAX_SIZE+1];
2979 unsigned long flags; 2970 unsigned long flags;
2980 2971
2981 if (nrq->length > IW_ESSID_MAX_SIZE) 2972 if (nrq->length > IW_ESSID_MAX_SIZE)
2982 return -E2BIG; 2973 return -E2BIG;
2983 2974
2984 memset(nickbuf, 0, sizeof(nickbuf));
2985
2986 if (copy_from_user(nickbuf, nrq->pointer, nrq->length))
2987 return -EFAULT;
2988
2989 nickbuf[nrq->length] = '\0';
2990
2991 if (orinoco_lock(priv, &flags) != 0) 2975 if (orinoco_lock(priv, &flags) != 0)
2992 return -EBUSY; 2976 return -EBUSY;
2993 2977
2994 memcpy(priv->nick, nickbuf, sizeof(priv->nick)); 2978 memset(priv->nick, 0, sizeof(priv->nick));
2979 memcpy(priv->nick, nickbuf, nrq->length);
2995 2980
2996 orinoco_unlock(priv, &flags); 2981 orinoco_unlock(priv, &flags);
2997 2982
2998 return 0; 2983 return -EINPROGRESS; /* Call commit handler */
2999} 2984}
3000 2985
3001static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq) 2986static int orinoco_ioctl_getnick(struct net_device *dev,
2987 struct iw_request_info *info,
2988 struct iw_point *nrq,
2989 char *nickbuf)
3002{ 2990{
3003 struct orinoco_private *priv = netdev_priv(dev); 2991 struct orinoco_private *priv = netdev_priv(dev);
3004 char nickbuf[IW_ESSID_MAX_SIZE+1];
3005 unsigned long flags; 2992 unsigned long flags;
3006 2993
3007 if (orinoco_lock(priv, &flags) != 0) 2994 if (orinoco_lock(priv, &flags) != 0)
@@ -3012,17 +2999,18 @@ static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
3012 2999
3013 nrq->length = strlen(nickbuf)+1; 3000 nrq->length = strlen(nickbuf)+1;
3014 3001
3015 if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf)))
3016 return -EFAULT;
3017
3018 return 0; 3002 return 0;
3019} 3003}
3020 3004
3021static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq) 3005static int orinoco_ioctl_setfreq(struct net_device *dev,
3006 struct iw_request_info *info,
3007 struct iw_freq *frq,
3008 char *extra)
3022{ 3009{
3023 struct orinoco_private *priv = netdev_priv(dev); 3010 struct orinoco_private *priv = netdev_priv(dev);
3024 int chan = -1; 3011 int chan = -1;
3025 unsigned long flags; 3012 unsigned long flags;
3013 int err = -EINPROGRESS; /* Call commit handler */
3026 3014
3027 /* We can only use this in Ad-Hoc demo mode to set the operating 3015 /* We can only use this in Ad-Hoc demo mode to set the operating
3028 * frequency, or in IBSS mode to set the frequency where the IBSS 3016 * frequency, or in IBSS mode to set the frequency where the IBSS
@@ -3055,10 +3043,33 @@ static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
3055 priv->channel = chan; 3043 priv->channel = chan;
3056 orinoco_unlock(priv, &flags); 3044 orinoco_unlock(priv, &flags);
3057 3045
3046 return err;
3047}
3048
3049static int orinoco_ioctl_getfreq(struct net_device *dev,
3050 struct iw_request_info *info,
3051 struct iw_freq *frq,
3052 char *extra)
3053{
3054 struct orinoco_private *priv = netdev_priv(dev);
3055 int tmp;
3056
3057 /* Locking done in there */
3058 tmp = orinoco_hw_get_freq(priv);
3059 if (tmp < 0) {
3060 return tmp;
3061 }
3062
3063 frq->m = tmp;
3064 frq->e = 1;
3065
3058 return 0; 3066 return 0;
3059} 3067}
3060 3068
3061static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq) 3069static int orinoco_ioctl_getsens(struct net_device *dev,
3070 struct iw_request_info *info,
3071 struct iw_param *srq,
3072 char *extra)
3062{ 3073{
3063 struct orinoco_private *priv = netdev_priv(dev); 3074 struct orinoco_private *priv = netdev_priv(dev);
3064 hermes_t *hw = &priv->hw; 3075 hermes_t *hw = &priv->hw;
@@ -3084,7 +3095,10 @@ static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
3084 return 0; 3095 return 0;
3085} 3096}
3086 3097
3087static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq) 3098static int orinoco_ioctl_setsens(struct net_device *dev,
3099 struct iw_request_info *info,
3100 struct iw_param *srq,
3101 char *extra)
3088{ 3102{
3089 struct orinoco_private *priv = netdev_priv(dev); 3103 struct orinoco_private *priv = netdev_priv(dev);
3090 int val = srq->value; 3104 int val = srq->value;
@@ -3101,10 +3115,13 @@ static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
3101 priv->ap_density = val; 3115 priv->ap_density = val;
3102 orinoco_unlock(priv, &flags); 3116 orinoco_unlock(priv, &flags);
3103 3117
3104 return 0; 3118 return -EINPROGRESS; /* Call commit handler */
3105} 3119}
3106 3120
3107static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq) 3121static int orinoco_ioctl_setrts(struct net_device *dev,
3122 struct iw_request_info *info,
3123 struct iw_param *rrq,
3124 char *extra)
3108{ 3125{
3109 struct orinoco_private *priv = netdev_priv(dev); 3126 struct orinoco_private *priv = netdev_priv(dev);
3110 int val = rrq->value; 3127 int val = rrq->value;
@@ -3122,13 +3139,30 @@ static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
3122 priv->rts_thresh = val; 3139 priv->rts_thresh = val;
3123 orinoco_unlock(priv, &flags); 3140 orinoco_unlock(priv, &flags);
3124 3141
3142 return -EINPROGRESS; /* Call commit handler */
3143}
3144
3145static int orinoco_ioctl_getrts(struct net_device *dev,
3146 struct iw_request_info *info,
3147 struct iw_param *rrq,
3148 char *extra)
3149{
3150 struct orinoco_private *priv = netdev_priv(dev);
3151
3152 rrq->value = priv->rts_thresh;
3153 rrq->disabled = (rrq->value == 2347);
3154 rrq->fixed = 1;
3155
3125 return 0; 3156 return 0;
3126} 3157}
3127 3158
3128static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq) 3159static int orinoco_ioctl_setfrag(struct net_device *dev,
3160 struct iw_request_info *info,
3161 struct iw_param *frq,
3162 char *extra)
3129{ 3163{
3130 struct orinoco_private *priv = netdev_priv(dev); 3164 struct orinoco_private *priv = netdev_priv(dev);
3131 int err = 0; 3165 int err = -EINPROGRESS; /* Call commit handler */
3132 unsigned long flags; 3166 unsigned long flags;
3133 3167
3134 if (orinoco_lock(priv, &flags) != 0) 3168 if (orinoco_lock(priv, &flags) != 0)
@@ -3160,11 +3194,14 @@ static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
3160 return err; 3194 return err;
3161} 3195}
3162 3196
3163static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq) 3197static int orinoco_ioctl_getfrag(struct net_device *dev,
3198 struct iw_request_info *info,
3199 struct iw_param *frq,
3200 char *extra)
3164{ 3201{
3165 struct orinoco_private *priv = netdev_priv(dev); 3202 struct orinoco_private *priv = netdev_priv(dev);
3166 hermes_t *hw = &priv->hw; 3203 hermes_t *hw = &priv->hw;
3167 int err = 0; 3204 int err;
3168 u16 val; 3205 u16 val;
3169 unsigned long flags; 3206 unsigned long flags;
3170 3207
@@ -3197,10 +3234,12 @@ static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
3197 return err; 3234 return err;
3198} 3235}
3199 3236
3200static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq) 3237static int orinoco_ioctl_setrate(struct net_device *dev,
3238 struct iw_request_info *info,
3239 struct iw_param *rrq,
3240 char *extra)
3201{ 3241{
3202 struct orinoco_private *priv = netdev_priv(dev); 3242 struct orinoco_private *priv = netdev_priv(dev);
3203 int err = 0;
3204 int ratemode = -1; 3243 int ratemode = -1;
3205 int bitrate; /* 100s of kilobits */ 3244 int bitrate; /* 100s of kilobits */
3206 int i; 3245 int i;
@@ -3236,10 +3275,13 @@ static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
3236 priv->bitratemode = ratemode; 3275 priv->bitratemode = ratemode;
3237 orinoco_unlock(priv, &flags); 3276 orinoco_unlock(priv, &flags);
3238 3277
3239 return err; 3278 return -EINPROGRESS;
3240} 3279}
3241 3280
3242static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq) 3281static int orinoco_ioctl_getrate(struct net_device *dev,
3282 struct iw_request_info *info,
3283 struct iw_param *rrq,
3284 char *extra)
3243{ 3285{
3244 struct orinoco_private *priv = netdev_priv(dev); 3286 struct orinoco_private *priv = netdev_priv(dev);
3245 hermes_t *hw = &priv->hw; 3287 hermes_t *hw = &priv->hw;
@@ -3304,10 +3346,13 @@ static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
3304 return err; 3346 return err;
3305} 3347}
3306 3348
3307static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq) 3349static int orinoco_ioctl_setpower(struct net_device *dev,
3350 struct iw_request_info *info,
3351 struct iw_param *prq,
3352 char *extra)
3308{ 3353{
3309 struct orinoco_private *priv = netdev_priv(dev); 3354 struct orinoco_private *priv = netdev_priv(dev);
3310 int err = 0; 3355 int err = -EINPROGRESS; /* Call commit handler */
3311 unsigned long flags; 3356 unsigned long flags;
3312 3357
3313 if (orinoco_lock(priv, &flags) != 0) 3358 if (orinoco_lock(priv, &flags) != 0)
@@ -3356,7 +3401,10 @@ static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
3356 return err; 3401 return err;
3357} 3402}
3358 3403
3359static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq) 3404static int orinoco_ioctl_getpower(struct net_device *dev,
3405 struct iw_request_info *info,
3406 struct iw_param *prq,
3407 char *extra)
3360{ 3408{
3361 struct orinoco_private *priv = netdev_priv(dev); 3409 struct orinoco_private *priv = netdev_priv(dev);
3362 hermes_t *hw = &priv->hw; 3410 hermes_t *hw = &priv->hw;
@@ -3404,7 +3452,10 @@ static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
3404 return err; 3452 return err;
3405} 3453}
3406 3454
3407static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) 3455static int orinoco_ioctl_getretry(struct net_device *dev,
3456 struct iw_request_info *info,
3457 struct iw_param *rrq,
3458 char *extra)
3408{ 3459{
3409 struct orinoco_private *priv = netdev_priv(dev); 3460 struct orinoco_private *priv = netdev_priv(dev);
3410 hermes_t *hw = &priv->hw; 3461 hermes_t *hw = &priv->hw;
@@ -3455,10 +3506,38 @@ static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
3455 return err; 3506 return err;
3456} 3507}
3457 3508
3458static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq) 3509static int orinoco_ioctl_reset(struct net_device *dev,
3510 struct iw_request_info *info,
3511 void *wrqu,
3512 char *extra)
3513{
3514 struct orinoco_private *priv = netdev_priv(dev);
3515
3516 if (! capable(CAP_NET_ADMIN))
3517 return -EPERM;
3518
3519 if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
3520 printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
3521
3522 /* Firmware reset */
3523 orinoco_reset(dev);
3524 } else {
3525 printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
3526
3527 schedule_work(&priv->reset_work);
3528 }
3529
3530 return 0;
3531}
3532
3533static int orinoco_ioctl_setibssport(struct net_device *dev,
3534 struct iw_request_info *info,
3535 void *wrqu,
3536 char *extra)
3537
3459{ 3538{
3460 struct orinoco_private *priv = netdev_priv(dev); 3539 struct orinoco_private *priv = netdev_priv(dev);
3461 int val = *( (int *) wrq->u.name ); 3540 int val = *( (int *) extra );
3462 unsigned long flags; 3541 unsigned long flags;
3463 3542
3464 if (orinoco_lock(priv, &flags) != 0) 3543 if (orinoco_lock(priv, &flags) != 0)
@@ -3470,28 +3549,28 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
3470 set_port_type(priv); 3549 set_port_type(priv);
3471 3550
3472 orinoco_unlock(priv, &flags); 3551 orinoco_unlock(priv, &flags);
3473 return 0; 3552 return -EINPROGRESS; /* Call commit handler */
3474} 3553}
3475 3554
3476static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq) 3555static int orinoco_ioctl_getibssport(struct net_device *dev,
3556 struct iw_request_info *info,
3557 void *wrqu,
3558 char *extra)
3477{ 3559{
3478 struct orinoco_private *priv = netdev_priv(dev); 3560 struct orinoco_private *priv = netdev_priv(dev);
3479 int *val = (int *)wrq->u.name; 3561 int *val = (int *) extra;
3480 unsigned long flags;
3481
3482 if (orinoco_lock(priv, &flags) != 0)
3483 return -EBUSY;
3484 3562
3485 *val = priv->ibss_port; 3563 *val = priv->ibss_port;
3486 orinoco_unlock(priv, &flags);
3487
3488 return 0; 3564 return 0;
3489} 3565}
3490 3566
3491static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) 3567static int orinoco_ioctl_setport3(struct net_device *dev,
3568 struct iw_request_info *info,
3569 void *wrqu,
3570 char *extra)
3492{ 3571{
3493 struct orinoco_private *priv = netdev_priv(dev); 3572 struct orinoco_private *priv = netdev_priv(dev);
3494 int val = *( (int *) wrq->u.name ); 3573 int val = *( (int *) extra );
3495 int err = 0; 3574 int err = 0;
3496 unsigned long flags; 3575 unsigned long flags;
3497 3576
@@ -3520,51 +3599,131 @@ static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
3520 err = -EINVAL; 3599 err = -EINVAL;
3521 } 3600 }
3522 3601
3523 if (! err) 3602 if (! err) {
3524 /* Actually update the mode we are using */ 3603 /* Actually update the mode we are using */
3525 set_port_type(priv); 3604 set_port_type(priv);
3605 err = -EINPROGRESS;
3606 }
3526 3607
3527 orinoco_unlock(priv, &flags); 3608 orinoco_unlock(priv, &flags);
3528 3609
3529 return err; 3610 return err;
3530} 3611}
3531 3612
3532static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq) 3613static int orinoco_ioctl_getport3(struct net_device *dev,
3614 struct iw_request_info *info,
3615 void *wrqu,
3616 char *extra)
3617{
3618 struct orinoco_private *priv = netdev_priv(dev);
3619 int *val = (int *) extra;
3620
3621 *val = priv->prefer_port3;
3622 return 0;
3623}
3624
3625static int orinoco_ioctl_setpreamble(struct net_device *dev,
3626 struct iw_request_info *info,
3627 void *wrqu,
3628 char *extra)
3533{ 3629{
3534 struct orinoco_private *priv = netdev_priv(dev); 3630 struct orinoco_private *priv = netdev_priv(dev);
3535 int *val = (int *)wrq->u.name;
3536 unsigned long flags; 3631 unsigned long flags;
3632 int val;
3633
3634 if (! priv->has_preamble)
3635 return -EOPNOTSUPP;
3636
3637 /* 802.11b has recently defined some short preamble.
3638 * Basically, the Phy header has been reduced in size.
3639 * This increase performance, especially at high rates
3640 * (the preamble is transmitted at 1Mb/s), unfortunately
3641 * this give compatibility troubles... - Jean II */
3642 val = *( (int *) extra );
3537 3643
3538 if (orinoco_lock(priv, &flags) != 0) 3644 if (orinoco_lock(priv, &flags) != 0)
3539 return -EBUSY; 3645 return -EBUSY;
3540 3646
3541 *val = priv->prefer_port3; 3647 if (val)
3648 priv->preamble = 1;
3649 else
3650 priv->preamble = 0;
3651
3542 orinoco_unlock(priv, &flags); 3652 orinoco_unlock(priv, &flags);
3653
3654 return -EINPROGRESS; /* Call commit handler */
3655}
3656
3657static int orinoco_ioctl_getpreamble(struct net_device *dev,
3658 struct iw_request_info *info,
3659 void *wrqu,
3660 char *extra)
3661{
3662 struct orinoco_private *priv = netdev_priv(dev);
3663 int *val = (int *) extra;
3664
3665 if (! priv->has_preamble)
3666 return -EOPNOTSUPP;
3667
3668 *val = priv->preamble;
3543 return 0; 3669 return 0;
3544} 3670}
3545 3671
3672/* ioctl interface to hermes_read_ltv()
3673 * To use with iwpriv, pass the RID as the token argument, e.g.
3674 * iwpriv get_rid [0xfc00]
3675 * At least Wireless Tools 25 is required to use iwpriv.
3676 * For Wireless Tools 25 and 26 append "dummy" are the end. */
3677static int orinoco_ioctl_getrid(struct net_device *dev,
3678 struct iw_request_info *info,
3679 struct iw_point *data,
3680 char *extra)
3681{
3682 struct orinoco_private *priv = netdev_priv(dev);
3683 hermes_t *hw = &priv->hw;
3684 int rid = data->flags;
3685 u16 length;
3686 int err;
3687 unsigned long flags;
3688
3689 /* It's a "get" function, but we don't want users to access the
3690 * WEP key and other raw firmware data */
3691 if (! capable(CAP_NET_ADMIN))
3692 return -EPERM;
3693
3694 if (rid < 0xfc00 || rid > 0xffff)
3695 return -EINVAL;
3696
3697 if (orinoco_lock(priv, &flags) != 0)
3698 return -EBUSY;
3699
3700 err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
3701 extra);
3702 if (err)
3703 goto out;
3704
3705 data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
3706 MAX_RID_LEN);
3707
3708 out:
3709 orinoco_unlock(priv, &flags);
3710 return err;
3711}
3712
3546/* Spy is used for link quality/strength measurements in Ad-Hoc mode 3713/* Spy is used for link quality/strength measurements in Ad-Hoc mode
3547 * Jean II */ 3714 * Jean II */
3548static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq) 3715static int orinoco_ioctl_setspy(struct net_device *dev,
3716 struct iw_request_info *info,
3717 struct iw_point *srq,
3718 char *extra)
3719
3549{ 3720{
3550 struct orinoco_private *priv = netdev_priv(dev); 3721 struct orinoco_private *priv = netdev_priv(dev);
3551 struct sockaddr address[IW_MAX_SPY]; 3722 struct sockaddr *address = (struct sockaddr *) extra;
3552 int number = srq->length; 3723 int number = srq->length;
3553 int i; 3724 int i;
3554 int err = 0;
3555 unsigned long flags; 3725 unsigned long flags;
3556 3726
3557 /* Check the number of addresses */
3558 if (number > IW_MAX_SPY)
3559 return -E2BIG;
3560
3561 /* Get the data in the driver */
3562 if (srq->pointer) {
3563 if (copy_from_user(address, srq->pointer,
3564 sizeof(struct sockaddr) * number))
3565 return -EFAULT;
3566 }
3567
3568 /* Make sure nobody mess with the structure while we do */ 3727 /* Make sure nobody mess with the structure while we do */
3569 if (orinoco_lock(priv, &flags) != 0) 3728 if (orinoco_lock(priv, &flags) != 0)
3570 return -EBUSY; 3729 return -EBUSY;
@@ -3588,14 +3747,17 @@ static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
3588 /* Now, let the others play */ 3747 /* Now, let the others play */
3589 orinoco_unlock(priv, &flags); 3748 orinoco_unlock(priv, &flags);
3590 3749
3591 return err; 3750 /* Do NOT call commit handler */
3751 return 0;
3592} 3752}
3593 3753
3594static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq) 3754static int orinoco_ioctl_getspy(struct net_device *dev,
3755 struct iw_request_info *info,
3756 struct iw_point *srq,
3757 char *extra)
3595{ 3758{
3596 struct orinoco_private *priv = netdev_priv(dev); 3759 struct orinoco_private *priv = netdev_priv(dev);
3597 struct sockaddr address[IW_MAX_SPY]; 3760 struct sockaddr *address = (struct sockaddr *) extra;
3598 struct iw_quality spy_stat[IW_MAX_SPY];
3599 int number; 3761 int number;
3600 int i; 3762 int i;
3601 unsigned long flags; 3763 unsigned long flags;
@@ -3604,7 +3766,12 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
3604 return -EBUSY; 3766 return -EBUSY;
3605 3767
3606 number = priv->spy_number; 3768 number = priv->spy_number;
3607 if ((number > 0) && (srq->pointer)) { 3769 /* Create address struct */
3770 for (i = 0; i < number; i++) {
3771 memcpy(address[i].sa_data, priv->spy_address[i], ETH_ALEN);
3772 address[i].sa_family = AF_UNIX;
3773 }
3774 if (number > 0) {
3608 /* Create address struct */ 3775 /* Create address struct */
3609 for (i = 0; i < number; i++) { 3776 for (i = 0; i < number; i++) {
3610 memcpy(address[i].sa_data, priv->spy_address[i], 3777 memcpy(address[i].sa_data, priv->spy_address[i],
@@ -3615,344 +3782,153 @@ static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
3615 /* In theory, we should disable irqs while copying the stats 3782 /* In theory, we should disable irqs while copying the stats
3616 * because the rx path might update it in the middle... 3783 * because the rx path might update it in the middle...
3617 * Bah, who care ? - Jean II */ 3784 * Bah, who care ? - Jean II */
3618 memcpy(&spy_stat, priv->spy_stat, 3785 memcpy(extra + (sizeof(struct sockaddr) * number),
3619 sizeof(struct iw_quality) * IW_MAX_SPY); 3786 priv->spy_stat, sizeof(struct iw_quality) * number);
3620 for (i=0; i < number; i++)
3621 priv->spy_stat[i].updated = 0;
3622 } 3787 }
3788 /* Reset updated flags. */
3789 for (i = 0; i < number; i++)
3790 priv->spy_stat[i].updated = 0;
3623 3791
3624 orinoco_unlock(priv, &flags); 3792 orinoco_unlock(priv, &flags);
3625 3793
3626 /* Push stuff to user space */
3627 srq->length = number; 3794 srq->length = number;
3628 if(copy_to_user(srq->pointer, address,
3629 sizeof(struct sockaddr) * number))
3630 return -EFAULT;
3631 if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number),
3632 &spy_stat, sizeof(struct iw_quality) * number))
3633 return -EFAULT;
3634 3795
3635 return 0; 3796 return 0;
3636} 3797}
3637 3798
3638static int 3799/* Commit handler, called after set operations */
3639orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) 3800static int orinoco_ioctl_commit(struct net_device *dev,
3801 struct iw_request_info *info,
3802 void *wrqu,
3803 char *extra)
3640{ 3804{
3641 struct orinoco_private *priv = netdev_priv(dev); 3805 struct orinoco_private *priv = netdev_priv(dev);
3642 struct iwreq *wrq = (struct iwreq *)rq; 3806 struct hermes *hw = &priv->hw;
3643 int err = 0;
3644 int tmp;
3645 int changed = 0;
3646 unsigned long flags; 3807 unsigned long flags;
3808 int err = 0;
3647 3809
3648 TRACE_ENTER(dev->name); 3810 if (!priv->open)
3649 3811 return 0;
3650 /* In theory, we could allow most of the the SET stuff to be
3651 * done. In practice, the lapse of time at startup when the
3652 * card is not ready is very short, so why bother... Note
3653 * that netif_device_present is different from up/down
3654 * (ifconfig), when the device is not yet up, it is usually
3655 * already ready... Jean II */
3656 if (! netif_device_present(dev))
3657 return -ENODEV;
3658
3659 switch (cmd) {
3660 case SIOCGIWNAME:
3661 strcpy(wrq->u.name, "IEEE 802.11-DS");
3662 break;
3663
3664 case SIOCGIWAP:
3665 wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
3666 err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data);
3667 break;
3668
3669 case SIOCGIWRANGE:
3670 err = orinoco_ioctl_getiwrange(dev, &wrq->u.data);
3671 break;
3672
3673 case SIOCSIWMODE:
3674 if (orinoco_lock(priv, &flags) != 0)
3675 return -EBUSY;
3676 switch (wrq->u.mode) {
3677 case IW_MODE_ADHOC:
3678 if (! (priv->has_ibss || priv->has_port3) )
3679 err = -EINVAL;
3680 else {
3681 priv->iw_mode = IW_MODE_ADHOC;
3682 changed = 1;
3683 }
3684 break;
3685
3686 case IW_MODE_INFRA:
3687 priv->iw_mode = IW_MODE_INFRA;
3688 changed = 1;
3689 break;
3690
3691 default:
3692 err = -EINVAL;
3693 break;
3694 }
3695 set_port_type(priv);
3696 orinoco_unlock(priv, &flags);
3697 break;
3698
3699 case SIOCGIWMODE:
3700 if (orinoco_lock(priv, &flags) != 0)
3701 return -EBUSY;
3702 wrq->u.mode = priv->iw_mode;
3703 orinoco_unlock(priv, &flags);
3704 break;
3705
3706 case SIOCSIWENCODE:
3707 err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding);
3708 if (! err)
3709 changed = 1;
3710 break;
3711
3712 case SIOCGIWENCODE:
3713 if (! capable(CAP_NET_ADMIN)) {
3714 err = -EPERM;
3715 break;
3716 }
3717
3718 err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding);
3719 break;
3720
3721 case SIOCSIWESSID:
3722 err = orinoco_ioctl_setessid(dev, &wrq->u.essid);
3723 if (! err)
3724 changed = 1;
3725 break;
3726
3727 case SIOCGIWESSID:
3728 err = orinoco_ioctl_getessid(dev, &wrq->u.essid);
3729 break;
3730
3731 case SIOCSIWNICKN:
3732 err = orinoco_ioctl_setnick(dev, &wrq->u.data);
3733 if (! err)
3734 changed = 1;
3735 break;
3736
3737 case SIOCGIWNICKN:
3738 err = orinoco_ioctl_getnick(dev, &wrq->u.data);
3739 break;
3740
3741 case SIOCGIWFREQ:
3742 tmp = orinoco_hw_get_freq(priv);
3743 if (tmp < 0) {
3744 err = tmp;
3745 } else {
3746 wrq->u.freq.m = tmp;
3747 wrq->u.freq.e = 1;
3748 }
3749 break;
3750
3751 case SIOCSIWFREQ:
3752 err = orinoco_ioctl_setfreq(dev, &wrq->u.freq);
3753 if (! err)
3754 changed = 1;
3755 break;
3756
3757 case SIOCGIWSENS:
3758 err = orinoco_ioctl_getsens(dev, &wrq->u.sens);
3759 break;
3760
3761 case SIOCSIWSENS:
3762 err = orinoco_ioctl_setsens(dev, &wrq->u.sens);
3763 if (! err)
3764 changed = 1;
3765 break;
3766
3767 case SIOCGIWRTS:
3768 wrq->u.rts.value = priv->rts_thresh;
3769 wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
3770 wrq->u.rts.fixed = 1;
3771 break;
3772
3773 case SIOCSIWRTS:
3774 err = orinoco_ioctl_setrts(dev, &wrq->u.rts);
3775 if (! err)
3776 changed = 1;
3777 break;
3778
3779 case SIOCSIWFRAG:
3780 err = orinoco_ioctl_setfrag(dev, &wrq->u.frag);
3781 if (! err)
3782 changed = 1;
3783 break;
3784
3785 case SIOCGIWFRAG:
3786 err = orinoco_ioctl_getfrag(dev, &wrq->u.frag);
3787 break;
3788
3789 case SIOCSIWRATE:
3790 err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate);
3791 if (! err)
3792 changed = 1;
3793 break;
3794
3795 case SIOCGIWRATE:
3796 err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate);
3797 break;
3798
3799 case SIOCSIWPOWER:
3800 err = orinoco_ioctl_setpower(dev, &wrq->u.power);
3801 if (! err)
3802 changed = 1;
3803 break;
3804
3805 case SIOCGIWPOWER:
3806 err = orinoco_ioctl_getpower(dev, &wrq->u.power);
3807 break;
3808
3809 case SIOCGIWTXPOW:
3810 /* The card only supports one tx power, so this is easy */
3811 wrq->u.txpower.value = 15; /* dBm */
3812 wrq->u.txpower.fixed = 1;
3813 wrq->u.txpower.disabled = 0;
3814 wrq->u.txpower.flags = IW_TXPOW_DBM;
3815 break;
3816 3812
3817 case SIOCSIWRETRY: 3813 if (priv->broken_disableport) {
3818 err = -EOPNOTSUPP; 3814 orinoco_reset(dev);
3819 break; 3815 return 0;
3816 }
3820 3817
3821 case SIOCGIWRETRY: 3818 if (orinoco_lock(priv, &flags) != 0)
3822 err = orinoco_ioctl_getretry(dev, &wrq->u.retry); 3819 return err;
3823 break;
3824 3820
3825 case SIOCSIWSPY: 3821 err = hermes_disable_port(hw, 0);
3826 err = orinoco_ioctl_setspy(dev, &wrq->u.data); 3822 if (err) {
3827 break; 3823 printk(KERN_WARNING "%s: Unable to disable port "
3824 "while reconfiguring card\n", dev->name);
3825 priv->broken_disableport = 1;
3826 goto out;
3827 }
3828 3828
3829 case SIOCGIWSPY: 3829 err = __orinoco_program_rids(dev);
3830 err = orinoco_ioctl_getspy(dev, &wrq->u.data); 3830 if (err) {
3831 break; 3831 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
3832 dev->name);
3833 goto out;
3834 }
3832 3835
3833 case SIOCGIWPRIV: 3836 err = hermes_enable_port(hw, 0);
3834 if (wrq->u.data.pointer) { 3837 if (err) {
3835 struct iw_priv_args privtab[] = { 3838 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
3836 { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, 3839 dev->name);
3837 { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, 3840 goto out;
3838 { SIOCIWFIRSTPRIV + 0x2, 3841 }
3839 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3840 0, "set_port3" },
3841 { SIOCIWFIRSTPRIV + 0x3, 0,
3842 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3843 "get_port3" },
3844 { SIOCIWFIRSTPRIV + 0x4,
3845 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3846 0, "set_preamble" },
3847 { SIOCIWFIRSTPRIV + 0x5, 0,
3848 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3849 "get_preamble" },
3850 { SIOCIWFIRSTPRIV + 0x6,
3851 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3852 0, "set_ibssport" },
3853 { SIOCIWFIRSTPRIV + 0x7, 0,
3854 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3855 "get_ibssport" },
3856 };
3857
3858 wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
3859 if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
3860 err = -EFAULT;
3861 }
3862 break;
3863
3864 case SIOCIWFIRSTPRIV + 0x0: /* force_reset */
3865 case SIOCIWFIRSTPRIV + 0x1: /* card_reset */
3866 if (! capable(CAP_NET_ADMIN)) {
3867 err = -EPERM;
3868 break;
3869 }
3870
3871 printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
3872 3842
3843 out:
3844 if (err) {
3845 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
3873 schedule_work(&priv->reset_work); 3846 schedule_work(&priv->reset_work);
3874 break; 3847 err = 0;
3875 3848 }
3876 case SIOCIWFIRSTPRIV + 0x2: /* set_port3 */
3877 if (! capable(CAP_NET_ADMIN)) {
3878 err = -EPERM;
3879 break;
3880 }
3881
3882 err = orinoco_ioctl_setport3(dev, wrq);
3883 if (! err)
3884 changed = 1;
3885 break;
3886
3887 case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */
3888 err = orinoco_ioctl_getport3(dev, wrq);
3889 break;
3890
3891 case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */
3892 if (! capable(CAP_NET_ADMIN)) {
3893 err = -EPERM;
3894 break;
3895 }
3896
3897 /* 802.11b has recently defined some short preamble.
3898 * Basically, the Phy header has been reduced in size.
3899 * This increase performance, especially at high rates
3900 * (the preamble is transmitted at 1Mb/s), unfortunately
3901 * this give compatibility troubles... - Jean II */
3902 if(priv->has_preamble) {
3903 int val = *( (int *) wrq->u.name );
3904
3905 if (orinoco_lock(priv, &flags) != 0)
3906 return -EBUSY;
3907 if (val)
3908 priv->preamble = 1;
3909 else
3910 priv->preamble = 0;
3911 orinoco_unlock(priv, &flags);
3912 changed = 1;
3913 } else
3914 err = -EOPNOTSUPP;
3915 break;
3916 3849
3917 case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */ 3850 orinoco_unlock(priv, &flags);
3918 if(priv->has_preamble) { 3851 return err;
3919 int *val = (int *)wrq->u.name; 3852}
3920 3853
3921 if (orinoco_lock(priv, &flags) != 0) 3854static const struct iw_priv_args orinoco_privtab[] = {
3922 return -EBUSY; 3855 { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
3923 *val = priv->preamble; 3856 { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
3924 orinoco_unlock(priv, &flags); 3857 { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3925 } else 3858 0, "set_port3" },
3926 err = -EOPNOTSUPP; 3859 { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3927 break; 3860 "get_port3" },
3928 case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */ 3861 { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3929 if (! capable(CAP_NET_ADMIN)) { 3862 0, "set_preamble" },
3930 err = -EPERM; 3863 { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3931 break; 3864 "get_preamble" },
3932 } 3865 { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3866 0, "set_ibssport" },
3867 { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
3868 "get_ibssport" },
3869 { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
3870 "get_rid" },
3871};
3933 3872
3934 err = orinoco_ioctl_setibssport(dev, wrq);
3935 if (! err)
3936 changed = 1;
3937 break;
3938 3873
3939 case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */ 3874/*
3940 err = orinoco_ioctl_getibssport(dev, wrq); 3875 * Structures to export the Wireless Handlers
3941 break; 3876 */
3942 3877
3943 default: 3878static const iw_handler orinoco_handler[] = {
3944 err = -EOPNOTSUPP; 3879 [SIOCSIWCOMMIT-SIOCIWFIRST] (iw_handler) orinoco_ioctl_commit,
3945 } 3880 [SIOCGIWNAME -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getname,
3946 3881 [SIOCSIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfreq,
3947 if (! err && changed && netif_running(dev)) { 3882 [SIOCGIWFREQ -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfreq,
3948 err = orinoco_reconfigure(dev); 3883 [SIOCSIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setmode,
3949 } 3884 [SIOCGIWMODE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getmode,
3885 [SIOCSIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setsens,
3886 [SIOCGIWSENS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getsens,
3887 [SIOCGIWRANGE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwrange,
3888 [SIOCSIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setspy,
3889 [SIOCGIWSPY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getspy,
3890 [SIOCGIWAP -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getwap,
3891 [SIOCSIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setessid,
3892 [SIOCGIWESSID -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getessid,
3893 [SIOCSIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setnick,
3894 [SIOCGIWNICKN -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getnick,
3895 [SIOCSIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrate,
3896 [SIOCGIWRATE -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrate,
3897 [SIOCSIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setrts,
3898 [SIOCGIWRTS -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getrts,
3899 [SIOCSIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setfrag,
3900 [SIOCGIWFRAG -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getfrag,
3901 [SIOCGIWRETRY -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getretry,
3902 [SIOCSIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_setiwencode,
3903 [SIOCGIWENCODE-SIOCIWFIRST] (iw_handler) orinoco_ioctl_getiwencode,
3904 [SIOCSIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_setpower,
3905 [SIOCGIWPOWER -SIOCIWFIRST] (iw_handler) orinoco_ioctl_getpower,
3906};
3950 3907
3951 TRACE_EXIT(dev->name);
3952 3908
3953 return err; 3909/*
3954} 3910 Added typecasting since we no longer use iwreq_data -- Moustafa
3911 */
3912static const iw_handler orinoco_private_handler[] = {
3913 [0] (iw_handler) orinoco_ioctl_reset,
3914 [1] (iw_handler) orinoco_ioctl_reset,
3915 [2] (iw_handler) orinoco_ioctl_setport3,
3916 [3] (iw_handler) orinoco_ioctl_getport3,
3917 [4] (iw_handler) orinoco_ioctl_setpreamble,
3918 [5] (iw_handler) orinoco_ioctl_getpreamble,
3919 [6] (iw_handler) orinoco_ioctl_setibssport,
3920 [7] (iw_handler) orinoco_ioctl_getibssport,
3921 [9] (iw_handler) orinoco_ioctl_getrid,
3922};
3955 3923
3924static const struct iw_handler_def orinoco_handler_def = {
3925 .num_standard = ARRAY_SIZE(orinoco_handler),
3926 .num_private = ARRAY_SIZE(orinoco_private_handler),
3927 .num_private_args = ARRAY_SIZE(orinoco_privtab),
3928 .standard = orinoco_handler,
3929 .private = orinoco_private_handler,
3930 .private_args = orinoco_privtab,
3931};
3956 3932
3957/********************************************************************/ 3933/********************************************************************/
3958/* Debugging */ 3934/* Debugging */