netdev
[Top] [All Lists]

[PATCH 2.6.10-rc1 11/15] wireless/orinoco: Clean up firmware version & c

To: netdev@xxxxxxxxxxx
Subject: [PATCH 2.6.10-rc1 11/15] wireless/orinoco: Clean up firmware version & capability detection
From: Dan Williams <dcbw@xxxxxxxxxx>
Date: Tue, 26 Oct 2004 15:18:31 -0400
Cc: jgarzik@xxxxxxxxxx, hermes@xxxxxxxxxxxxxxxxxxxxx
In-reply-to: <1098814320.3663.24.camel@dcbw.boston.redhat.com>
References: <1098814320.3663.24.camel@dcbw.boston.redhat.com>
Sender: netdev-bounce@xxxxxxxxxxx
Update in-kernel orinoco wireless drivers to upstream CVS.
None of this is original code by Dan Williams, simply a
broken down patch set split-out from upstream orinoco CVS.

o Clean up firmware version & capability detection

Signed-off-by: Dan Williams <dcbw@xxxxxxxxxx>

--- a/drivers/net/wireless/orinoco.c.11-firmware-fixes  2004-10-26 
15:15:11.454350912 -0400
+++ b/drivers/net/wireless/orinoco.c    2004-10-26 15:15:11.456350608 -0400
@@ -1452,7 +1452,7 @@
                return err;
 
        err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-       if (err == -EIO) {
+       if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
                /* Try workaround for old Symbol firmware bug */
                printk(KERN_WARNING "%s: firmware ALLOC bug detected "
                       "(old Symbol firmware?). Trying to work around... ",
@@ -2098,39 +2098,54 @@
 /* Initialization                                                   */
 /********************************************************************/
 
-struct sta_id {
+struct comp_id {
        u16 id, variant, major, minor;
 } __attribute__ ((packed));
 
-static int determine_firmware_type(struct net_device *dev, struct sta_id 
*sta_id)
+static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
 {
-       /* FIXME: this is fundamentally broken */
-       unsigned int firmver = ((u32)sta_id->major << 16) | sta_id->minor;
-       
-       if (sta_id->variant == 1)
+       if (nic_id->id < 0x8000)
                return FIRMWARE_TYPE_AGERE;
-       else if ((sta_id->variant == 2) &&
-                  ((firmver == 0x10001) || (firmver == 0x20001)))
+       else if (nic_id->id == 0x8000 && nic_id->major == 0)
                return FIRMWARE_TYPE_SYMBOL;
        else
                return FIRMWARE_TYPE_INTERSIL;
 }
 
-static void determine_firmware(struct net_device *dev)
+/* Set priv->firmware type, determine firmware properties */
+static int determine_firmware(struct net_device *dev)
 {
        struct orinoco_private *priv = netdev_priv(dev);
        hermes_t *hw = &priv->hw;
        int err;
-       struct sta_id sta_id;
+       struct comp_id nic_id, sta_id;
        unsigned int firmver;
        char tmp[SYMBOL_MAX_VER_LEN+1];
 
+       /* Get the hardware version */
+       err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
+       if (err) {
+               printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
+                      dev->name, err);
+               return err;
+       }
+
+       le16_to_cpus(&nic_id.id);
+       le16_to_cpus(&nic_id.variant);
+       le16_to_cpus(&nic_id.major);
+       le16_to_cpus(&nic_id.minor);
+       printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
+              dev->name, nic_id.id, nic_id.variant,
+              nic_id.major, nic_id.minor);
+
+       priv->firmware_type = determine_firmware_type(&nic_id);
+
        /* Get the firmware version */
        err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
        if (err) {
                printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
                       dev->name, err);
-               memset(&sta_id, 0, sizeof(sta_id));
+               return err;
        }
 
        le16_to_cpus(&sta_id.id);
@@ -2141,8 +2156,23 @@
               dev->name, sta_id.id, sta_id.variant,
               sta_id.major, sta_id.minor);
 
-       if (! priv->firmware_type)
-               priv->firmware_type = determine_firmware_type(dev, &sta_id);
+       switch (sta_id.id) {
+       case 0x15:
+               printk(KERN_ERR "%s: Primary firmware is active\n",
+                      dev->name);
+               return -ENODEV;
+       case 0x14b:
+               printk(KERN_ERR "%s: Tertiary firmware is active\n",
+                      dev->name);
+               return -ENODEV;
+       case 0x1f:      /* Intersil, Agere, Symbol Spectrum24 */
+       case 0x21:      /* Symbol Spectrum24 Trilogy */
+               break;
+       default:
+               printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
+                      dev->name);
+               break;
+       }
 
        /* Default capabilities */
        priv->has_sensitivity = 1;
@@ -2158,9 +2188,8 @@
        case FIRMWARE_TYPE_AGERE:
                /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
                   ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
-               printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "
-                      "version %d.%02d\n", dev->name,
-                      sta_id.major, sta_id.minor);
+               snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+                        "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
 
                firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
 
@@ -2203,16 +2232,19 @@
                        tmp[SYMBOL_MAX_VER_LEN] = '\0';
                }
 
-               printk(KERN_DEBUG "%s: Looks like a Symbol firmware "
-                      "version [%s] (parsing to %X)\n", dev->name,
-                      tmp, firmver);
+               snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+                        "Symbol %s", tmp);
 
                priv->has_ibss = (firmver >= 0x20000);
                priv->has_wep = (firmver >= 0x15012);
                priv->has_big_wep = (firmver >= 0x20000);
-               priv->has_pm = (firmver >= 0x20000) && (firmver < 0x22000);
+               priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) || 
+                              (firmver >= 0x29000 && firmver < 0x30000) ||
+                              firmver >= 0x31000;
                priv->has_preamble = (firmver >= 0x20000);
                priv->ibss_port = 4;
+               priv->broken_disableport = (firmver == 0x25013) ||
+                                          (firmver >= 0x30000 && firmver <= 
0x31000);
                /* Tested with Intel firmware : 0x20015 => Jean II */
                /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
                break;
@@ -2222,9 +2254,9 @@
                 * different and less well tested */
                /* D-Link MAC : 00:40:05:* */
                /* Addtron MAC : 00:90:D1:* */
-               printk(KERN_DEBUG "%s: Looks like an Intersil firmware "
-                      "version %d.%d.%d\n", dev->name,
-                      sta_id.major, sta_id.minor, sta_id.variant);
+               snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
+                        "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
+                        sta_id.variant);
 
                firmver = ((unsigned long)sta_id.major << 16) |
                        ((unsigned long)sta_id.minor << 8) | sta_id.variant;
@@ -2242,9 +2274,11 @@
                        priv->ibss_port = 1;
                }
                break;
-       default:
-               break;
        }
+       printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
+              priv->fw_name);
+
+       return 0;
 }
 
 static int orinoco_init(struct net_device *dev)
@@ -2263,14 +2297,19 @@
        priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
 
        /* Initialize the firmware */
-       err = hermes_init(hw);
+       err = orinoco_reinit_firmware(dev);
        if (err != 0) {
                printk(KERN_ERR "%s: failed to initialize firmware (err = 
%d)\n",
                       dev->name, err);
                goto out;
        }
 
-       determine_firmware(dev);
+       err = determine_firmware(dev);
+       if (err != 0) {
+               printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
+                      dev->name);
+               goto out;
+       }
 
        if (priv->has_port3)
                printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", 
dev->name);
@@ -2391,31 +2430,12 @@
        /* By default use IEEE/IBSS ad-hoc mode if we have it */
        priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
        set_port_type(priv);
-       priv->channel = 10; /* default channel, more-or-less arbitrary */
+       priv->channel = 0; /* use firmware default */
 
        priv->promiscuous = 0;
        priv->wep_on = 0;
        priv->tx_key = 0;
 
-       err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-       if (err == -EIO) {
-               /* Try workaround for old Symbol firmware bug */
-               printk(KERN_WARNING "%s: firmware ALLOC bug detected "
-                      "(old Symbol firmware?). Trying to work around... ",
-                      dev->name);
-               
-               priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
-               err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
-               if (err)
-                       printk("failed!\n");
-               else
-                       printk("ok.\n");
-       }
-       if (err) {
-               printk("%s: Error %d allocating Tx buffer\n", dev->name, err);
-               goto out;
-       }
-
        /* Make the hardware available, as long as it hasn't been
         * removed elsewhere (e.g. by PCMCIA hot unplug) */
        orinoco_spin_lock(priv);
--- a/drivers/net/wireless/orinoco.h.11-firmware-fixes  2004-10-26 
15:15:11.454350912 -0400
+++ b/drivers/net/wireless/orinoco.h    2004-10-26 15:15:11.456350608 -0400
@@ -36,6 +36,12 @@
        char data[ORINOCO_MAX_KEY_SIZE];
 } __attribute__ ((packed));
 
+typedef enum {
+       FIRMWARE_TYPE_AGERE,
+       FIRMWARE_TYPE_INTERSIL,
+       FIRMWARE_TYPE_SYMBOL
+} fwtype_t;
+
 struct orinoco_private {
        void *card;     /* Pointer to card dependent structure */
        int (*hard_reset)(struct orinoco_private *);
@@ -60,12 +66,9 @@
        u16 txfid;
 
        /* Capabilities of the hardware/firmware */
-       int firmware_type;
-#define FIRMWARE_TYPE_AGERE 1
-#define FIRMWARE_TYPE_INTERSIL 2
-#define FIRMWARE_TYPE_SYMBOL 3
+       fwtype_t firmware_type;
+       char fw_name[32];
        int ibss_port;
-       int has_ibss_any;
        int nicbuf_size;
        u16 channel_mask;
 



<Prev in Thread] Current Thread [Next in Thread>