aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/orinoco
diff options
context:
space:
mode:
authorDavid Kilroy <kilroyd@googlemail.com>2008-10-31 09:35:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-11-10 15:17:42 -0500
commitb2e53b338b7b4608372d070bb477f3bae3971e5a (patch)
tree1d2bc35201029e8cd0b8007c5ebc0b07fd1a03ec /drivers/net/wireless/orinoco
parent5166ccd220f187b2e9edfc5f01eb49f4a0ebf586 (diff)
orinoco: Move sources to a subdirectory
Keeping all the orinoco drivers in a common directory will make maintenance easier. Signed-off by: David Kilroy <kilroyd@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/orinoco')
-rw-r--r--drivers/net/wireless/orinoco/Makefile12
-rw-r--r--drivers/net/wireless/orinoco/airport.c286
-rw-r--r--drivers/net/wireless/orinoco/hermes.c544
-rw-r--r--drivers/net/wireless/orinoco/hermes.h494
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.c730
-rw-r--r--drivers/net/wireless/orinoco/hermes_dld.h48
-rw-r--r--drivers/net/wireless/orinoco/hermes_rid.h165
-rw-r--r--drivers/net/wireless/orinoco/orinoco.c6032
-rw-r--r--drivers/net/wireless/orinoco/orinoco.h218
-rw-r--r--drivers/net/wireless/orinoco/orinoco_cs.c533
-rw-r--r--drivers/net/wireless/orinoco/orinoco_nortel.c324
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.c264
-rw-r--r--drivers/net/wireless/orinoco/orinoco_pci.h109
-rw-r--r--drivers/net/wireless/orinoco/orinoco_plx.c371
-rw-r--r--drivers/net/wireless/orinoco/orinoco_tmd.c248
-rw-r--r--drivers/net/wireless/orinoco/spectrum_cs.c507
16 files changed, 10885 insertions, 0 deletions
diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile
new file mode 100644
index 000000000000..791366e08c50
--- /dev/null
+++ b/drivers/net/wireless/orinoco/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for the orinoco wireless device drivers.
3#
4
5obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o
6obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o
7obj-$(CONFIG_APPLE_AIRPORT) += airport.o
8obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o
9obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o
10obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o
11obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o
12obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o
diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c
new file mode 100644
index 000000000000..ce03a2e865fa
--- /dev/null
+++ b/drivers/net/wireless/orinoco/airport.c
@@ -0,0 +1,286 @@
1/* airport.c
2 *
3 * A driver for "Hermes" chipset based Apple Airport wireless
4 * card.
5 *
6 * Copyright notice & release notes in file orinoco.c
7 *
8 * Note specific to airport stub:
9 *
10 * 0.05 : first version of the new split driver
11 * 0.06 : fix possible hang on powerup, add sleep support
12 */
13
14#define DRIVER_NAME "airport"
15#define PFX DRIVER_NAME ": "
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/delay.h>
21#include <asm/pmac_feature.h>
22
23#include "orinoco.h"
24
25#define AIRPORT_IO_LEN (0x1000) /* one page */
26
27struct airport {
28 struct macio_dev *mdev;
29 void __iomem *vaddr;
30 int irq_requested;
31 int ndev_registered;
32};
33
34static int
35airport_suspend(struct macio_dev *mdev, pm_message_t state)
36{
37 struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
38 struct orinoco_private *priv = netdev_priv(dev);
39 unsigned long flags;
40 int err;
41
42 printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name);
43
44 err = orinoco_lock(priv, &flags);
45 if (err) {
46 printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n",
47 dev->name);
48 return 0;
49 }
50
51 err = __orinoco_down(dev);
52 if (err)
53 printk(KERN_WARNING "%s: PBOOK_SLEEP_NOW: Error %d downing interface\n",
54 dev->name, err);
55
56 netif_device_detach(dev);
57
58 priv->hw_unavailable++;
59
60 orinoco_unlock(priv, &flags);
61
62 disable_irq(dev->irq);
63 pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
64
65 return 0;
66}
67
68static int
69airport_resume(struct macio_dev *mdev)
70{
71 struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
72 struct orinoco_private *priv = netdev_priv(dev);
73 unsigned long flags;
74 int err;
75
76 printk(KERN_DEBUG "%s: Airport waking up\n", dev->name);
77
78 pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
79 msleep(200);
80
81 enable_irq(dev->irq);
82
83 err = orinoco_reinit_firmware(dev);
84 if (err) {
85 printk(KERN_ERR "%s: Error %d re-initializing firmware on PBOOK_WAKE\n",
86 dev->name, err);
87 return 0;
88 }
89
90 spin_lock_irqsave(&priv->lock, flags);
91
92 netif_device_attach(dev);
93
94 priv->hw_unavailable--;
95
96 if (priv->open && (! priv->hw_unavailable)) {
97 err = __orinoco_up(dev);
98 if (err)
99 printk(KERN_ERR "%s: Error %d restarting card on PBOOK_WAKE\n",
100 dev->name, err);
101 }
102
103
104 spin_unlock_irqrestore(&priv->lock, flags);
105
106 return 0;
107}
108
109static int
110airport_detach(struct macio_dev *mdev)
111{
112 struct net_device *dev = dev_get_drvdata(&mdev->ofdev.dev);
113 struct orinoco_private *priv = netdev_priv(dev);
114 struct airport *card = priv->card;
115
116 if (card->ndev_registered)
117 unregister_netdev(dev);
118 card->ndev_registered = 0;
119
120 if (card->irq_requested)
121 free_irq(dev->irq, dev);
122 card->irq_requested = 0;
123
124 if (card->vaddr)
125 iounmap(card->vaddr);
126 card->vaddr = NULL;
127
128 macio_release_resource(mdev, 0);
129
130 pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 0);
131 ssleep(1);
132
133 macio_set_drvdata(mdev, NULL);
134 free_orinocodev(dev);
135
136 return 0;
137}
138
139static int airport_hard_reset(struct orinoco_private *priv)
140{
141 /* It would be nice to power cycle the Airport for a real hard
142 * reset, but for some reason although it appears to
143 * re-initialize properly, it falls in a screaming heap
144 * shortly afterwards. */
145#if 0
146 struct net_device *dev = priv->ndev;
147 struct airport *card = priv->card;
148
149 /* Vitally important. If we don't do this it seems we get an
150 * interrupt somewhere during the power cycle, since
151 * hw_unavailable is already set it doesn't get ACKed, we get
152 * into an interrupt loop and the PMU decides to turn us
153 * off. */
154 disable_irq(dev->irq);
155
156 pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 0);
157 ssleep(1);
158 pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(card->mdev), 0, 1);
159 ssleep(1);
160
161 enable_irq(dev->irq);
162 ssleep(1);
163#endif
164
165 return 0;
166}
167
168static int
169airport_attach(struct macio_dev *mdev, const struct of_device_id *match)
170{
171 struct orinoco_private *priv;
172 struct net_device *dev;
173 struct airport *card;
174 unsigned long phys_addr;
175 hermes_t *hw;
176
177 if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) {
178 printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n");
179 return -ENODEV;
180 }
181
182 /* Allocate space for private device-specific data */
183 dev = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev,
184 airport_hard_reset, NULL);
185 if (! dev) {
186 printk(KERN_ERR PFX "Cannot allocate network device\n");
187 return -ENODEV;
188 }
189 priv = netdev_priv(dev);
190 card = priv->card;
191
192 hw = &priv->hw;
193 card->mdev = mdev;
194
195 if (macio_request_resource(mdev, 0, "airport")) {
196 printk(KERN_ERR PFX "can't request IO resource !\n");
197 free_orinocodev(dev);
198 return -EBUSY;
199 }
200
201 SET_NETDEV_DEV(dev, &mdev->ofdev.dev);
202
203 macio_set_drvdata(mdev, dev);
204
205 /* Setup interrupts & base address */
206 dev->irq = macio_irq(mdev, 0);
207 phys_addr = macio_resource_start(mdev, 0); /* Physical address */
208 printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr);
209 dev->base_addr = phys_addr;
210 card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN);
211 if (!card->vaddr) {
212 printk(KERN_ERR PFX "ioremap() failed\n");
213 goto failed;
214 }
215
216 hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING);
217
218 /* Power up card */
219 pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, macio_get_of_node(mdev), 0, 1);
220 ssleep(1);
221
222 /* Reset it before we get the interrupt */
223 hermes_init(hw);
224
225 if (request_irq(dev->irq, orinoco_interrupt, 0, dev->name, dev)) {
226 printk(KERN_ERR PFX "Couldn't get IRQ %d\n", dev->irq);
227 goto failed;
228 }
229 card->irq_requested = 1;
230
231 /* Tell the stack we exist */
232 if (register_netdev(dev) != 0) {
233 printk(KERN_ERR PFX "register_netdev() failed\n");
234 goto failed;
235 }
236 printk(KERN_DEBUG PFX "Card registered for interface %s\n", dev->name);
237 card->ndev_registered = 1;
238 return 0;
239 failed:
240 airport_detach(mdev);
241 return -ENODEV;
242} /* airport_attach */
243
244
245static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
246 " (Benjamin Herrenschmidt <benh@kernel.crashing.org>)";
247MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
248MODULE_DESCRIPTION("Driver for the Apple Airport wireless card.");
249MODULE_LICENSE("Dual MPL/GPL");
250
251static struct of_device_id airport_match[] =
252{
253 {
254 .name = "radio",
255 },
256 {},
257};
258
259MODULE_DEVICE_TABLE (of, airport_match);
260
261static struct macio_driver airport_driver =
262{
263 .name = DRIVER_NAME,
264 .match_table = airport_match,
265 .probe = airport_attach,
266 .remove = airport_detach,
267 .suspend = airport_suspend,
268 .resume = airport_resume,
269};
270
271static int __init
272init_airport(void)
273{
274 printk(KERN_DEBUG "%s\n", version);
275
276 return macio_register_driver(&airport_driver);
277}
278
279static void __exit
280exit_airport(void)
281{
282 return macio_unregister_driver(&airport_driver);
283}
284
285module_init(init_airport);
286module_exit(exit_airport);
diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c
new file mode 100644
index 000000000000..bfa375369df3
--- /dev/null
+++ b/drivers/net/wireless/orinoco/hermes.c
@@ -0,0 +1,544 @@
1/* hermes.c
2 *
3 * Driver core for the "Hermes" wireless MAC controller, as used in
4 * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
5 * work on the hfa3841 and hfa3842 MAC controller chips used in the
6 * Prism II chipsets.
7 *
8 * This is not a complete driver, just low-level access routines for
9 * the MAC controller itself.
10 *
11 * Based on the prism2 driver from Absolute Value Systems' linux-wlan
12 * project, the Linux wvlan_cs driver, Lucent's HCF-Light
13 * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no
14 * particular order).
15 *
16 * Copyright (C) 2000, David Gibson, Linuxcare Australia.
17 * (C) Copyright David Gibson, IBM Corp. 2001-2003.
18 *
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License
22 * at http://www.mozilla.org/MPL/
23 *
24 * Software distributed under the License is distributed on an "AS IS"
25 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
26 * the License for the specific language governing rights and
27 * limitations under the License.
28 *
29 * Alternatively, the contents of this file may be used under the
30 * terms of the GNU General Public License version 2 (the "GPL"), in
31 * which case the provisions of the GPL are applicable instead of the
32 * above. If you wish to allow the use of your version of this file
33 * only under the terms of the GPL and not to allow others to use your
34 * version of this file under the MPL, indicate your decision by
35 * deleting the provisions above and replace them with the notice and
36 * other provisions required by the GPL. If you do not delete the
37 * provisions above, a recipient may use your version of this file
38 * under either the MPL or the GPL.
39 */
40
41#include <linux/module.h>
42#include <linux/kernel.h>
43#include <linux/init.h>
44#include <linux/delay.h>
45
46#include "hermes.h"
47
48MODULE_DESCRIPTION("Low-level driver helper for Lucent Hermes chipset and Prism II HFA384x wireless MAC controller");
49MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>"
50 " & David Gibson <hermes@gibson.dropbear.id.au>");
51MODULE_LICENSE("Dual MPL/GPL");
52
53/* These are maximum timeouts. Most often, card wil react much faster */
54#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
55#define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
56#define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
57#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
58
59/*
60 * Debugging helpers
61 */
62
63#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \
64 printk(stuff);} while (0)
65
66#undef HERMES_DEBUG
67#ifdef HERMES_DEBUG
68#include <stdarg.h>
69
70#define DEBUG(lvl, stuff...) if ( (lvl) <= HERMES_DEBUG) DMSG(stuff)
71
72#else /* ! HERMES_DEBUG */
73
74#define DEBUG(lvl, stuff...) do { } while (0)
75
76#endif /* ! HERMES_DEBUG */
77
78
79/*
80 * Internal functions
81 */
82
83/* Issue a command to the chip. Waiting for it to complete is the caller's
84 problem.
85
86 Returns -EBUSY if the command register is busy, 0 on success.
87
88 Callable from any context.
89*/
90static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
91 u16 param1, u16 param2)
92{
93 int k = CMD_BUSY_TIMEOUT;
94 u16 reg;
95
96 /* First wait for the command register to unbusy */
97 reg = hermes_read_regn(hw, CMD);
98 while ( (reg & HERMES_CMD_BUSY) && k ) {
99 k--;
100 udelay(1);
101 reg = hermes_read_regn(hw, CMD);
102 }
103 if (reg & HERMES_CMD_BUSY) {
104 return -EBUSY;
105 }
106
107 hermes_write_regn(hw, PARAM2, param2);
108 hermes_write_regn(hw, PARAM1, param1);
109 hermes_write_regn(hw, PARAM0, param0);
110 hermes_write_regn(hw, CMD, cmd);
111
112 return 0;
113}
114
115/*
116 * Function definitions
117 */
118
119/* For doing cmds that wipe the magic constant in SWSUPPORT0 */
120int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
121 u16 parm0, u16 parm1, u16 parm2,
122 struct hermes_response *resp)
123{
124 int err = 0;
125 int k;
126 u16 status, reg;
127
128 err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2);
129 if (err)
130 return err;
131
132 reg = hermes_read_regn(hw, EVSTAT);
133 k = CMD_INIT_TIMEOUT;
134 while ((!(reg & HERMES_EV_CMD)) && k) {
135 k--;
136 udelay(10);
137 reg = hermes_read_regn(hw, EVSTAT);
138 }
139
140 hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
141
142 if (!hermes_present(hw)) {
143 DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
144 hw->iobase);
145 err = -ENODEV;
146 goto out;
147 }
148
149 if (!(reg & HERMES_EV_CMD)) {
150 printk(KERN_ERR "hermes @ %p: "
151 "Timeout waiting for card to reset (reg=0x%04x)!\n",
152 hw->iobase, reg);
153 err = -ETIMEDOUT;
154 goto out;
155 }
156
157 status = hermes_read_regn(hw, STATUS);
158 if (resp) {
159 resp->status = status;
160 resp->resp0 = hermes_read_regn(hw, RESP0);
161 resp->resp1 = hermes_read_regn(hw, RESP1);
162 resp->resp2 = hermes_read_regn(hw, RESP2);
163 }
164
165 hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
166
167 if (status & HERMES_STATUS_RESULT)
168 err = -EIO;
169out:
170 return err;
171}
172EXPORT_SYMBOL(hermes_doicmd_wait);
173
174void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
175{
176 hw->iobase = address;
177 hw->reg_spacing = reg_spacing;
178 hw->inten = 0x0;
179}
180EXPORT_SYMBOL(hermes_struct_init);
181
182int hermes_init(hermes_t *hw)
183{
184 u16 reg;
185 int err = 0;
186 int k;
187
188 /* We don't want to be interrupted while resetting the chipset */
189 hw->inten = 0x0;
190 hermes_write_regn(hw, INTEN, 0);
191 hermes_write_regn(hw, EVACK, 0xffff);
192
193 /* Normally it's a "can't happen" for the command register to
194 be busy when we go to issue a command because we are
195 serializing all commands. However we want to have some
196 chance of resetting the card even if it gets into a stupid
197 state, so we actually wait to see if the command register
198 will unbusy itself here. */
199 k = CMD_BUSY_TIMEOUT;
200 reg = hermes_read_regn(hw, CMD);
201 while (k && (reg & HERMES_CMD_BUSY)) {
202 if (reg == 0xffff) /* Special case - the card has probably been removed,
203 so don't wait for the timeout */
204 return -ENODEV;
205
206 k--;
207 udelay(1);
208 reg = hermes_read_regn(hw, CMD);
209 }
210
211 /* No need to explicitly handle the timeout - if we've timed
212 out hermes_issue_cmd() will probably return -EBUSY below */
213
214 /* According to the documentation, EVSTAT may contain
215 obsolete event occurrence information. We have to acknowledge
216 it by writing EVACK. */
217 reg = hermes_read_regn(hw, EVSTAT);
218 hermes_write_regn(hw, EVACK, reg);
219
220 /* We don't use hermes_docmd_wait here, because the reset wipes
221 the magic constant in SWSUPPORT0 away, and it gets confused */
222 err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL);
223
224 return err;
225}
226EXPORT_SYMBOL(hermes_init);
227
228/* Issue a command to the chip, and (busy!) wait for it to
229 * complete.
230 *
231 * Returns: < 0 on internal error, 0 on success, > 0 on error returned by the firmware
232 *
233 * Callable from any context, but locking is your problem. */
234int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
235 struct hermes_response *resp)
236{
237 int err;
238 int k;
239 u16 reg;
240 u16 status;
241
242 err = hermes_issue_cmd(hw, cmd, parm0, 0, 0);
243 if (err) {
244 if (! hermes_present(hw)) {
245 if (net_ratelimit())
246 printk(KERN_WARNING "hermes @ %p: "
247 "Card removed while issuing command "
248 "0x%04x.\n", hw->iobase, cmd);
249 err = -ENODEV;
250 } else
251 if (net_ratelimit())
252 printk(KERN_ERR "hermes @ %p: "
253 "Error %d issuing command 0x%04x.\n",
254 hw->iobase, err, cmd);
255 goto out;
256 }
257
258 reg = hermes_read_regn(hw, EVSTAT);
259 k = CMD_COMPL_TIMEOUT;
260 while ( (! (reg & HERMES_EV_CMD)) && k) {
261 k--;
262 udelay(10);
263 reg = hermes_read_regn(hw, EVSTAT);
264 }
265
266 if (! hermes_present(hw)) {
267 printk(KERN_WARNING "hermes @ %p: Card removed "
268 "while waiting for command 0x%04x completion.\n",
269 hw->iobase, cmd);
270 err = -ENODEV;
271 goto out;
272 }
273
274 if (! (reg & HERMES_EV_CMD)) {
275 printk(KERN_ERR "hermes @ %p: Timeout waiting for "
276 "command 0x%04x completion.\n", hw->iobase, cmd);
277 err = -ETIMEDOUT;
278 goto out;
279 }
280
281 status = hermes_read_regn(hw, STATUS);
282 if (resp) {
283 resp->status = status;
284 resp->resp0 = hermes_read_regn(hw, RESP0);
285 resp->resp1 = hermes_read_regn(hw, RESP1);
286 resp->resp2 = hermes_read_regn(hw, RESP2);
287 }
288
289 hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
290
291 if (status & HERMES_STATUS_RESULT)
292 err = -EIO;
293
294 out:
295 return err;
296}
297EXPORT_SYMBOL(hermes_docmd_wait);
298
299int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
300{
301 int err = 0;
302 int k;
303 u16 reg;
304
305 if ( (size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX) )
306 return -EINVAL;
307
308 err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL);
309 if (err) {
310 return err;
311 }
312
313 reg = hermes_read_regn(hw, EVSTAT);
314 k = ALLOC_COMPL_TIMEOUT;
315 while ( (! (reg & HERMES_EV_ALLOC)) && k) {
316 k--;
317 udelay(10);
318 reg = hermes_read_regn(hw, EVSTAT);
319 }
320
321 if (! hermes_present(hw)) {
322 printk(KERN_WARNING "hermes @ %p: "
323 "Card removed waiting for frame allocation.\n",
324 hw->iobase);
325 return -ENODEV;
326 }
327
328 if (! (reg & HERMES_EV_ALLOC)) {
329 printk(KERN_ERR "hermes @ %p: "
330 "Timeout waiting for frame allocation\n",
331 hw->iobase);
332 return -ETIMEDOUT;
333 }
334
335 *fid = hermes_read_regn(hw, ALLOCFID);
336 hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC);
337
338 return 0;
339}
340EXPORT_SYMBOL(hermes_allocate);
341
342/* Set up a BAP to read a particular chunk of data from card's internal buffer.
343 *
344 * Returns: < 0 on internal failure (errno), 0 on success, >0 on error
345 * from firmware
346 *
347 * Callable from any context */
348static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
349{
350 int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
351 int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
352 int k;
353 u16 reg;
354
355 /* Paranoia.. */
356 if ( (offset > HERMES_BAP_OFFSET_MAX) || (offset % 2) )
357 return -EINVAL;
358
359 k = HERMES_BAP_BUSY_TIMEOUT;
360 reg = hermes_read_reg(hw, oreg);
361 while ((reg & HERMES_OFFSET_BUSY) && k) {
362 k--;
363 udelay(1);
364 reg = hermes_read_reg(hw, oreg);
365 }
366
367 if (reg & HERMES_OFFSET_BUSY)
368 return -ETIMEDOUT;
369
370 /* Now we actually set up the transfer */
371 hermes_write_reg(hw, sreg, id);
372 hermes_write_reg(hw, oreg, offset);
373
374 /* Wait for the BAP to be ready */
375 k = HERMES_BAP_BUSY_TIMEOUT;
376 reg = hermes_read_reg(hw, oreg);
377 while ( (reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
378 k--;
379 udelay(1);
380 reg = hermes_read_reg(hw, oreg);
381 }
382
383 if (reg != offset) {
384 printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
385 "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
386 (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
387 reg, id, offset);
388
389 if (reg & HERMES_OFFSET_BUSY) {
390 return -ETIMEDOUT;
391 }
392
393 return -EIO; /* error or wrong offset */
394 }
395
396 return 0;
397}
398
399/* Read a block of data from the chip's buffer, via the
400 * BAP. Synchronization/serialization is the caller's problem. len
401 * must be even.
402 *
403 * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
404 */
405int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
406 u16 id, u16 offset)
407{
408 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
409 int err = 0;
410
411 if ( (len < 0) || (len % 2) )
412 return -EINVAL;
413
414 err = hermes_bap_seek(hw, bap, id, offset);
415 if (err)
416 goto out;
417
418 /* Actually do the transfer */
419 hermes_read_words(hw, dreg, buf, len/2);
420
421 out:
422 return err;
423}
424EXPORT_SYMBOL(hermes_bap_pread);
425
426/* Write a block of data to the chip's buffer, via the
427 * BAP. Synchronization/serialization is the caller's problem.
428 *
429 * Returns: < 0 on internal failure (errno), 0 on success, > 0 on error from firmware
430 */
431int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
432 u16 id, u16 offset)
433{
434 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
435 int err = 0;
436
437 if (len < 0)
438 return -EINVAL;
439
440 err = hermes_bap_seek(hw, bap, id, offset);
441 if (err)
442 goto out;
443
444 /* Actually do the transfer */
445 hermes_write_bytes(hw, dreg, buf, len);
446
447 out:
448 return err;
449}
450EXPORT_SYMBOL(hermes_bap_pwrite);
451
452/* Read a Length-Type-Value record from the card.
453 *
454 * If length is NULL, we ignore the length read from the card, and
455 * read the entire buffer regardless. This is useful because some of
456 * the configuration records appear to have incorrect lengths in
457 * practice.
458 *
459 * Callable from user or bh context. */
460int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
461 u16 *length, void *buf)
462{
463 int err = 0;
464 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
465 u16 rlength, rtype;
466 unsigned nwords;
467
468 if ( (bufsize < 0) || (bufsize % 2) )
469 return -EINVAL;
470
471 err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL);
472 if (err)
473 return err;
474
475 err = hermes_bap_seek(hw, bap, rid, 0);
476 if (err)
477 return err;
478
479 rlength = hermes_read_reg(hw, dreg);
480
481 if (! rlength)
482 return -ENODATA;
483
484 rtype = hermes_read_reg(hw, dreg);
485
486 if (length)
487 *length = rlength;
488
489 if (rtype != rid)
490 printk(KERN_WARNING "hermes @ %p: %s(): "
491 "rid (0x%04x) does not match type (0x%04x)\n",
492 hw->iobase, __func__, rid, rtype);
493 if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
494 printk(KERN_WARNING "hermes @ %p: "
495 "Truncating LTV record from %d to %d bytes. "
496 "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
497 HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
498
499 nwords = min((unsigned)rlength - 1, bufsize / 2);
500 hermes_read_words(hw, dreg, buf, nwords);
501
502 return 0;
503}
504EXPORT_SYMBOL(hermes_read_ltv);
505
506int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
507 u16 length, const void *value)
508{
509 int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
510 int err = 0;
511 unsigned count;
512
513 if (length == 0)
514 return -EINVAL;
515
516 err = hermes_bap_seek(hw, bap, rid, 0);
517 if (err)
518 return err;
519
520 hermes_write_reg(hw, dreg, length);
521 hermes_write_reg(hw, dreg, rid);
522
523 count = length - 1;
524
525 hermes_write_bytes(hw, dreg, value, count << 1);
526
527 err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
528 rid, NULL);
529
530 return err;
531}
532EXPORT_SYMBOL(hermes_write_ltv);
533
534static int __init init_hermes(void)
535{
536 return 0;
537}
538
539static void __exit exit_hermes(void)
540{
541}
542
543module_init(init_hermes);
544module_exit(exit_hermes);
diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h
new file mode 100644
index 000000000000..8b13c8fef3dc
--- /dev/null
+++ b/drivers/net/wireless/orinoco/hermes.h
@@ -0,0 +1,494 @@
1/* hermes.h
2 *
3 * Driver core for the "Hermes" wireless MAC controller, as used in
4 * the Lucent Orinoco and Cabletron RoamAbout cards. It should also
5 * work on the hfa3841 and hfa3842 MAC controller chips used in the
6 * Prism I & II chipsets.
7 *
8 * This is not a complete driver, just low-level access routines for
9 * the MAC controller itself.
10 *
11 * Based on the prism2 driver from Absolute Value Systems' linux-wlan
12 * project, the Linux wvlan_cs driver, Lucent's HCF-Light
13 * (wvlan_hcf.c) library, and the NetBSD wireless driver.
14 *
15 * Copyright (C) 2000, David Gibson, Linuxcare Australia.
16 * (C) Copyright David Gibson, IBM Corp. 2001-2003.
17 *
18 * Portions taken from hfa384x.h, Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
19 *
20 * This file distributed under the GPL, version 2.
21 */
22
23#ifndef _HERMES_H
24#define _HERMES_H
25
26/* Notes on locking:
27 *
28 * As a module of low level hardware access routines, there is no
29 * locking. Users of this module should ensure that they serialize
30 * access to the hermes_t structure, and to the hardware
31*/
32
33#include <linux/if_ether.h>
34#include <asm/io.h>
35
36/*
37 * Limits and constants
38 */
39#define HERMES_ALLOC_LEN_MIN (4)
40#define HERMES_ALLOC_LEN_MAX (2400)
41#define HERMES_LTV_LEN_MAX (34)
42#define HERMES_BAP_DATALEN_MAX (4096)
43#define HERMES_BAP_OFFSET_MAX (4096)
44#define HERMES_PORTID_MAX (7)
45#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX+1)
46#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */
47#define HERMES_PDA_RECS_MAX (200) /* a guess */
48#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */
49#define HERMES_SCANRESULT_MAX (35)
50#define HERMES_CHINFORESULT_MAX (8)
51#define HERMES_MAX_MULTICAST (16)
52#define HERMES_MAGIC (0x7d1f)
53
54/*
55 * Hermes register offsets
56 */
57#define HERMES_CMD (0x00)
58#define HERMES_PARAM0 (0x02)
59#define HERMES_PARAM1 (0x04)
60#define HERMES_PARAM2 (0x06)
61#define HERMES_STATUS (0x08)
62#define HERMES_RESP0 (0x0A)
63#define HERMES_RESP1 (0x0C)
64#define HERMES_RESP2 (0x0E)
65#define HERMES_INFOFID (0x10)
66#define HERMES_RXFID (0x20)
67#define HERMES_ALLOCFID (0x22)
68#define HERMES_TXCOMPLFID (0x24)
69#define HERMES_SELECT0 (0x18)
70#define HERMES_OFFSET0 (0x1C)
71#define HERMES_DATA0 (0x36)
72#define HERMES_SELECT1 (0x1A)
73#define HERMES_OFFSET1 (0x1E)
74#define HERMES_DATA1 (0x38)
75#define HERMES_EVSTAT (0x30)
76#define HERMES_INTEN (0x32)
77#define HERMES_EVACK (0x34)
78#define HERMES_CONTROL (0x14)
79#define HERMES_SWSUPPORT0 (0x28)
80#define HERMES_SWSUPPORT1 (0x2A)
81#define HERMES_SWSUPPORT2 (0x2C)
82#define HERMES_AUXPAGE (0x3A)
83#define HERMES_AUXOFFSET (0x3C)
84#define HERMES_AUXDATA (0x3E)
85
86/*
87 * CMD register bitmasks
88 */
89#define HERMES_CMD_BUSY (0x8000)
90#define HERMES_CMD_AINFO (0x7f00)
91#define HERMES_CMD_MACPORT (0x0700)
92#define HERMES_CMD_RECL (0x0100)
93#define HERMES_CMD_WRITE (0x0100)
94#define HERMES_CMD_PROGMODE (0x0300)
95#define HERMES_CMD_CMDCODE (0x003f)
96
97/*
98 * STATUS register bitmasks
99 */
100#define HERMES_STATUS_RESULT (0x7f00)
101#define HERMES_STATUS_CMDCODE (0x003f)
102
103/*
104 * OFFSET register bitmasks
105 */
106#define HERMES_OFFSET_BUSY (0x8000)
107#define HERMES_OFFSET_ERR (0x4000)
108#define HERMES_OFFSET_DATAOFF (0x0ffe)
109
110/*
111 * Event register bitmasks (INTEN, EVSTAT, EVACK)
112 */
113#define HERMES_EV_TICK (0x8000)
114#define HERMES_EV_WTERR (0x4000)
115#define HERMES_EV_INFDROP (0x2000)
116#define HERMES_EV_INFO (0x0080)
117#define HERMES_EV_DTIM (0x0020)
118#define HERMES_EV_CMD (0x0010)
119#define HERMES_EV_ALLOC (0x0008)
120#define HERMES_EV_TXEXC (0x0004)
121#define HERMES_EV_TX (0x0002)
122#define HERMES_EV_RX (0x0001)
123
124/*
125 * Command codes
126 */
127/*--- Controller Commands ----------------------------*/
128#define HERMES_CMD_INIT (0x0000)
129#define HERMES_CMD_ENABLE (0x0001)
130#define HERMES_CMD_DISABLE (0x0002)
131#define HERMES_CMD_DIAG (0x0003)
132
133/*--- Buffer Mgmt Commands ---------------------------*/
134#define HERMES_CMD_ALLOC (0x000A)
135#define HERMES_CMD_TX (0x000B)
136
137/*--- Regulate Commands ------------------------------*/
138#define HERMES_CMD_NOTIFY (0x0010)
139#define HERMES_CMD_INQUIRE (0x0011)
140
141/*--- Configure Commands -----------------------------*/
142#define HERMES_CMD_ACCESS (0x0021)
143#define HERMES_CMD_DOWNLD (0x0022)
144
145/*--- Serial I/O Commands ----------------------------*/
146#define HERMES_CMD_READMIF (0x0030)
147#define HERMES_CMD_WRITEMIF (0x0031)
148
149/*--- Debugging Commands -----------------------------*/
150#define HERMES_CMD_TEST (0x0038)
151
152
153/* Test command arguments */
154#define HERMES_TEST_SET_CHANNEL 0x0800
155#define HERMES_TEST_MONITOR 0x0b00
156#define HERMES_TEST_STOP 0x0f00
157
158/* Authentication algorithms */
159#define HERMES_AUTH_OPEN 1
160#define HERMES_AUTH_SHARED_KEY 2
161
162/* WEP settings */
163#define HERMES_WEP_PRIVACY_INVOKED 0x0001
164#define HERMES_WEP_EXCL_UNENCRYPTED 0x0002
165#define HERMES_WEP_HOST_ENCRYPT 0x0010
166#define HERMES_WEP_HOST_DECRYPT 0x0080
167
168/* Symbol hostscan options */
169#define HERMES_HOSTSCAN_SYMBOL_5SEC 0x0001
170#define HERMES_HOSTSCAN_SYMBOL_ONCE 0x0002
171#define HERMES_HOSTSCAN_SYMBOL_PASSIVE 0x0040
172#define HERMES_HOSTSCAN_SYMBOL_BCAST 0x0080
173
174/*
175 * Frame structures and constants
176 */
177
178#define HERMES_DESCRIPTOR_OFFSET 0
179#define HERMES_802_11_OFFSET (14)
180#define HERMES_802_3_OFFSET (14+32)
181#define HERMES_802_2_OFFSET (14+32+14)
182#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2)
183
184#define HERMES_RXSTAT_ERR (0x0003)
185#define HERMES_RXSTAT_BADCRC (0x0001)
186#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002)
187#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */
188#define HERMES_RXSTAT_MACPORT (0x0700)
189#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */
190#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */
191#define HERMES_RXSTAT_MSGTYPE (0xE000)
192#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */
193#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */
194#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */
195
196/* Shift amount for key ID in RXSTAT and TXCTRL */
197#define HERMES_MIC_KEY_ID_SHIFT 11
198
199struct hermes_tx_descriptor {
200 __le16 status;
201 __le16 reserved1;
202 __le16 reserved2;
203 __le32 sw_support;
204 u8 retry_count;
205 u8 tx_rate;
206 __le16 tx_control;
207} __attribute__ ((packed));
208
209#define HERMES_TXSTAT_RETRYERR (0x0001)
210#define HERMES_TXSTAT_AGEDERR (0x0002)
211#define HERMES_TXSTAT_DISCON (0x0004)
212#define HERMES_TXSTAT_FORMERR (0x0008)
213
214#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */
215#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */
216#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */
217#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */
218#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */
219#define HERMES_TXCTRL_ALT_RTRY (0x0020)
220
221/* Inquiry constants and data types */
222
223#define HERMES_INQ_TALLIES (0xF100)
224#define HERMES_INQ_SCAN (0xF101)
225#define HERMES_INQ_CHANNELINFO (0xF102)
226#define HERMES_INQ_HOSTSCAN (0xF103)
227#define HERMES_INQ_HOSTSCAN_SYMBOL (0xF104)
228#define HERMES_INQ_LINKSTATUS (0xF200)
229#define HERMES_INQ_SEC_STAT_AGERE (0xF202)
230
231struct hermes_tallies_frame {
232 __le16 TxUnicastFrames;
233 __le16 TxMulticastFrames;
234 __le16 TxFragments;
235 __le16 TxUnicastOctets;
236 __le16 TxMulticastOctets;
237 __le16 TxDeferredTransmissions;
238 __le16 TxSingleRetryFrames;
239 __le16 TxMultipleRetryFrames;
240 __le16 TxRetryLimitExceeded;
241 __le16 TxDiscards;
242 __le16 RxUnicastFrames;
243 __le16 RxMulticastFrames;
244 __le16 RxFragments;
245 __le16 RxUnicastOctets;
246 __le16 RxMulticastOctets;
247 __le16 RxFCSErrors;
248 __le16 RxDiscards_NoBuffer;
249 __le16 TxDiscardsWrongSA;
250 __le16 RxWEPUndecryptable;
251 __le16 RxMsgInMsgFragments;
252 __le16 RxMsgInBadMsgFragments;
253 /* Those last are probably not available in very old firmwares */
254 __le16 RxDiscards_WEPICVError;
255 __le16 RxDiscards_WEPExcluded;
256} __attribute__ ((packed));
257
258/* Grabbed from wlan-ng - Thanks Mark... - Jean II
259 * This is the result of a scan inquiry command */
260/* Structure describing info about an Access Point */
261struct prism2_scan_apinfo {
262 __le16 channel; /* Channel where the AP sits */
263 __le16 noise; /* Noise level */
264 __le16 level; /* Signal level */
265 u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
266 __le16 beacon_interv; /* Beacon interval */
267 __le16 capabilities; /* Capabilities */
268 __le16 essid_len; /* ESSID length */
269 u8 essid[32]; /* ESSID of the network */
270 u8 rates[10]; /* Bit rate supported */
271 __le16 proberesp_rate; /* Data rate of the response frame */
272 __le16 atim; /* ATIM window time, Kus (hostscan only) */
273} __attribute__ ((packed));
274
275/* Same stuff for the Lucent/Agere card.
276 * Thanks to h1kari <h1kari AT dachb0den.com> - Jean II */
277struct agere_scan_apinfo {
278 __le16 channel; /* Channel where the AP sits */
279 __le16 noise; /* Noise level */
280 __le16 level; /* Signal level */
281 u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
282 __le16 beacon_interv; /* Beacon interval */
283 __le16 capabilities; /* Capabilities */
284 /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
285 __le16 essid_len; /* ESSID length */
286 u8 essid[32]; /* ESSID of the network */
287} __attribute__ ((packed));
288
289/* Moustafa: Scan structure for Symbol cards */
290struct symbol_scan_apinfo {
291 u8 channel; /* Channel where the AP sits */
292 u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */
293 __le16 noise; /* Noise level */
294 __le16 level; /* Signal level */
295 u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */
296 __le16 beacon_interv; /* Beacon interval */
297 __le16 capabilities; /* Capabilities */
298 /* bits: 0-ess, 1-ibss, 4-privacy [wep] */
299 __le16 essid_len; /* ESSID length */
300 u8 essid[32]; /* ESSID of the network */
301 __le16 rates[5]; /* Bit rate supported */
302 __le16 basic_rates; /* Basic rates bitmask */
303 u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */
304 u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */
305} __attribute__ ((packed));
306
307union hermes_scan_info {
308 struct agere_scan_apinfo a;
309 struct prism2_scan_apinfo p;
310 struct symbol_scan_apinfo s;
311};
312
313/* Extended scan struct for HERMES_INQ_CHANNELINFO.
314 * wl_lkm calls this an ACS scan (Automatic Channel Select).
315 * Keep out of union hermes_scan_info because it is much bigger than
316 * the older scan structures. */
317struct agere_ext_scan_info {
318 __le16 reserved0;
319
320 u8 noise;
321 u8 level;
322 u8 rx_flow;
323 u8 rate;
324 __le16 reserved1[2];
325
326 __le16 frame_control;
327 __le16 dur_id;
328 u8 addr1[ETH_ALEN];
329 u8 addr2[ETH_ALEN];
330 u8 bssid[ETH_ALEN];
331 __le16 sequence;
332 u8 addr4[ETH_ALEN];
333
334 __le16 data_length;
335
336 /* Next 3 fields do not get filled in. */
337 u8 daddr[ETH_ALEN];
338 u8 saddr[ETH_ALEN];
339 __le16 len_type;
340
341 __le64 timestamp;
342 __le16 beacon_interval;
343 __le16 capabilities;
344 u8 data[316];
345} __attribute__ ((packed));
346
347#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000)
348#define HERMES_LINKSTATUS_CONNECTED (0x0001)
349#define HERMES_LINKSTATUS_DISCONNECTED (0x0002)
350#define HERMES_LINKSTATUS_AP_CHANGE (0x0003)
351#define HERMES_LINKSTATUS_AP_OUT_OF_RANGE (0x0004)
352#define HERMES_LINKSTATUS_AP_IN_RANGE (0x0005)
353#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006)
354
355struct hermes_linkstatus {
356 __le16 linkstatus; /* Link status */
357} __attribute__ ((packed));
358
359struct hermes_response {
360 u16 status, resp0, resp1, resp2;
361};
362
363/* "ID" structure - used for ESSID and station nickname */
364struct hermes_idstring {
365 __le16 len;
366 __le16 val[16];
367} __attribute__ ((packed));
368
369struct hermes_multicast {
370 u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN];
371} __attribute__ ((packed));
372
373/* Timeouts */
374#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */
375
376/* Basic control structure */
377typedef struct hermes {
378 void __iomem *iobase;
379 int reg_spacing;
380#define HERMES_16BIT_REGSPACING 0
381#define HERMES_32BIT_REGSPACING 1
382 u16 inten; /* Which interrupts should be enabled? */
383} hermes_t;
384
385/* Register access convenience macros */
386#define hermes_read_reg(hw, off) \
387 (ioread16((hw)->iobase + ( (off) << (hw)->reg_spacing )))
388#define hermes_write_reg(hw, off, val) \
389 (iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing)))
390#define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name)
391#define hermes_write_regn(hw, name, val) hermes_write_reg((hw), HERMES_##name, (val))
392
393/* Function prototypes */
394void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing);
395int hermes_init(hermes_t *hw);
396int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
397 struct hermes_response *resp);
398int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
399 u16 parm0, u16 parm1, u16 parm2,
400 struct hermes_response *resp);
401int hermes_allocate(hermes_t *hw, u16 size, u16 *fid);
402
403int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
404 u16 id, u16 offset);
405int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
406 u16 id, u16 offset);
407int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen,
408 u16 *length, void *buf);
409int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
410 u16 length, const void *value);
411
412/* Inline functions */
413
414static inline int hermes_present(hermes_t *hw)
415{
416 return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC;
417}
418
419static inline void hermes_set_irqmask(hermes_t *hw, u16 events)
420{
421 hw->inten = events;
422 hermes_write_regn(hw, INTEN, events);
423}
424
425static inline int hermes_enable_port(hermes_t *hw, int port)
426{
427 return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8),
428 0, NULL);
429}
430
431static inline int hermes_disable_port(hermes_t *hw, int port)
432{
433 return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8),
434 0, NULL);
435}
436
437/* Initiate an INQUIRE command (tallies or scan). The result will come as an
438 * information frame in __orinoco_ev_info() */
439static inline int hermes_inquire(hermes_t *hw, u16 rid)
440{
441 return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL);
442}
443
444#define HERMES_BYTES_TO_RECLEN(n) ( (((n)+1)/2) + 1 )
445#define HERMES_RECLEN_TO_BYTES(n) ( ((n)-1) * 2 )
446
447/* Note that for the next two, the count is in 16-bit words, not bytes */
448static inline void hermes_read_words(struct hermes *hw, int off, void *buf, unsigned count)
449{
450 off = off << hw->reg_spacing;
451 ioread16_rep(hw->iobase + off, buf, count);
452}
453
454static inline void hermes_write_bytes(struct hermes *hw, int off,
455 const char *buf, unsigned count)
456{
457 off = off << hw->reg_spacing;
458 iowrite16_rep(hw->iobase + off, buf, count >> 1);
459 if (unlikely(count & 1))
460 iowrite8(buf[count - 1], hw->iobase + off);
461}
462
463static inline void hermes_clear_words(struct hermes *hw, int off, unsigned count)
464{
465 unsigned i;
466
467 off = off << hw->reg_spacing;
468
469 for (i = 0; i < count; i++)
470 iowrite16(0, hw->iobase + off);
471}
472
473#define HERMES_READ_RECORD(hw, bap, rid, buf) \
474 (hermes_read_ltv((hw),(bap),(rid), sizeof(*buf), NULL, (buf)))
475#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \
476 (hermes_write_ltv((hw),(bap),(rid),HERMES_BYTES_TO_RECLEN(sizeof(*buf)),(buf)))
477
478static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word)
479{
480 __le16 rec;
481 int err;
482
483 err = HERMES_READ_RECORD(hw, bap, rid, &rec);
484 *word = le16_to_cpu(rec);
485 return err;
486}
487
488static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word)
489{
490 __le16 rec = cpu_to_le16(word);
491 return HERMES_WRITE_RECORD(hw, bap, rid, &rec);
492}
493
494#endif /* _HERMES_H */
diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c
new file mode 100644
index 000000000000..d8c626e61a3a
--- /dev/null
+++ b/drivers/net/wireless/orinoco/hermes_dld.c
@@ -0,0 +1,730 @@
1/*
2 * Hermes download helper driver.
3 *
4 * This could be entirely merged into hermes.c.
5 *
6 * I'm keeping it separate to minimise the amount of merging between
7 * kernel upgrades. It also means the memory overhead for drivers that
8 * don't need firmware download low.
9 *
10 * This driver:
11 * - is capable of writing to the volatile area of the hermes device
12 * - is currently not capable of writing to non-volatile areas
13 * - provide helpers to identify and update plugin data
14 * - is not capable of interpreting a fw image directly. That is up to
15 * the main card driver.
16 * - deals with Hermes I devices. It can probably be modified to deal
17 * with Hermes II devices
18 *
19 * Copyright (C) 2007, David Kilroy
20 *
21 * Plug data code slightly modified from spectrum_cs driver
22 * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
23 * Portions based on information in wl_lkm_718 Agere driver
24 * COPYRIGHT (C) 2001-2004 by Agere Systems Inc. All Rights Reserved
25 *
26 * The contents of this file are subject to the Mozilla Public License
27 * Version 1.1 (the "License"); you may not use this file except in
28 * compliance with the License. You may obtain a copy of the License
29 * at http://www.mozilla.org/MPL/
30 *
31 * Software distributed under the License is distributed on an "AS IS"
32 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
33 * the License for the specific language governing rights and
34 * limitations under the License.
35 *
36 * Alternatively, the contents of this file may be used under the
37 * terms of the GNU General Public License version 2 (the "GPL"), in
38 * which case the provisions of the GPL are applicable instead of the
39 * above. If you wish to allow the use of your version of this file
40 * only under the terms of the GPL and not to allow others to use your
41 * version of this file under the MPL, indicate your decision by
42 * deleting the provisions above and replace them with the notice and
43 * other provisions required by the GPL. If you do not delete the
44 * provisions above, a recipient may use your version of this file
45 * under either the MPL or the GPL.
46 */
47
48#include <linux/module.h>
49#include <linux/delay.h>
50#include "hermes.h"
51#include "hermes_dld.h"
52
53MODULE_DESCRIPTION("Download helper for Lucent Hermes chipset");
54MODULE_AUTHOR("David Kilroy <kilroyd@gmail.com>");
55MODULE_LICENSE("Dual MPL/GPL");
56
57#define PFX "hermes_dld: "
58
59/*
60 * AUX port access. To unlock the AUX port write the access keys to the
61 * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL
62 * register. Then read it and make sure it's HERMES_AUX_ENABLED.
63 */
64#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */
65#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */
66#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */
67#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */
68
69#define HERMES_AUX_PW0 0xFE01
70#define HERMES_AUX_PW1 0xDC23
71#define HERMES_AUX_PW2 0xBA45
72
73/* HERMES_CMD_DOWNLD */
74#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD)
75#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD)
76#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD)
77#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD)
78
79/* End markers used in dblocks */
80#define PDI_END 0x00000000 /* End of PDA */
81#define BLOCK_END 0xFFFFFFFF /* Last image block */
82#define TEXT_END 0x1A /* End of text header */
83
84/*
85 * PDA == Production Data Area
86 *
87 * In principle, the max. size of the PDA is is 4096 words. Currently,
88 * however, only about 500 bytes of this area are used.
89 *
90 * Some USB implementations can't handle sizes in excess of 1016. Note
91 * that PDA is not actually used in those USB environments, but may be
92 * retrieved by common code.
93 */
94#define MAX_PDA_SIZE 1000
95
96/* Limit the amout we try to download in a single shot.
97 * Size is in bytes.
98 */
99#define MAX_DL_SIZE 1024
100#define LIMIT_PROGRAM_SIZE 0
101
102/*
103 * The following structures have little-endian fields denoted by
104 * the leading underscore. Don't access them directly - use inline
105 * functions defined below.
106 */
107
108/*
109 * The binary image to be downloaded consists of series of data blocks.
110 * Each block has the following structure.
111 */
112struct dblock {
113 __le32 addr; /* adapter address where to write the block */
114 __le16 len; /* length of the data only, in bytes */
115 char data[0]; /* data to be written */
116} __attribute__ ((packed));
117
118/*
119 * Plug Data References are located in in the image after the last data
120 * block. They refer to areas in the adapter memory where the plug data
121 * items with matching ID should be written.
122 */
123struct pdr {
124 __le32 id; /* record ID */
125 __le32 addr; /* adapter address where to write the data */
126 __le32 len; /* expected length of the data, in bytes */
127 char next[0]; /* next PDR starts here */
128} __attribute__ ((packed));
129
130/*
131 * Plug Data Items are located in the EEPROM read from the adapter by
132 * primary firmware. They refer to the device-specific data that should
133 * be plugged into the secondary firmware.
134 */
135struct pdi {
136 __le16 len; /* length of ID and data, in words */
137 __le16 id; /* record ID */
138 char data[0]; /* plug data */
139} __attribute__ ((packed));
140
141/*** FW data block access functions ***/
142
143static inline u32
144dblock_addr(const struct dblock *blk)
145{
146 return le32_to_cpu(blk->addr);
147}
148
149static inline u32
150dblock_len(const struct dblock *blk)
151{
152 return le16_to_cpu(blk->len);
153}
154
155/*** PDR Access functions ***/
156
157static inline u32
158pdr_id(const struct pdr *pdr)
159{
160 return le32_to_cpu(pdr->id);
161}
162
163static inline u32
164pdr_addr(const struct pdr *pdr)
165{
166 return le32_to_cpu(pdr->addr);
167}
168
169static inline u32
170pdr_len(const struct pdr *pdr)
171{
172 return le32_to_cpu(pdr->len);
173}
174
175/*** PDI Access functions ***/
176
177static inline u32
178pdi_id(const struct pdi *pdi)
179{
180 return le16_to_cpu(pdi->id);
181}
182
183/* Return length of the data only, in bytes */
184static inline u32
185pdi_len(const struct pdi *pdi)
186{
187 return 2 * (le16_to_cpu(pdi->len) - 1);
188}
189
190/*** Hermes AUX control ***/
191
192static inline void
193hermes_aux_setaddr(hermes_t *hw, u32 addr)
194{
195 hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7));
196 hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F));
197}
198
199static inline int
200hermes_aux_control(hermes_t *hw, int enabled)
201{
202 int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED;
203 int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE;
204 int i;
205
206 /* Already open? */
207 if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state)
208 return 0;
209
210 hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0);
211 hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1);
212 hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2);
213 hermes_write_reg(hw, HERMES_CONTROL, action);
214
215 for (i = 0; i < 20; i++) {
216 udelay(10);
217 if (hermes_read_reg(hw, HERMES_CONTROL) ==
218 desired_state)
219 return 0;
220 }
221
222 return -EBUSY;
223}
224
225/*** Plug Data Functions ***/
226
227/*
228 * Scan PDR for the record with the specified RECORD_ID.
229 * If it's not found, return NULL.
230 */
231static struct pdr *
232hermes_find_pdr(struct pdr *first_pdr, u32 record_id)
233{
234 struct pdr *pdr = first_pdr;
235 void *end = (void *)first_pdr + MAX_PDA_SIZE;
236
237 while (((void *)pdr < end) &&
238 (pdr_id(pdr) != PDI_END)) {
239 /*
240 * PDR area is currently not terminated by PDI_END.
241 * It's followed by CRC records, which have the type
242 * field where PDR has length. The type can be 0 or 1.
243 */
244 if (pdr_len(pdr) < 2)
245 return NULL;
246
247 /* If the record ID matches, we are done */
248 if (pdr_id(pdr) == record_id)
249 return pdr;
250
251 pdr = (struct pdr *) pdr->next;
252 }
253 return NULL;
254}
255
256/* Scan production data items for a particular entry */
257static struct pdi *
258hermes_find_pdi(struct pdi *first_pdi, u32 record_id)
259{
260 struct pdi *pdi = first_pdi;
261
262 while (pdi_id(pdi) != PDI_END) {
263
264 /* If the record ID matches, we are done */
265 if (pdi_id(pdi) == record_id)
266 return pdi;
267
268 pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];
269 }
270 return NULL;
271}
272
273/* Process one Plug Data Item - find corresponding PDR and plug it */
274static int
275hermes_plug_pdi(hermes_t *hw, struct pdr *first_pdr, const struct pdi *pdi)
276{
277 struct pdr *pdr;
278
279 /* Find the PDR corresponding to this PDI */
280 pdr = hermes_find_pdr(first_pdr, pdi_id(pdi));
281
282 /* No match is found, safe to ignore */
283 if (!pdr)
284 return 0;
285
286 /* Lengths of the data in PDI and PDR must match */
287 if (pdi_len(pdi) != pdr_len(pdr))
288 return -EINVAL;
289
290 /* do the actual plugging */
291 hermes_aux_setaddr(hw, pdr_addr(pdr));
292 hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi));
293
294 return 0;
295}
296
297/* Read PDA from the adapter */
298int hermes_read_pda(hermes_t *hw,
299 __le16 *pda,
300 u32 pda_addr,
301 u16 pda_len,
302 int use_eeprom) /* can we get this into hw? */
303{
304 int ret;
305 u16 pda_size;
306 u16 data_len = pda_len;
307 __le16 *data = pda;
308
309 if (use_eeprom) {
310 /* PDA of spectrum symbol is in eeprom */
311
312 /* Issue command to read EEPROM */
313 ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);
314 if (ret)
315 return ret;
316 } else {
317 /* wl_lkm does not include PDA size in the PDA area.
318 * We will pad the information into pda, so other routines
319 * don't have to be modified */
320 pda[0] = cpu_to_le16(pda_len - 2);
321 /* Includes CFG_PROD_DATA but not itself */
322 pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */
323 data_len = pda_len - 4;
324 data = pda + 2;
325 }
326
327 /* Open auxiliary port */
328 ret = hermes_aux_control(hw, 1);
329 printk(KERN_DEBUG PFX "AUX enable returned %d\n", ret);
330 if (ret)
331 return ret;
332
333 /* read PDA from EEPROM */
334 hermes_aux_setaddr(hw, pda_addr);
335 hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2);
336
337 /* Close aux port */
338 ret = hermes_aux_control(hw, 0);
339 printk(KERN_DEBUG PFX "AUX disable returned %d\n", ret);
340
341 /* Check PDA length */
342 pda_size = le16_to_cpu(pda[0]);
343 printk(KERN_DEBUG PFX "Actual PDA length %d, Max allowed %d\n",
344 pda_size, pda_len);
345 if (pda_size > pda_len)
346 return -EINVAL;
347
348 return 0;
349}
350EXPORT_SYMBOL(hermes_read_pda);
351
352/* Parse PDA and write the records into the adapter
353 *
354 * Attempt to write every records that is in the specified pda
355 * which also has a valid production data record for the firmware.
356 */
357int hermes_apply_pda(hermes_t *hw,
358 const char *first_pdr,
359 const __le16 *pda)
360{
361 int ret;
362 const struct pdi *pdi;
363 struct pdr *pdr;
364
365 pdr = (struct pdr *) first_pdr;
366
367 /* Go through every PDI and plug them into the adapter */
368 pdi = (const struct pdi *) (pda + 2);
369 while (pdi_id(pdi) != PDI_END) {
370 ret = hermes_plug_pdi(hw, pdr, pdi);
371 if (ret)
372 return ret;
373
374 /* Increment to the next PDI */
375 pdi = (const struct pdi *) &pdi->data[pdi_len(pdi)];
376 }
377 return 0;
378}
379EXPORT_SYMBOL(hermes_apply_pda);
380
381/* Identify the total number of bytes in all blocks
382 * including the header data.
383 */
384size_t
385hermes_blocks_length(const char *first_block)
386{
387 const struct dblock *blk = (const struct dblock *) first_block;
388 int total_len = 0;
389 int len;
390
391 /* Skip all blocks to locate Plug Data References
392 * (Spectrum CS) */
393 while (dblock_addr(blk) != BLOCK_END) {
394 len = dblock_len(blk);
395 total_len += sizeof(*blk) + len;
396 blk = (struct dblock *) &blk->data[len];
397 }
398
399 return total_len;
400}
401EXPORT_SYMBOL(hermes_blocks_length);
402
403/*** Hermes programming ***/
404
405/* About to start programming data (Hermes I)
406 * offset is the entry point
407 *
408 * Spectrum_cs' Symbol fw does not require this
409 * wl_lkm Agere fw does
410 * Don't know about intersil
411 */
412int hermesi_program_init(hermes_t *hw, u32 offset)
413{
414 int err;
415
416 /* Disable interrupts?*/
417 /*hw->inten = 0x0;*/
418 /*hermes_write_regn(hw, INTEN, 0);*/
419 /*hermes_set_irqmask(hw, 0);*/
420
421 /* Acknowledge any outstanding command */
422 hermes_write_regn(hw, EVACK, 0xFFFF);
423
424 /* Using doicmd_wait rather than docmd_wait */
425 err = hermes_doicmd_wait(hw,
426 0x0100 | HERMES_CMD_INIT,
427 0, 0, 0, NULL);
428 if (err)
429 return err;
430
431 err = hermes_doicmd_wait(hw,
432 0x0000 | HERMES_CMD_INIT,
433 0, 0, 0, NULL);
434 if (err)
435 return err;
436
437 err = hermes_aux_control(hw, 1);
438 printk(KERN_DEBUG PFX "AUX enable returned %d\n", err);
439
440 if (err)
441 return err;
442
443 printk(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset);
444 err = hermes_doicmd_wait(hw,
445 HERMES_PROGRAM_ENABLE_VOLATILE,
446 offset & 0xFFFFu,
447 offset >> 16,
448 0,
449 NULL);
450 printk(KERN_DEBUG PFX "PROGRAM_ENABLE returned %d\n",
451 err);
452
453 return err;
454}
455EXPORT_SYMBOL(hermesi_program_init);
456
457/* Done programming data (Hermes I)
458 *
459 * Spectrum_cs' Symbol fw does not require this
460 * wl_lkm Agere fw does
461 * Don't know about intersil
462 */
463int hermesi_program_end(hermes_t *hw)
464{
465 struct hermes_response resp;
466 int rc = 0;
467 int err;
468
469 rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp);
470
471 printk(KERN_DEBUG PFX "PROGRAM_DISABLE returned %d, "
472 "r0 0x%04x, r1 0x%04x, r2 0x%04x\n",
473 rc, resp.resp0, resp.resp1, resp.resp2);
474
475 if ((rc == 0) &&
476 ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD))
477 rc = -EIO;
478
479 err = hermes_aux_control(hw, 0);
480 printk(KERN_DEBUG PFX "AUX disable returned %d\n", err);
481
482 /* Acknowledge any outstanding command */
483 hermes_write_regn(hw, EVACK, 0xFFFF);
484
485 /* Reinitialise, ignoring return */
486 (void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT,
487 0, 0, 0, NULL);
488
489 return rc ? rc : err;
490}
491EXPORT_SYMBOL(hermesi_program_end);
492
493/* Program the data blocks */
494int hermes_program(hermes_t *hw, const char *first_block, const char *end)
495{
496 const struct dblock *blk;
497 u32 blkaddr;
498 u32 blklen;
499#if LIMIT_PROGRAM_SIZE
500 u32 addr;
501 u32 len;
502#endif
503
504 blk = (const struct dblock *) first_block;
505
506 if ((const char *) blk > (end - sizeof(*blk)))
507 return -EIO;
508
509 blkaddr = dblock_addr(blk);
510 blklen = dblock_len(blk);
511
512 while ((blkaddr != BLOCK_END) &&
513 (((const char *) blk + blklen) <= end)) {
514 printk(KERN_DEBUG PFX
515 "Programming block of length %d to address 0x%08x\n",
516 blklen, blkaddr);
517
518#if !LIMIT_PROGRAM_SIZE
519 /* wl_lkm driver splits this into writes of 2000 bytes */
520 hermes_aux_setaddr(hw, blkaddr);
521 hermes_write_bytes(hw, HERMES_AUXDATA, blk->data,
522 blklen);
523#else
524 len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE;
525 addr = blkaddr;
526
527 while (addr < (blkaddr + blklen)) {
528 printk(KERN_DEBUG PFX
529 "Programming subblock of length %d "
530 "to address 0x%08x. Data @ %p\n",
531 len, addr, &blk->data[addr - blkaddr]);
532
533 hermes_aux_setaddr(hw, addr);
534 hermes_write_bytes(hw, HERMES_AUXDATA,
535 &blk->data[addr - blkaddr],
536 len);
537
538 addr += len;
539 len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ?
540 (blkaddr + blklen - addr) : MAX_DL_SIZE;
541 }
542#endif
543 blk = (const struct dblock *) &blk->data[blklen];
544
545 if ((const char *) blk > (end - sizeof(*blk)))
546 return -EIO;
547
548 blkaddr = dblock_addr(blk);
549 blklen = dblock_len(blk);
550 }
551 return 0;
552}
553EXPORT_SYMBOL(hermes_program);
554
555static int __init init_hermes_dld(void)
556{
557 return 0;
558}
559
560static void __exit exit_hermes_dld(void)
561{
562}
563
564module_init(init_hermes_dld);
565module_exit(exit_hermes_dld);
566
567/*** Default plugging data for Hermes I ***/
568/* Values from wl_lkm_718/hcf/dhf.c */
569
570#define DEFINE_DEFAULT_PDR(pid, length, data) \
571static const struct { \
572 __le16 len; \
573 __le16 id; \
574 u8 val[length]; \
575} __attribute__ ((packed)) default_pdr_data_##pid = { \
576 __constant_cpu_to_le16((sizeof(default_pdr_data_##pid)/ \
577 sizeof(__le16)) - 1), \
578 __constant_cpu_to_le16(pid), \
579 data \
580}
581
582#define DEFAULT_PDR(pid) default_pdr_data_##pid
583
584/* HWIF Compatiblity */
585DEFINE_DEFAULT_PDR(0x0005, 10, "\x00\x00\x06\x00\x01\x00\x01\x00\x01\x00");
586
587/* PPPPSign */
588DEFINE_DEFAULT_PDR(0x0108, 4, "\x00\x00\x00\x00");
589
590/* PPPPProf */
591DEFINE_DEFAULT_PDR(0x0109, 10, "\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00");
592
593/* Antenna diversity */
594DEFINE_DEFAULT_PDR(0x0150, 2, "\x00\x3F");
595
596/* Modem VCO band Set-up */
597DEFINE_DEFAULT_PDR(0x0160, 28,
598 "\x00\x00\x00\x00\x00\x00\x00\x00"
599 "\x00\x00\x00\x00\x00\x00\x00\x00"
600 "\x00\x00\x00\x00\x00\x00\x00\x00"
601 "\x00\x00\x00\x00");
602
603/* Modem Rx Gain Table Values */
604DEFINE_DEFAULT_PDR(0x0161, 256,
605 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
606 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
607 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
608 "\x3F\x01\x3F\01\x3F\x01\x3F\x01"
609 "\x3F\x01\x3E\01\x3E\x01\x3D\x01"
610 "\x3D\x01\x3C\01\x3C\x01\x3B\x01"
611 "\x3B\x01\x3A\01\x3A\x01\x39\x01"
612 "\x39\x01\x38\01\x38\x01\x37\x01"
613 "\x37\x01\x36\01\x36\x01\x35\x01"
614 "\x35\x01\x34\01\x34\x01\x33\x01"
615 "\x33\x01\x32\x01\x32\x01\x31\x01"
616 "\x31\x01\x30\x01\x30\x01\x7B\x01"
617 "\x7B\x01\x7A\x01\x7A\x01\x79\x01"
618 "\x79\x01\x78\x01\x78\x01\x77\x01"
619 "\x77\x01\x76\x01\x76\x01\x75\x01"
620 "\x75\x01\x74\x01\x74\x01\x73\x01"
621 "\x73\x01\x72\x01\x72\x01\x71\x01"
622 "\x71\x01\x70\x01\x70\x01\x68\x01"
623 "\x68\x01\x67\x01\x67\x01\x66\x01"
624 "\x66\x01\x65\x01\x65\x01\x57\x01"
625 "\x57\x01\x56\x01\x56\x01\x55\x01"
626 "\x55\x01\x54\x01\x54\x01\x53\x01"
627 "\x53\x01\x52\x01\x52\x01\x51\x01"
628 "\x51\x01\x50\x01\x50\x01\x48\x01"
629 "\x48\x01\x47\x01\x47\x01\x46\x01"
630 "\x46\x01\x45\x01\x45\x01\x44\x01"
631 "\x44\x01\x43\x01\x43\x01\x42\x01"
632 "\x42\x01\x41\x01\x41\x01\x40\x01"
633 "\x40\x01\x40\x01\x40\x01\x40\x01"
634 "\x40\x01\x40\x01\x40\x01\x40\x01"
635 "\x40\x01\x40\x01\x40\x01\x40\x01"
636 "\x40\x01\x40\x01\x40\x01\x40\x01");
637
638/* Write PDA according to certain rules.
639 *
640 * For every production data record, look for a previous setting in
641 * the pda, and use that.
642 *
643 * For certain records, use defaults if they are not found in pda.
644 */
645int hermes_apply_pda_with_defaults(hermes_t *hw,
646 const char *first_pdr,
647 const __le16 *pda)
648{
649 const struct pdr *pdr = (const struct pdr *) first_pdr;
650 struct pdi *first_pdi = (struct pdi *) &pda[2];
651 struct pdi *pdi;
652 struct pdi *default_pdi = NULL;
653 struct pdi *outdoor_pdi;
654 void *end = (void *)first_pdr + MAX_PDA_SIZE;
655 int record_id;
656
657 while (((void *)pdr < end) &&
658 (pdr_id(pdr) != PDI_END)) {
659 /*
660 * For spectrum_cs firmwares,
661 * PDR area is currently not terminated by PDI_END.
662 * It's followed by CRC records, which have the type
663 * field where PDR has length. The type can be 0 or 1.
664 */
665 if (pdr_len(pdr) < 2)
666 break;
667 record_id = pdr_id(pdr);
668
669 pdi = hermes_find_pdi(first_pdi, record_id);
670 if (pdi)
671 printk(KERN_DEBUG PFX "Found record 0x%04x at %p\n",
672 record_id, pdi);
673
674 switch (record_id) {
675 case 0x110: /* Modem REFDAC values */
676 case 0x120: /* Modem VGDAC values */
677 outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1);
678 default_pdi = NULL;
679 if (outdoor_pdi) {
680 pdi = outdoor_pdi;
681 printk(KERN_DEBUG PFX
682 "Using outdoor record 0x%04x at %p\n",
683 record_id + 1, pdi);
684 }
685 break;
686 case 0x5: /* HWIF Compatiblity */
687 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0005);
688 break;
689 case 0x108: /* PPPPSign */
690 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0108);
691 break;
692 case 0x109: /* PPPPProf */
693 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0109);
694 break;
695 case 0x150: /* Antenna diversity */
696 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0150);
697 break;
698 case 0x160: /* Modem VCO band Set-up */
699 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0160);
700 break;
701 case 0x161: /* Modem Rx Gain Table Values */
702 default_pdi = (struct pdi *) &DEFAULT_PDR(0x0161);
703 break;
704 default:
705 default_pdi = NULL;
706 break;
707 }
708 if (!pdi && default_pdi) {
709 /* Use default */
710 pdi = default_pdi;
711 printk(KERN_DEBUG PFX
712 "Using default record 0x%04x at %p\n",
713 record_id, pdi);
714 }
715
716 if (pdi) {
717 /* Lengths of the data in PDI and PDR must match */
718 if (pdi_len(pdi) == pdr_len(pdr)) {
719 /* do the actual plugging */
720 hermes_aux_setaddr(hw, pdr_addr(pdr));
721 hermes_write_bytes(hw, HERMES_AUXDATA,
722 pdi->data, pdi_len(pdi));
723 }
724 }
725
726 pdr++;
727 }
728 return 0;
729}
730EXPORT_SYMBOL(hermes_apply_pda_with_defaults);
diff --git a/drivers/net/wireless/orinoco/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h
new file mode 100644
index 000000000000..6fcb26277999
--- /dev/null
+++ b/drivers/net/wireless/orinoco/hermes_dld.h
@@ -0,0 +1,48 @@
1/*
2 * Copyright (C) 2007, David Kilroy
3 *
4 * The contents of this file are subject to the Mozilla Public License
5 * Version 1.1 (the "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy of the License
7 * at http://www.mozilla.org/MPL/
8 *
9 * Software distributed under the License is distributed on an "AS IS"
10 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
11 * the License for the specific language governing rights and
12 * limitations under the License.
13 *
14 * Alternatively, the contents of this file may be used under the
15 * terms of the GNU General Public License version 2 (the "GPL"), in
16 * which case the provisions of the GPL are applicable instead of the
17 * above. If you wish to allow the use of your version of this file
18 * only under the terms of the GPL and not to allow others to use your
19 * version of this file under the MPL, indicate your decision by
20 * deleting the provisions above and replace them with the notice and
21 * other provisions required by the GPL. If you do not delete the
22 * provisions above, a recipient may use your version of this file
23 * under either the MPL or the GPL.
24 */
25#ifndef _HERMES_DLD_H
26#define _HERMES_DLD_H
27
28#include "hermes.h"
29
30int hermesi_program_init(hermes_t *hw, u32 offset);
31int hermesi_program_end(hermes_t *hw);
32int hermes_program(hermes_t *hw, const char *first_block, const char *end);
33
34int hermes_read_pda(hermes_t *hw,
35 __le16 *pda,
36 u32 pda_addr,
37 u16 pda_len,
38 int use_eeprom);
39int hermes_apply_pda(hermes_t *hw,
40 const char *first_pdr,
41 const __le16 *pda);
42int hermes_apply_pda_with_defaults(hermes_t *hw,
43 const char *first_pdr,
44 const __le16 *pda);
45
46size_t hermes_blocks_length(const char *first_block);
47
48#endif /* _HERMES_DLD_H */
diff --git a/drivers/net/wireless/orinoco/hermes_rid.h b/drivers/net/wireless/orinoco/hermes_rid.h
new file mode 100644
index 000000000000..42eb67dea1df
--- /dev/null
+++ b/drivers/net/wireless/orinoco/hermes_rid.h
@@ -0,0 +1,165 @@
1#ifndef _HERMES_RID_H
2#define _HERMES_RID_H
3
4/*
5 * Configuration RIDs
6 */
7#define HERMES_RID_CNFPORTTYPE 0xFC00
8#define HERMES_RID_CNFOWNMACADDR 0xFC01
9#define HERMES_RID_CNFDESIREDSSID 0xFC02
10#define HERMES_RID_CNFOWNCHANNEL 0xFC03
11#define HERMES_RID_CNFOWNSSID 0xFC04
12#define HERMES_RID_CNFOWNATIMWINDOW 0xFC05
13#define HERMES_RID_CNFSYSTEMSCALE 0xFC06
14#define HERMES_RID_CNFMAXDATALEN 0xFC07
15#define HERMES_RID_CNFWDSADDRESS 0xFC08
16#define HERMES_RID_CNFPMENABLED 0xFC09
17#define HERMES_RID_CNFPMEPS 0xFC0A
18#define HERMES_RID_CNFMULTICASTRECEIVE 0xFC0B
19#define HERMES_RID_CNFMAXSLEEPDURATION 0xFC0C
20#define HERMES_RID_CNFPMHOLDOVERDURATION 0xFC0D
21#define HERMES_RID_CNFOWNNAME 0xFC0E
22#define HERMES_RID_CNFOWNDTIMPERIOD 0xFC10
23#define HERMES_RID_CNFWDSADDRESS1 0xFC11
24#define HERMES_RID_CNFWDSADDRESS2 0xFC12
25#define HERMES_RID_CNFWDSADDRESS3 0xFC13
26#define HERMES_RID_CNFWDSADDRESS4 0xFC14
27#define HERMES_RID_CNFWDSADDRESS5 0xFC15
28#define HERMES_RID_CNFWDSADDRESS6 0xFC16
29#define HERMES_RID_CNFMULTICASTPMBUFFERING 0xFC17
30#define HERMES_RID_CNFWEPENABLED_AGERE 0xFC20
31#define HERMES_RID_CNFAUTHENTICATION_AGERE 0xFC21
32#define HERMES_RID_CNFMANDATORYBSSID_SYMBOL 0xFC21
33#define HERMES_RID_CNFDROPUNENCRYPTED 0xFC22
34#define HERMES_RID_CNFWEPDEFAULTKEYID 0xFC23
35#define HERMES_RID_CNFDEFAULTKEY0 0xFC24
36#define HERMES_RID_CNFDEFAULTKEY1 0xFC25
37#define HERMES_RID_CNFMWOROBUST_AGERE 0xFC25
38#define HERMES_RID_CNFDEFAULTKEY2 0xFC26
39#define HERMES_RID_CNFDEFAULTKEY3 0xFC27
40#define HERMES_RID_CNFWEPFLAGS_INTERSIL 0xFC28
41#define HERMES_RID_CNFWEPKEYMAPPINGTABLE 0xFC29
42#define HERMES_RID_CNFAUTHENTICATION 0xFC2A
43#define HERMES_RID_CNFMAXASSOCSTA 0xFC2B
44#define HERMES_RID_CNFKEYLENGTH_SYMBOL 0xFC2B
45#define HERMES_RID_CNFTXCONTROL 0xFC2C
46#define HERMES_RID_CNFROAMINGMODE 0xFC2D
47#define HERMES_RID_CNFHOSTAUTHENTICATION 0xFC2E
48#define HERMES_RID_CNFRCVCRCERROR 0xFC30
49#define HERMES_RID_CNFMMLIFE 0xFC31
50#define HERMES_RID_CNFALTRETRYCOUNT 0xFC32
51#define HERMES_RID_CNFBEACONINT 0xFC33
52#define HERMES_RID_CNFAPPCFINFO 0xFC34
53#define HERMES_RID_CNFSTAPCFINFO 0xFC35
54#define HERMES_RID_CNFPRIORITYQUSAGE 0xFC37
55#define HERMES_RID_CNFTIMCTRL 0xFC40
56#define HERMES_RID_CNFTHIRTY2TALLY 0xFC42
57#define HERMES_RID_CNFENHSECURITY 0xFC43
58#define HERMES_RID_CNFGROUPADDRESSES 0xFC80
59#define HERMES_RID_CNFCREATEIBSS 0xFC81
60#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD 0xFC82
61#define HERMES_RID_CNFRTSTHRESHOLD 0xFC83
62#define HERMES_RID_CNFTXRATECONTROL 0xFC84
63#define HERMES_RID_CNFPROMISCUOUSMODE 0xFC85
64#define HERMES_RID_CNFBASICRATES_SYMBOL 0xFC8A
65#define HERMES_RID_CNFPREAMBLE_SYMBOL 0xFC8C
66#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0 0xFC90
67#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1 0xFC91
68#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2 0xFC92
69#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD3 0xFC93
70#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD4 0xFC94
71#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD5 0xFC95
72#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD6 0xFC96
73#define HERMES_RID_CNFRTSTHRESHOLD0 0xFC97
74#define HERMES_RID_CNFRTSTHRESHOLD1 0xFC98
75#define HERMES_RID_CNFRTSTHRESHOLD2 0xFC99
76#define HERMES_RID_CNFRTSTHRESHOLD3 0xFC9A
77#define HERMES_RID_CNFRTSTHRESHOLD4 0xFC9B
78#define HERMES_RID_CNFRTSTHRESHOLD5 0xFC9C
79#define HERMES_RID_CNFRTSTHRESHOLD6 0xFC9D
80#define HERMES_RID_CNFHOSTSCAN_SYMBOL 0xFCAB
81#define HERMES_RID_CNFSHORTPREAMBLE 0xFCB0
82#define HERMES_RID_CNFWEPKEYS_AGERE 0xFCB0
83#define HERMES_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1
84#define HERMES_RID_CNFTXKEY_AGERE 0xFCB1
85#define HERMES_RID_CNFAUTHENTICATIONRSPTO 0xFCB2
86#define HERMES_RID_CNFSCANSSID_AGERE 0xFCB2
87#define HERMES_RID_CNFBASICRATES 0xFCB3
88#define HERMES_RID_CNFSUPPORTEDRATES 0xFCB4
89#define HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE 0xFCB4
90#define HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE 0xFCB5
91#define HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE 0xFCB6
92#define HERMES_RID_CNFADDMAPPEDTKIPKEY_AGERE 0xFCB7
93#define HERMES_RID_CNFREMMAPPEDTKIPKEY_AGERE 0xFCB8
94#define HERMES_RID_CNFSETWPACAPABILITIES_AGERE 0xFCB9
95#define HERMES_RID_CNFCACHEDPMKADDRESS 0xFCBA
96#define HERMES_RID_CNFREMOVEPMKADDRESS 0xFCBB
97#define HERMES_RID_CNFSCANCHANNELS2GHZ 0xFCC2
98#define HERMES_RID_CNFDISASSOCIATE 0xFCC8
99#define HERMES_RID_CNFTICKTIME 0xFCE0
100#define HERMES_RID_CNFSCANREQUEST 0xFCE1
101#define HERMES_RID_CNFJOINREQUEST 0xFCE2
102#define HERMES_RID_CNFAUTHENTICATESTATION 0xFCE3
103#define HERMES_RID_CNFCHANNELINFOREQUEST 0xFCE4
104#define HERMES_RID_CNFHOSTSCAN 0xFCE5
105
106/*
107 * Information RIDs
108 */
109#define HERMES_RID_MAXLOADTIME 0xFD00
110#define HERMES_RID_DOWNLOADBUFFER 0xFD01
111#define HERMES_RID_PRIID 0xFD02
112#define HERMES_RID_PRISUPRANGE 0xFD03
113#define HERMES_RID_CFIACTRANGES 0xFD04
114#define HERMES_RID_NICSERNUM 0xFD0A
115#define HERMES_RID_NICID 0xFD0B
116#define HERMES_RID_MFISUPRANGE 0xFD0C
117#define HERMES_RID_CFISUPRANGE 0xFD0D
118#define HERMES_RID_CHANNELLIST 0xFD10
119#define HERMES_RID_REGULATORYDOMAINS 0xFD11
120#define HERMES_RID_TEMPTYPE 0xFD12
121#define HERMES_RID_CIS 0xFD13
122#define HERMES_RID_STAID 0xFD20
123#define HERMES_RID_STASUPRANGE 0xFD21
124#define HERMES_RID_MFIACTRANGES 0xFD22
125#define HERMES_RID_CFIACTRANGES2 0xFD23
126#define HERMES_RID_SECONDARYVERSION_SYMBOL 0xFD24
127#define HERMES_RID_PORTSTATUS 0xFD40
128#define HERMES_RID_CURRENTSSID 0xFD41
129#define HERMES_RID_CURRENTBSSID 0xFD42
130#define HERMES_RID_COMMSQUALITY 0xFD43
131#define HERMES_RID_CURRENTTXRATE 0xFD44
132#define HERMES_RID_CURRENTBEACONINTERVAL 0xFD45
133#define HERMES_RID_CURRENTSCALETHRESHOLDS 0xFD46
134#define HERMES_RID_PROTOCOLRSPTIME 0xFD47
135#define HERMES_RID_SHORTRETRYLIMIT 0xFD48
136#define HERMES_RID_LONGRETRYLIMIT 0xFD49
137#define HERMES_RID_MAXTRANSMITLIFETIME 0xFD4A
138#define HERMES_RID_MAXRECEIVELIFETIME 0xFD4B
139#define HERMES_RID_CFPOLLABLE 0xFD4C
140#define HERMES_RID_AUTHENTICATIONALGORITHMS 0xFD4D
141#define HERMES_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F
142#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL 0xFD51
143#define HERMES_RID_CURRENTTXRATE1 0xFD80
144#define HERMES_RID_CURRENTTXRATE2 0xFD81
145#define HERMES_RID_CURRENTTXRATE3 0xFD82
146#define HERMES_RID_CURRENTTXRATE4 0xFD83
147#define HERMES_RID_CURRENTTXRATE5 0xFD84
148#define HERMES_RID_CURRENTTXRATE6 0xFD85
149#define HERMES_RID_OWNMACADDR 0xFD86
150#define HERMES_RID_SCANRESULTSTABLE 0xFD88
151#define HERMES_RID_CURRENT_COUNTRY_INFO 0xFD89
152#define HERMES_RID_CURRENT_WPA_IE 0xFD8A
153#define HERMES_RID_CURRENT_TKIP_IV 0xFD8B
154#define HERMES_RID_CURRENT_ASSOC_REQ_INFO 0xFD8C
155#define HERMES_RID_CURRENT_ASSOC_RESP_INFO 0xFD8D
156#define HERMES_RID_TXQUEUEEMPTY 0xFD91
157#define HERMES_RID_PHYTYPE 0xFDC0
158#define HERMES_RID_CURRENTCHANNEL 0xFDC1
159#define HERMES_RID_CURRENTPOWERSTATE 0xFDC2
160#define HERMES_RID_CCAMODE 0xFDC3
161#define HERMES_RID_SUPPORTEDDATARATES 0xFDC6
162#define HERMES_RID_BUILDSEQ 0xFFFE
163#define HERMES_RID_FWID 0xFFFF
164
165#endif
diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c
new file mode 100644
index 000000000000..f4ea08f96970
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco.c
@@ -0,0 +1,6032 @@
1/* orinoco.c - (formerly known as dldwd_cs.c and orinoco_cs.c)
2 *
3 * A driver for Hermes or Prism 2 chipset based PCMCIA wireless
4 * adaptors, with Lucent/Agere, Intersil or Symbol firmware.
5 *
6 * Current maintainers (as of 29 September 2003) are:
7 * Pavel Roskin <proski AT gnu.org>
8 * and David Gibson <hermes AT gibson.dropbear.id.au>
9 *
10 * (C) Copyright David Gibson, IBM Corporation 2001-2003.
11 * Copyright (C) 2000 David Gibson, Linuxcare Australia.
12 * With some help from :
13 * Copyright (C) 2001 Jean Tourrilhes, HP Labs
14 * Copyright (C) 2001 Benjamin Herrenschmidt
15 *
16 * Based on dummy_cs.c 1.27 2000/06/12 21:27:25
17 *
18 * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus <andy
19 * AT fasta.fh-dortmund.de>
20 * http://www.stud.fh-dortmund.de/~andy/wvlan/
21 *
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License
25 * at http://www.mozilla.org/MPL/
26 *
27 * Software distributed under the License is distributed on an "AS IS"
28 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
29 * the License for the specific language governing rights and
30 * limitations under the License.
31 *
32 * The initial developer of the original code is David A. Hinds
33 * <dahinds AT users.sourceforge.net>. Portions created by David
34 * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights
35 * Reserved.
36 *
37 * Alternatively, the contents of this file may be used under the
38 * terms of the GNU General Public License version 2 (the "GPL"), in
39 * which case the provisions of the GPL are applicable instead of the
40 * above. If you wish to allow the use of your version of this file
41 * only under the terms of the GPL and not to allow others to use your
42 * version of this file under the MPL, indicate your decision by
43 * deleting the provisions above and replace them with the notice and
44 * other provisions required by the GPL. If you do not delete the
45 * provisions above, a recipient may use your version of this file
46 * under either the MPL or the GPL. */
47
48/*
49 * TODO
50 * o Handle de-encapsulation within network layer, provide 802.11
51 * headers (patch from Thomas 'Dent' Mirlacher)
52 * o Fix possible races in SPY handling.
53 * o Disconnect wireless extensions from fundamental configuration.
54 * o (maybe) Software WEP support (patch from Stano Meduna).
55 * o (maybe) Use multiple Tx buffers - driver handling queue
56 * rather than firmware.
57 */
58
59/* Locking and synchronization:
60 *
61 * The basic principle is that everything is serialized through a
62 * single spinlock, priv->lock. The lock is used in user, bh and irq
63 * context, so when taken outside hardirq context it should always be
64 * taken with interrupts disabled. The lock protects both the
65 * hardware and the struct orinoco_private.
66 *
67 * Another flag, priv->hw_unavailable indicates that the hardware is
68 * unavailable for an extended period of time (e.g. suspended, or in
69 * the middle of a hard reset). This flag is protected by the
70 * spinlock. All code which touches the hardware should check the
71 * flag after taking the lock, and if it is set, give up on whatever
72 * they are doing and drop the lock again. The orinoco_lock()
73 * function handles this (it unlocks and returns -EBUSY if
74 * hw_unavailable is non-zero).
75 */
76
77#define DRIVER_NAME "orinoco"
78
79#include <linux/module.h>
80#include <linux/kernel.h>
81#include <linux/init.h>
82#include <linux/delay.h>
83#include <linux/netdevice.h>
84#include <linux/etherdevice.h>
85#include <linux/ethtool.h>
86#include <linux/firmware.h>
87#include <linux/if_arp.h>
88#include <linux/wireless.h>
89#include <linux/ieee80211.h>
90#include <net/iw_handler.h>
91
92#include <linux/scatterlist.h>
93#include <linux/crypto.h>
94
95#include "hermes_rid.h"
96#include "hermes_dld.h"
97#include "orinoco.h"
98
99/********************************************************************/
100/* Module information */
101/********************************************************************/
102
103MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
104MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based and similar wireless cards");
105MODULE_LICENSE("Dual MPL/GPL");
106
107/* Level of debugging. Used in the macros in orinoco.h */
108#ifdef ORINOCO_DEBUG
109int orinoco_debug = ORINOCO_DEBUG;
110module_param(orinoco_debug, int, 0644);
111MODULE_PARM_DESC(orinoco_debug, "Debug level");
112EXPORT_SYMBOL(orinoco_debug);
113#endif
114
115static int suppress_linkstatus; /* = 0 */
116module_param(suppress_linkstatus, bool, 0644);
117MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
118static int ignore_disconnect; /* = 0 */
119module_param(ignore_disconnect, int, 0644);
120MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
121
122static int force_monitor; /* = 0 */
123module_param(force_monitor, int, 0644);
124MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions");
125
126/********************************************************************/
127/* Compile time configuration and compatibility stuff */
128/********************************************************************/
129
130/* We do this this way to avoid ifdefs in the actual code */
131#ifdef WIRELESS_SPY
132#define SPY_NUMBER(priv) (priv->spy_data.spy_number)
133#else
134#define SPY_NUMBER(priv) 0
135#endif /* WIRELESS_SPY */
136
137/********************************************************************/
138/* Internal constants */
139/********************************************************************/
140
141/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
142static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
143#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2)
144
145#define ORINOCO_MIN_MTU 256
146#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD)
147
148#define SYMBOL_MAX_VER_LEN (14)
149#define USER_BAP 0
150#define IRQ_BAP 1
151#define MAX_IRQLOOPS_PER_IRQ 10
152#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of
153 * how many events the
154 * device could
155 * legitimately generate */
156#define SMALL_KEY_SIZE 5
157#define LARGE_KEY_SIZE 13
158#define TX_NICBUF_SIZE_BUG 1585 /* Bug in Symbol firmware */
159
160#define DUMMY_FID 0xFFFF
161
162/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \
163 HERMES_MAX_MULTICAST : 0)*/
164#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST)
165
166#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \
167 | HERMES_EV_TX | HERMES_EV_TXEXC \
168 | HERMES_EV_WTERR | HERMES_EV_INFO \
169 | HERMES_EV_INFDROP )
170
171#define MAX_RID_LEN 1024
172
173static const struct iw_handler_def orinoco_handler_def;
174static const struct ethtool_ops orinoco_ethtool_ops;
175
176/********************************************************************/
177/* Data tables */
178/********************************************************************/
179
180/* The frequency of each channel in MHz */
181static const long channel_frequency[] = {
182 2412, 2417, 2422, 2427, 2432, 2437, 2442,
183 2447, 2452, 2457, 2462, 2467, 2472, 2484
184};
185#define NUM_CHANNELS ARRAY_SIZE(channel_frequency)
186
187/* This tables gives the actual meanings of the bitrate IDs returned
188 * by the firmware. */
189static struct {
190 int bitrate; /* in 100s of kilobits */
191 int automatic;
192 u16 agere_txratectrl;
193 u16 intersil_txratectrl;
194} bitrate_table[] = {
195 {110, 1, 3, 15}, /* Entry 0 is the default */
196 {10, 0, 1, 1},
197 {10, 1, 1, 1},
198 {20, 0, 2, 2},
199 {20, 1, 6, 3},
200 {55, 0, 4, 4},
201 {55, 1, 7, 7},
202 {110, 0, 5, 8},
203};
204#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
205
206/********************************************************************/
207/* Data types */
208/********************************************************************/
209
210/* Beginning of the Tx descriptor, used in TxExc handling */
211struct hermes_txexc_data {
212 struct hermes_tx_descriptor desc;
213 __le16 frame_ctl;
214 __le16 duration_id;
215 u8 addr1[ETH_ALEN];
216} __attribute__ ((packed));
217
218/* Rx frame header except compatibility 802.3 header */
219struct hermes_rx_descriptor {
220 /* Control */
221 __le16 status;
222 __le32 time;
223 u8 silence;
224 u8 signal;
225 u8 rate;
226 u8 rxflow;
227 __le32 reserved;
228
229 /* 802.11 header */
230 __le16 frame_ctl;
231 __le16 duration_id;
232 u8 addr1[ETH_ALEN];
233 u8 addr2[ETH_ALEN];
234 u8 addr3[ETH_ALEN];
235 __le16 seq_ctl;
236 u8 addr4[ETH_ALEN];
237
238 /* Data length */
239 __le16 data_len;
240} __attribute__ ((packed));
241
242/********************************************************************/
243/* Function prototypes */
244/********************************************************************/
245
246static int __orinoco_program_rids(struct net_device *dev);
247static void __orinoco_set_multicast_list(struct net_device *dev);
248
249/********************************************************************/
250/* Michael MIC crypto setup */
251/********************************************************************/
252#define MICHAEL_MIC_LEN 8
253static int orinoco_mic_init(struct orinoco_private *priv)
254{
255 priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
256 if (IS_ERR(priv->tx_tfm_mic)) {
257 printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
258 "crypto API michael_mic\n");
259 priv->tx_tfm_mic = NULL;
260 return -ENOMEM;
261 }
262
263 priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0);
264 if (IS_ERR(priv->rx_tfm_mic)) {
265 printk(KERN_DEBUG "orinoco_mic_init: could not allocate "
266 "crypto API michael_mic\n");
267 priv->rx_tfm_mic = NULL;
268 return -ENOMEM;
269 }
270
271 return 0;
272}
273
274static void orinoco_mic_free(struct orinoco_private *priv)
275{
276 if (priv->tx_tfm_mic)
277 crypto_free_hash(priv->tx_tfm_mic);
278 if (priv->rx_tfm_mic)
279 crypto_free_hash(priv->rx_tfm_mic);
280}
281
282static int michael_mic(struct crypto_hash *tfm_michael, u8 *key,
283 u8 *da, u8 *sa, u8 priority,
284 u8 *data, size_t data_len, u8 *mic)
285{
286 struct hash_desc desc;
287 struct scatterlist sg[2];
288 u8 hdr[ETH_HLEN + 2]; /* size of header + padding */
289
290 if (tfm_michael == NULL) {
291 printk(KERN_WARNING "michael_mic: tfm_michael == NULL\n");
292 return -1;
293 }
294
295 /* Copy header into buffer. We need the padding on the end zeroed */
296 memcpy(&hdr[0], da, ETH_ALEN);
297 memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN);
298 hdr[ETH_ALEN*2] = priority;
299 hdr[ETH_ALEN*2+1] = 0;
300 hdr[ETH_ALEN*2+2] = 0;
301 hdr[ETH_ALEN*2+3] = 0;
302
303 /* Use scatter gather to MIC header and data in one go */
304 sg_init_table(sg, 2);
305 sg_set_buf(&sg[0], hdr, sizeof(hdr));
306 sg_set_buf(&sg[1], data, data_len);
307
308 if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN))
309 return -1;
310
311 desc.tfm = tfm_michael;
312 desc.flags = 0;
313 return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr),
314 mic);
315}
316
317/********************************************************************/
318/* Internal helper functions */
319/********************************************************************/
320
321static inline void set_port_type(struct orinoco_private *priv)
322{
323 switch (priv->iw_mode) {
324 case IW_MODE_INFRA:
325 priv->port_type = 1;
326 priv->createibss = 0;
327 break;
328 case IW_MODE_ADHOC:
329 if (priv->prefer_port3) {
330 priv->port_type = 3;
331 priv->createibss = 0;
332 } else {
333 priv->port_type = priv->ibss_port;
334 priv->createibss = 1;
335 }
336 break;
337 case IW_MODE_MONITOR:
338 priv->port_type = 3;
339 priv->createibss = 0;
340 break;
341 default:
342 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
343 priv->ndev->name);
344 }
345}
346
347#define ORINOCO_MAX_BSS_COUNT 64
348static int orinoco_bss_data_allocate(struct orinoco_private *priv)
349{
350 if (priv->bss_xbss_data)
351 return 0;
352
353 if (priv->has_ext_scan)
354 priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
355 sizeof(struct xbss_element),
356 GFP_KERNEL);
357 else
358 priv->bss_xbss_data = kzalloc(ORINOCO_MAX_BSS_COUNT *
359 sizeof(struct bss_element),
360 GFP_KERNEL);
361
362 if (!priv->bss_xbss_data) {
363 printk(KERN_WARNING "Out of memory allocating beacons");
364 return -ENOMEM;
365 }
366 return 0;
367}
368
369static void orinoco_bss_data_free(struct orinoco_private *priv)
370{
371 kfree(priv->bss_xbss_data);
372 priv->bss_xbss_data = NULL;
373}
374
375#define PRIV_BSS ((struct bss_element *)priv->bss_xbss_data)
376#define PRIV_XBSS ((struct xbss_element *)priv->bss_xbss_data)
377static void orinoco_bss_data_init(struct orinoco_private *priv)
378{
379 int i;
380
381 INIT_LIST_HEAD(&priv->bss_free_list);
382 INIT_LIST_HEAD(&priv->bss_list);
383 if (priv->has_ext_scan)
384 for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
385 list_add_tail(&(PRIV_XBSS[i].list),
386 &priv->bss_free_list);
387 else
388 for (i = 0; i < ORINOCO_MAX_BSS_COUNT; i++)
389 list_add_tail(&(PRIV_BSS[i].list),
390 &priv->bss_free_list);
391
392}
393
394static inline u8 *orinoco_get_ie(u8 *data, size_t len,
395 enum ieee80211_eid eid)
396{
397 u8 *p = data;
398 while ((p + 2) < (data + len)) {
399 if (p[0] == eid)
400 return p;
401 p += p[1] + 2;
402 }
403 return NULL;
404}
405
406#define WPA_OUI_TYPE "\x00\x50\xF2\x01"
407#define WPA_SELECTOR_LEN 4
408static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
409{
410 u8 *p = data;
411 while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
412 if ((p[0] == WLAN_EID_GENERIC) &&
413 (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
414 return p;
415 p += p[1] + 2;
416 }
417 return NULL;
418}
419
420
421/********************************************************************/
422/* Download functionality */
423/********************************************************************/
424
425struct fw_info {
426 char *pri_fw;
427 char *sta_fw;
428 char *ap_fw;
429 u32 pda_addr;
430 u16 pda_size;
431};
432
433const static struct fw_info orinoco_fw[] = {
434 { "", "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 },
435 { "", "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 },
436 { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", "", 0x00003100, 512 }
437};
438
439/* Structure used to access fields in FW
440 * Make sure LE decoding macros are used
441 */
442struct orinoco_fw_header {
443 char hdr_vers[6]; /* ASCII string for header version */
444 __le16 headersize; /* Total length of header */
445 __le32 entry_point; /* NIC entry point */
446 __le32 blocks; /* Number of blocks to program */
447 __le32 block_offset; /* Offset of block data from eof header */
448 __le32 pdr_offset; /* Offset to PDR data from eof header */
449 __le32 pri_offset; /* Offset to primary plug data */
450 __le32 compat_offset; /* Offset to compatibility data*/
451 char signature[0]; /* FW signature length headersize-20 */
452} __attribute__ ((packed));
453
454/* Download either STA or AP firmware into the card. */
455static int
456orinoco_dl_firmware(struct orinoco_private *priv,
457 const struct fw_info *fw,
458 int ap)
459{
460 /* Plug Data Area (PDA) */
461 __le16 *pda;
462
463 hermes_t *hw = &priv->hw;
464 const struct firmware *fw_entry;
465 const struct orinoco_fw_header *hdr;
466 const unsigned char *first_block;
467 const unsigned char *end;
468 const char *firmware;
469 struct net_device *dev = priv->ndev;
470 int err = 0;
471
472 pda = kzalloc(fw->pda_size, GFP_KERNEL);
473 if (!pda)
474 return -ENOMEM;
475
476 if (ap)
477 firmware = fw->ap_fw;
478 else
479 firmware = fw->sta_fw;
480
481 printk(KERN_DEBUG "%s: Attempting to download firmware %s\n",
482 dev->name, firmware);
483
484 /* Read current plug data */
485 err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0);
486 printk(KERN_DEBUG "%s: Read PDA returned %d\n", dev->name, err);
487 if (err)
488 goto free;
489
490 if (priv->cached_fw)
491 fw_entry = priv->cached_fw;
492 else {
493 err = request_firmware(&fw_entry, firmware, priv->dev);
494 if (err) {
495 printk(KERN_ERR "%s: Cannot find firmware %s\n",
496 dev->name, firmware);
497 err = -ENOENT;
498 goto free;
499 }
500 priv->cached_fw = fw_entry;
501 }
502
503 hdr = (const struct orinoco_fw_header *) fw_entry->data;
504
505 /* Enable aux port to allow programming */
506 err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point));
507 printk(KERN_DEBUG "%s: Program init returned %d\n", dev->name, err);
508 if (err != 0)
509 goto abort;
510
511 /* Program data */
512 first_block = (fw_entry->data +
513 le16_to_cpu(hdr->headersize) +
514 le32_to_cpu(hdr->block_offset));
515 end = fw_entry->data + fw_entry->size;
516
517 err = hermes_program(hw, first_block, end);
518 printk(KERN_DEBUG "%s: Program returned %d\n", dev->name, err);
519 if (err != 0)
520 goto abort;
521
522 /* Update production data */
523 first_block = (fw_entry->data +
524 le16_to_cpu(hdr->headersize) +
525 le32_to_cpu(hdr->pdr_offset));
526
527 err = hermes_apply_pda_with_defaults(hw, first_block, pda);
528 printk(KERN_DEBUG "%s: Apply PDA returned %d\n", dev->name, err);
529 if (err)
530 goto abort;
531
532 /* Tell card we've finished */
533 err = hermesi_program_end(hw);
534 printk(KERN_DEBUG "%s: Program end returned %d\n", dev->name, err);
535 if (err != 0)
536 goto abort;
537
538 /* Check if we're running */
539 printk(KERN_DEBUG "%s: hermes_present returned %d\n",
540 dev->name, hermes_present(hw));
541
542abort:
543 /* In case of error, assume firmware was bogus and release it */
544 if (err) {
545 priv->cached_fw = NULL;
546 release_firmware(fw_entry);
547 }
548
549free:
550 kfree(pda);
551 return err;
552}
553
554/* End markers */
555#define TEXT_END 0x1A /* End of text header */
556
557/*
558 * Process a firmware image - stop the card, load the firmware, reset
559 * the card and make sure it responds. For the secondary firmware take
560 * care of the PDA - read it and then write it on top of the firmware.
561 */
562static int
563symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw,
564 const unsigned char *image, const unsigned char *end,
565 int secondary)
566{
567 hermes_t *hw = &priv->hw;
568 int ret = 0;
569 const unsigned char *ptr;
570 const unsigned char *first_block;
571
572 /* Plug Data Area (PDA) */
573 __le16 *pda = NULL;
574
575 /* Binary block begins after the 0x1A marker */
576 ptr = image;
577 while (*ptr++ != TEXT_END);
578 first_block = ptr;
579
580 /* Read the PDA from EEPROM */
581 if (secondary) {
582 pda = kzalloc(fw->pda_size, GFP_KERNEL);
583 if (!pda)
584 return -ENOMEM;
585
586 ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1);
587 if (ret)
588 goto free;
589 }
590
591 /* Stop the firmware, so that it can be safely rewritten */
592 if (priv->stop_fw) {
593 ret = priv->stop_fw(priv, 1);
594 if (ret)
595 goto free;
596 }
597
598 /* Program the adapter with new firmware */
599 ret = hermes_program(hw, first_block, end);
600 if (ret)
601 goto free;
602
603 /* Write the PDA to the adapter */
604 if (secondary) {
605 size_t len = hermes_blocks_length(first_block);
606 ptr = first_block + len;
607 ret = hermes_apply_pda(hw, ptr, pda);
608 kfree(pda);
609 if (ret)
610 return ret;
611 }
612
613 /* Run the firmware */
614 if (priv->stop_fw) {
615 ret = priv->stop_fw(priv, 0);
616 if (ret)
617 return ret;
618 }
619
620 /* Reset hermes chip and make sure it responds */
621 ret = hermes_init(hw);
622
623 /* hermes_reset() should return 0 with the secondary firmware */
624 if (secondary && ret != 0)
625 return -ENODEV;
626
627 /* And this should work with any firmware */
628 if (!hermes_present(hw))
629 return -ENODEV;
630
631 return 0;
632
633free:
634 kfree(pda);
635 return ret;
636}
637
638
639/*
640 * Download the firmware into the card, this also does a PCMCIA soft
641 * reset on the card, to make sure it's in a sane state.
642 */
643static int
644symbol_dl_firmware(struct orinoco_private *priv,
645 const struct fw_info *fw)
646{
647 struct net_device *dev = priv->ndev;
648 int ret;
649 const struct firmware *fw_entry;
650
651 if (request_firmware(&fw_entry, fw->pri_fw,
652 priv->dev) != 0) {
653 printk(KERN_ERR "%s: Cannot find firmware: %s\n",
654 dev->name, fw->pri_fw);
655 return -ENOENT;
656 }
657
658 /* Load primary firmware */
659 ret = symbol_dl_image(priv, fw, fw_entry->data,
660 fw_entry->data + fw_entry->size, 0);
661 release_firmware(fw_entry);
662 if (ret) {
663 printk(KERN_ERR "%s: Primary firmware download failed\n",
664 dev->name);
665 return ret;
666 }
667
668 if (request_firmware(&fw_entry, fw->sta_fw,
669 priv->dev) != 0) {
670 printk(KERN_ERR "%s: Cannot find firmware: %s\n",
671 dev->name, fw->sta_fw);
672 return -ENOENT;
673 }
674
675 /* Load secondary firmware */
676 ret = symbol_dl_image(priv, fw, fw_entry->data,
677 fw_entry->data + fw_entry->size, 1);
678 release_firmware(fw_entry);
679 if (ret) {
680 printk(KERN_ERR "%s: Secondary firmware download failed\n",
681 dev->name);
682 }
683
684 return ret;
685}
686
687static int orinoco_download(struct orinoco_private *priv)
688{
689 int err = 0;
690 /* Reload firmware */
691 switch (priv->firmware_type) {
692 case FIRMWARE_TYPE_AGERE:
693 /* case FIRMWARE_TYPE_INTERSIL: */
694 err = orinoco_dl_firmware(priv,
695 &orinoco_fw[priv->firmware_type], 0);
696 break;
697
698 case FIRMWARE_TYPE_SYMBOL:
699 err = symbol_dl_firmware(priv,
700 &orinoco_fw[priv->firmware_type]);
701 break;
702 case FIRMWARE_TYPE_INTERSIL:
703 break;
704 }
705 /* TODO: if we fail we probably need to reinitialise
706 * the driver */
707
708 return err;
709}
710
711/********************************************************************/
712/* Device methods */
713/********************************************************************/
714
715static int orinoco_open(struct net_device *dev)
716{
717 struct orinoco_private *priv = netdev_priv(dev);
718 unsigned long flags;
719 int err;
720
721 if (orinoco_lock(priv, &flags) != 0)
722 return -EBUSY;
723
724 err = __orinoco_up(dev);
725
726 if (! err)
727 priv->open = 1;
728
729 orinoco_unlock(priv, &flags);
730
731 return err;
732}
733
734static int orinoco_stop(struct net_device *dev)
735{
736 struct orinoco_private *priv = netdev_priv(dev);
737 int err = 0;
738
739 /* We mustn't use orinoco_lock() here, because we need to be
740 able to close the interface even if hw_unavailable is set
741 (e.g. as we're released after a PC Card removal) */
742 spin_lock_irq(&priv->lock);
743
744 priv->open = 0;
745
746 err = __orinoco_down(dev);
747
748 spin_unlock_irq(&priv->lock);
749
750 return err;
751}
752
753static struct net_device_stats *orinoco_get_stats(struct net_device *dev)
754{
755 struct orinoco_private *priv = netdev_priv(dev);
756
757 return &priv->stats;
758}
759
760static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
761{
762 struct orinoco_private *priv = netdev_priv(dev);
763 hermes_t *hw = &priv->hw;
764 struct iw_statistics *wstats = &priv->wstats;
765 int err;
766 unsigned long flags;
767
768 if (! netif_device_present(dev)) {
769 printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
770 dev->name);
771 return NULL; /* FIXME: Can we do better than this? */
772 }
773
774 /* If busy, return the old stats. Returning NULL may cause
775 * the interface to disappear from /proc/net/wireless */
776 if (orinoco_lock(priv, &flags) != 0)
777 return wstats;
778
779 /* We can't really wait for the tallies inquiry command to
780 * complete, so we just use the previous results and trigger
781 * a new tallies inquiry command for next time - Jean II */
782 /* FIXME: Really we should wait for the inquiry to come back -
783 * as it is the stats we give don't make a whole lot of sense.
784 * Unfortunately, it's not clear how to do that within the
785 * wireless extensions framework: I think we're in user
786 * context, but a lock seems to be held by the time we get in
787 * here so we're not safe to sleep here. */
788 hermes_inquire(hw, HERMES_INQ_TALLIES);
789
790 if (priv->iw_mode == IW_MODE_ADHOC) {
791 memset(&wstats->qual, 0, sizeof(wstats->qual));
792 /* If a spy address is defined, we report stats of the
793 * first spy address - Jean II */
794 if (SPY_NUMBER(priv)) {
795 wstats->qual.qual = priv->spy_data.spy_stat[0].qual;
796 wstats->qual.level = priv->spy_data.spy_stat[0].level;
797 wstats->qual.noise = priv->spy_data.spy_stat[0].noise;
798 wstats->qual.updated = priv->spy_data.spy_stat[0].updated;
799 }
800 } else {
801 struct {
802 __le16 qual, signal, noise, unused;
803 } __attribute__ ((packed)) cq;
804
805 err = HERMES_READ_RECORD(hw, USER_BAP,
806 HERMES_RID_COMMSQUALITY, &cq);
807
808 if (!err) {
809 wstats->qual.qual = (int)le16_to_cpu(cq.qual);
810 wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
811 wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
812 wstats->qual.updated = 7;
813 }
814 }
815
816 orinoco_unlock(priv, &flags);
817 return wstats;
818}
819
820static void orinoco_set_multicast_list(struct net_device *dev)
821{
822 struct orinoco_private *priv = netdev_priv(dev);
823 unsigned long flags;
824
825 if (orinoco_lock(priv, &flags) != 0) {
826 printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
827 "called when hw_unavailable\n", dev->name);
828 return;
829 }
830
831 __orinoco_set_multicast_list(dev);
832 orinoco_unlock(priv, &flags);
833}
834
835static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
836{
837 struct orinoco_private *priv = netdev_priv(dev);
838
839 if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
840 return -EINVAL;
841
842 /* MTU + encapsulation + header length */
843 if ( (new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) >
844 (priv->nicbuf_size - ETH_HLEN) )
845 return -EINVAL;
846
847 dev->mtu = new_mtu;
848
849 return 0;
850}
851
852/********************************************************************/
853/* Tx path */
854/********************************************************************/
855
856static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
857{
858 struct orinoco_private *priv = netdev_priv(dev);
859 struct net_device_stats *stats = &priv->stats;
860 hermes_t *hw = &priv->hw;
861 int err = 0;
862 u16 txfid = priv->txfid;
863 struct ethhdr *eh;
864 int tx_control;
865 unsigned long flags;
866
867 if (! netif_running(dev)) {
868 printk(KERN_ERR "%s: Tx on stopped device!\n",
869 dev->name);
870 return NETDEV_TX_BUSY;
871 }
872
873 if (netif_queue_stopped(dev)) {
874 printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
875 dev->name);
876 return NETDEV_TX_BUSY;
877 }
878
879 if (orinoco_lock(priv, &flags) != 0) {
880 printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
881 dev->name);
882 return NETDEV_TX_BUSY;
883 }
884
885 if (! netif_carrier_ok(dev) || (priv->iw_mode == IW_MODE_MONITOR)) {
886 /* Oops, the firmware hasn't established a connection,
887 silently drop the packet (this seems to be the
888 safest approach). */
889 goto drop;
890 }
891
892 /* Check packet length */
893 if (skb->len < ETH_HLEN)
894 goto drop;
895
896 tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX;
897
898 if (priv->encode_alg == IW_ENCODE_ALG_TKIP)
899 tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) |
900 HERMES_TXCTRL_MIC;
901
902 if (priv->has_alt_txcntl) {
903 /* WPA enabled firmwares have tx_cntl at the end of
904 * the 802.11 header. So write zeroed descriptor and
905 * 802.11 header at the same time
906 */
907 char desc[HERMES_802_3_OFFSET];
908 __le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET];
909
910 memset(&desc, 0, sizeof(desc));
911
912 *txcntl = cpu_to_le16(tx_control);
913 err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
914 txfid, 0);
915 if (err) {
916 if (net_ratelimit())
917 printk(KERN_ERR "%s: Error %d writing Tx "
918 "descriptor to BAP\n", dev->name, err);
919 goto busy;
920 }
921 } else {
922 struct hermes_tx_descriptor desc;
923
924 memset(&desc, 0, sizeof(desc));
925
926 desc.tx_control = cpu_to_le16(tx_control);
927 err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc),
928 txfid, 0);
929 if (err) {
930 if (net_ratelimit())
931 printk(KERN_ERR "%s: Error %d writing Tx "
932 "descriptor to BAP\n", dev->name, err);
933 goto busy;
934 }
935
936 /* Clear the 802.11 header and data length fields - some
937 * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
938 * if this isn't done. */
939 hermes_clear_words(hw, HERMES_DATA0,
940 HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
941 }
942
943 eh = (struct ethhdr *)skb->data;
944
945 /* Encapsulate Ethernet-II frames */
946 if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */
947 struct header_struct {
948 struct ethhdr eth; /* 802.3 header */
949 u8 encap[6]; /* 802.2 header */
950 } __attribute__ ((packed)) hdr;
951
952 /* Strip destination and source from the data */
953 skb_pull(skb, 2 * ETH_ALEN);
954
955 /* And move them to a separate header */
956 memcpy(&hdr.eth, eh, 2 * ETH_ALEN);
957 hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len);
958 memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr));
959
960 /* Insert the SNAP header */
961 if (skb_headroom(skb) < sizeof(hdr)) {
962 printk(KERN_ERR
963 "%s: Not enough headroom for 802.2 headers %d\n",
964 dev->name, skb_headroom(skb));
965 goto drop;
966 }
967 eh = (struct ethhdr *) skb_push(skb, sizeof(hdr));
968 memcpy(eh, &hdr, sizeof(hdr));
969 }
970
971 err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len,
972 txfid, HERMES_802_3_OFFSET);
973 if (err) {
974 printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
975 dev->name, err);
976 goto busy;
977 }
978
979 /* Calculate Michael MIC */
980 if (priv->encode_alg == IW_ENCODE_ALG_TKIP) {
981 u8 mic_buf[MICHAEL_MIC_LEN + 1];
982 u8 *mic;
983 size_t offset;
984 size_t len;
985
986 if (skb->len % 2) {
987 /* MIC start is on an odd boundary */
988 mic_buf[0] = skb->data[skb->len - 1];
989 mic = &mic_buf[1];
990 offset = skb->len - 1;
991 len = MICHAEL_MIC_LEN + 1;
992 } else {
993 mic = &mic_buf[0];
994 offset = skb->len;
995 len = MICHAEL_MIC_LEN;
996 }
997
998 michael_mic(priv->tx_tfm_mic,
999 priv->tkip_key[priv->tx_key].tx_mic,
1000 eh->h_dest, eh->h_source, 0 /* priority */,
1001 skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic);
1002
1003 /* Write the MIC */
1004 err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len,
1005 txfid, HERMES_802_3_OFFSET + offset);
1006 if (err) {
1007 printk(KERN_ERR "%s: Error %d writing MIC to BAP\n",
1008 dev->name, err);
1009 goto busy;
1010 }
1011 }
1012
1013 /* Finally, we actually initiate the send */
1014 netif_stop_queue(dev);
1015
1016 err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
1017 txfid, NULL);
1018 if (err) {
1019 netif_start_queue(dev);
1020 if (net_ratelimit())
1021 printk(KERN_ERR "%s: Error %d transmitting packet\n",
1022 dev->name, err);
1023 goto busy;
1024 }
1025
1026 dev->trans_start = jiffies;
1027 stats->tx_bytes += HERMES_802_3_OFFSET + skb->len;
1028 goto ok;
1029
1030 drop:
1031 stats->tx_errors++;
1032 stats->tx_dropped++;
1033
1034 ok:
1035 orinoco_unlock(priv, &flags);
1036 dev_kfree_skb(skb);
1037 return NETDEV_TX_OK;
1038
1039 busy:
1040 if (err == -EIO)
1041 schedule_work(&priv->reset_work);
1042 orinoco_unlock(priv, &flags);
1043 return NETDEV_TX_BUSY;
1044}
1045
1046static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
1047{
1048 struct orinoco_private *priv = netdev_priv(dev);
1049 u16 fid = hermes_read_regn(hw, ALLOCFID);
1050
1051 if (fid != priv->txfid) {
1052 if (fid != DUMMY_FID)
1053 printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
1054 dev->name, fid);
1055 return;
1056 }
1057
1058 hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
1059}
1060
1061static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
1062{
1063 struct orinoco_private *priv = netdev_priv(dev);
1064 struct net_device_stats *stats = &priv->stats;
1065
1066 stats->tx_packets++;
1067
1068 netif_wake_queue(dev);
1069
1070 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
1071}
1072
1073static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
1074{
1075 struct orinoco_private *priv = netdev_priv(dev);
1076 struct net_device_stats *stats = &priv->stats;
1077 u16 fid = hermes_read_regn(hw, TXCOMPLFID);
1078 u16 status;
1079 struct hermes_txexc_data hdr;
1080 int err = 0;
1081
1082 if (fid == DUMMY_FID)
1083 return; /* Nothing's really happened */
1084
1085 /* Read part of the frame header - we need status and addr1 */
1086 err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
1087 sizeof(struct hermes_txexc_data),
1088 fid, 0);
1089
1090 hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
1091 stats->tx_errors++;
1092
1093 if (err) {
1094 printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
1095 "(FID=%04X error %d)\n",
1096 dev->name, fid, err);
1097 return;
1098 }
1099
1100 DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name,
1101 err, fid);
1102
1103 /* We produce a TXDROP event only for retry or lifetime
1104 * exceeded, because that's the only status that really mean
1105 * that this particular node went away.
1106 * Other errors means that *we* screwed up. - Jean II */
1107 status = le16_to_cpu(hdr.desc.status);
1108 if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
1109 union iwreq_data wrqu;
1110
1111 /* Copy 802.11 dest address.
1112 * We use the 802.11 header because the frame may
1113 * not be 802.3 or may be mangled...
1114 * In Ad-Hoc mode, it will be the node address.
1115 * In managed mode, it will be most likely the AP addr
1116 * User space will figure out how to convert it to
1117 * whatever it needs (IP address or else).
1118 * - Jean II */
1119 memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
1120 wrqu.addr.sa_family = ARPHRD_ETHER;
1121
1122 /* Send event to user space */
1123 wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
1124 }
1125
1126 netif_wake_queue(dev);
1127}
1128
1129static void orinoco_tx_timeout(struct net_device *dev)
1130{
1131 struct orinoco_private *priv = netdev_priv(dev);
1132 struct net_device_stats *stats = &priv->stats;
1133 struct hermes *hw = &priv->hw;
1134
1135 printk(KERN_WARNING "%s: Tx timeout! "
1136 "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
1137 dev->name, hermes_read_regn(hw, ALLOCFID),
1138 hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
1139
1140 stats->tx_errors++;
1141
1142 schedule_work(&priv->reset_work);
1143}
1144
1145/********************************************************************/
1146/* Rx path (data frames) */
1147/********************************************************************/
1148
1149/* Does the frame have a SNAP header indicating it should be
1150 * de-encapsulated to Ethernet-II? */
1151static inline int is_ethersnap(void *_hdr)
1152{
1153 u8 *hdr = _hdr;
1154
1155 /* We de-encapsulate all packets which, a) have SNAP headers
1156 * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
1157 * and where b) the OUI of the SNAP header is 00:00:00 or
1158 * 00:00:f8 - we need both because different APs appear to use
1159 * different OUIs for some reason */
1160 return (memcmp(hdr, &encaps_hdr, 5) == 0)
1161 && ( (hdr[5] == 0x00) || (hdr[5] == 0xf8) );
1162}
1163
1164static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
1165 int level, int noise)
1166{
1167 struct iw_quality wstats;
1168 wstats.level = level - 0x95;
1169 wstats.noise = noise - 0x95;
1170 wstats.qual = (level > noise) ? (level - noise) : 0;
1171 wstats.updated = 7;
1172 /* Update spy records */
1173 wireless_spy_update(dev, mac, &wstats);
1174}
1175
1176static void orinoco_stat_gather(struct net_device *dev,
1177 struct sk_buff *skb,
1178 struct hermes_rx_descriptor *desc)
1179{
1180 struct orinoco_private *priv = netdev_priv(dev);
1181
1182 /* Using spy support with lots of Rx packets, like in an
1183 * infrastructure (AP), will really slow down everything, because
1184 * the MAC address must be compared to each entry of the spy list.
1185 * If the user really asks for it (set some address in the
1186 * spy list), we do it, but he will pay the price.
1187 * Note that to get here, you need both WIRELESS_SPY
1188 * compiled in AND some addresses in the list !!!
1189 */
1190 /* Note : gcc will optimise the whole section away if
1191 * WIRELESS_SPY is not defined... - Jean II */
1192 if (SPY_NUMBER(priv)) {
1193 orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN,
1194 desc->signal, desc->silence);
1195 }
1196}
1197
1198/*
1199 * orinoco_rx_monitor - handle received monitor frames.
1200 *
1201 * Arguments:
1202 * dev network device
1203 * rxfid received FID
1204 * desc rx descriptor of the frame
1205 *
1206 * Call context: interrupt
1207 */
1208static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid,
1209 struct hermes_rx_descriptor *desc)
1210{
1211 u32 hdrlen = 30; /* return full header by default */
1212 u32 datalen = 0;
1213 u16 fc;
1214 int err;
1215 int len;
1216 struct sk_buff *skb;
1217 struct orinoco_private *priv = netdev_priv(dev);
1218 struct net_device_stats *stats = &priv->stats;
1219 hermes_t *hw = &priv->hw;
1220
1221 len = le16_to_cpu(desc->data_len);
1222
1223 /* Determine the size of the header and the data */
1224 fc = le16_to_cpu(desc->frame_ctl);
1225 switch (fc & IEEE80211_FCTL_FTYPE) {
1226 case IEEE80211_FTYPE_DATA:
1227 if ((fc & IEEE80211_FCTL_TODS)
1228 && (fc & IEEE80211_FCTL_FROMDS))
1229 hdrlen = 30;
1230 else
1231 hdrlen = 24;
1232 datalen = len;
1233 break;
1234 case IEEE80211_FTYPE_MGMT:
1235 hdrlen = 24;
1236 datalen = len;
1237 break;
1238 case IEEE80211_FTYPE_CTL:
1239 switch (fc & IEEE80211_FCTL_STYPE) {
1240 case IEEE80211_STYPE_PSPOLL:
1241 case IEEE80211_STYPE_RTS:
1242 case IEEE80211_STYPE_CFEND:
1243 case IEEE80211_STYPE_CFENDACK:
1244 hdrlen = 16;
1245 break;
1246 case IEEE80211_STYPE_CTS:
1247 case IEEE80211_STYPE_ACK:
1248 hdrlen = 10;
1249 break;
1250 }
1251 break;
1252 default:
1253 /* Unknown frame type */
1254 break;
1255 }
1256
1257 /* sanity check the length */
1258 if (datalen > IEEE80211_MAX_DATA_LEN + 12) {
1259 printk(KERN_DEBUG "%s: oversized monitor frame, "
1260 "data length = %d\n", dev->name, datalen);
1261 stats->rx_length_errors++;
1262 goto update_stats;
1263 }
1264
1265 skb = dev_alloc_skb(hdrlen + datalen);
1266 if (!skb) {
1267 printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n",
1268 dev->name);
1269 goto update_stats;
1270 }
1271
1272 /* Copy the 802.11 header to the skb */
1273 memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen);
1274 skb_reset_mac_header(skb);
1275
1276 /* If any, copy the data from the card to the skb */
1277 if (datalen > 0) {
1278 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen),
1279 ALIGN(datalen, 2), rxfid,
1280 HERMES_802_2_OFFSET);
1281 if (err) {
1282 printk(KERN_ERR "%s: error %d reading monitor frame\n",
1283 dev->name, err);
1284 goto drop;
1285 }
1286 }
1287
1288 skb->dev = dev;
1289 skb->ip_summed = CHECKSUM_NONE;
1290 skb->pkt_type = PACKET_OTHERHOST;
1291 skb->protocol = __constant_htons(ETH_P_802_2);
1292
1293 stats->rx_packets++;
1294 stats->rx_bytes += skb->len;
1295
1296 netif_rx(skb);
1297 return;
1298
1299 drop:
1300 dev_kfree_skb_irq(skb);
1301 update_stats:
1302 stats->rx_errors++;
1303 stats->rx_dropped++;
1304}
1305
1306/* Get tsc from the firmware */
1307static int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key,
1308 u8 *tsc)
1309{
1310 hermes_t *hw = &priv->hw;
1311 int err = 0;
1312 u8 tsc_arr[4][IW_ENCODE_SEQ_MAX_SIZE];
1313
1314 if ((key < 0) || (key > 4))
1315 return -EINVAL;
1316
1317 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV,
1318 sizeof(tsc_arr), NULL, &tsc_arr);
1319 if (!err)
1320 memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0]));
1321
1322 return err;
1323}
1324
1325static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1326{
1327 struct orinoco_private *priv = netdev_priv(dev);
1328 struct net_device_stats *stats = &priv->stats;
1329 struct iw_statistics *wstats = &priv->wstats;
1330 struct sk_buff *skb = NULL;
1331 u16 rxfid, status;
1332 int length;
1333 struct hermes_rx_descriptor *desc;
1334 struct orinoco_rx_data *rx_data;
1335 int err;
1336
1337 desc = kmalloc(sizeof(*desc), GFP_ATOMIC);
1338 if (!desc) {
1339 printk(KERN_WARNING
1340 "%s: Can't allocate space for RX descriptor\n",
1341 dev->name);
1342 goto update_stats;
1343 }
1344
1345 rxfid = hermes_read_regn(hw, RXFID);
1346
1347 err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc),
1348 rxfid, 0);
1349 if (err) {
1350 printk(KERN_ERR "%s: error %d reading Rx descriptor. "
1351 "Frame dropped.\n", dev->name, err);
1352 goto update_stats;
1353 }
1354
1355 status = le16_to_cpu(desc->status);
1356
1357 if (status & HERMES_RXSTAT_BADCRC) {
1358 DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n",
1359 dev->name);
1360 stats->rx_crc_errors++;
1361 goto update_stats;
1362 }
1363
1364 /* Handle frames in monitor mode */
1365 if (priv->iw_mode == IW_MODE_MONITOR) {
1366 orinoco_rx_monitor(dev, rxfid, desc);
1367 goto out;
1368 }
1369
1370 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
1371 DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
1372 dev->name);
1373 wstats->discard.code++;
1374 goto update_stats;
1375 }
1376
1377 length = le16_to_cpu(desc->data_len);
1378
1379 /* Sanity checks */
1380 if (length < 3) { /* No for even an 802.2 LLC header */
1381 /* At least on Symbol firmware with PCF we get quite a
1382 lot of these legitimately - Poll frames with no
1383 data. */
1384 goto out;
1385 }
1386 if (length > IEEE80211_MAX_DATA_LEN) {
1387 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
1388 dev->name, length);
1389 stats->rx_length_errors++;
1390 goto update_stats;
1391 }
1392
1393 /* Payload size does not include Michael MIC. Increase payload
1394 * size to read it together with the data. */
1395 if (status & HERMES_RXSTAT_MIC)
1396 length += MICHAEL_MIC_LEN;
1397
1398 /* We need space for the packet data itself, plus an ethernet
1399 header, plus 2 bytes so we can align the IP header on a
1400 32bit boundary, plus 1 byte so we can read in odd length
1401 packets from the card, which has an IO granularity of 16
1402 bits */
1403 skb = dev_alloc_skb(length+ETH_HLEN+2+1);
1404 if (!skb) {
1405 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
1406 dev->name);
1407 goto update_stats;
1408 }
1409
1410 /* We'll prepend the header, so reserve space for it. The worst
1411 case is no decapsulation, when 802.3 header is prepended and
1412 nothing is removed. 2 is for aligning the IP header. */
1413 skb_reserve(skb, ETH_HLEN + 2);
1414
1415 err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length),
1416 ALIGN(length, 2), rxfid,
1417 HERMES_802_2_OFFSET);
1418 if (err) {
1419 printk(KERN_ERR "%s: error %d reading frame. "
1420 "Frame dropped.\n", dev->name, err);
1421 goto drop;
1422 }
1423
1424 /* Add desc and skb to rx queue */
1425 rx_data = kzalloc(sizeof(*rx_data), GFP_ATOMIC);
1426 if (!rx_data) {
1427 printk(KERN_WARNING "%s: Can't allocate RX packet\n",
1428 dev->name);
1429 goto drop;
1430 }
1431 rx_data->desc = desc;
1432 rx_data->skb = skb;
1433 list_add_tail(&rx_data->list, &priv->rx_list);
1434 tasklet_schedule(&priv->rx_tasklet);
1435
1436 return;
1437
1438drop:
1439 dev_kfree_skb_irq(skb);
1440update_stats:
1441 stats->rx_errors++;
1442 stats->rx_dropped++;
1443out:
1444 kfree(desc);
1445}
1446
1447static void orinoco_rx(struct net_device *dev,
1448 struct hermes_rx_descriptor *desc,
1449 struct sk_buff *skb)
1450{
1451 struct orinoco_private *priv = netdev_priv(dev);
1452 struct net_device_stats *stats = &priv->stats;
1453 u16 status, fc;
1454 int length;
1455 struct ethhdr *hdr;
1456
1457 status = le16_to_cpu(desc->status);
1458 length = le16_to_cpu(desc->data_len);
1459 fc = le16_to_cpu(desc->frame_ctl);
1460
1461 /* Calculate and check MIC */
1462 if (status & HERMES_RXSTAT_MIC) {
1463 int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >>
1464 HERMES_MIC_KEY_ID_SHIFT);
1465 u8 mic[MICHAEL_MIC_LEN];
1466 u8 *rxmic;
1467 u8 *src = (fc & IEEE80211_FCTL_FROMDS) ?
1468 desc->addr3 : desc->addr2;
1469
1470 /* Extract Michael MIC from payload */
1471 rxmic = skb->data + skb->len - MICHAEL_MIC_LEN;
1472
1473 skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
1474 length -= MICHAEL_MIC_LEN;
1475
1476 michael_mic(priv->rx_tfm_mic,
1477 priv->tkip_key[key_id].rx_mic,
1478 desc->addr1,
1479 src,
1480 0, /* priority or QoS? */
1481 skb->data,
1482 skb->len,
1483 &mic[0]);
1484
1485 if (memcmp(mic, rxmic,
1486 MICHAEL_MIC_LEN)) {
1487 union iwreq_data wrqu;
1488 struct iw_michaelmicfailure wxmic;
1489
1490 printk(KERN_WARNING "%s: "
1491 "Invalid Michael MIC in data frame from %pM, "
1492 "using key %i\n",
1493 dev->name, src, key_id);
1494
1495 /* TODO: update stats */
1496
1497 /* Notify userspace */
1498 memset(&wxmic, 0, sizeof(wxmic));
1499 wxmic.flags = key_id & IW_MICFAILURE_KEY_ID;
1500 wxmic.flags |= (desc->addr1[0] & 1) ?
1501 IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE;
1502 wxmic.src_addr.sa_family = ARPHRD_ETHER;
1503 memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN);
1504
1505 (void) orinoco_hw_get_tkip_iv(priv, key_id,
1506 &wxmic.tsc[0]);
1507
1508 memset(&wrqu, 0, sizeof(wrqu));
1509 wrqu.data.length = sizeof(wxmic);
1510 wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu,
1511 (char *) &wxmic);
1512
1513 goto drop;
1514 }
1515 }
1516
1517 /* Handle decapsulation
1518 * In most cases, the firmware tell us about SNAP frames.
1519 * For some reason, the SNAP frames sent by LinkSys APs
1520 * are not properly recognised by most firmwares.
1521 * So, check ourselves */
1522 if (length >= ENCAPS_OVERHEAD &&
1523 (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
1524 ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
1525 is_ethersnap(skb->data))) {
1526 /* These indicate a SNAP within 802.2 LLC within
1527 802.11 frame which we'll need to de-encapsulate to
1528 the original EthernetII frame. */
1529 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN - ENCAPS_OVERHEAD);
1530 } else {
1531 /* 802.3 frame - prepend 802.3 header as is */
1532 hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN);
1533 hdr->h_proto = htons(length);
1534 }
1535 memcpy(hdr->h_dest, desc->addr1, ETH_ALEN);
1536 if (fc & IEEE80211_FCTL_FROMDS)
1537 memcpy(hdr->h_source, desc->addr3, ETH_ALEN);
1538 else
1539 memcpy(hdr->h_source, desc->addr2, ETH_ALEN);
1540
1541 skb->protocol = eth_type_trans(skb, dev);
1542 skb->ip_summed = CHECKSUM_NONE;
1543 if (fc & IEEE80211_FCTL_TODS)
1544 skb->pkt_type = PACKET_OTHERHOST;
1545
1546 /* Process the wireless stats if needed */
1547 orinoco_stat_gather(dev, skb, desc);
1548
1549 /* Pass the packet to the networking stack */
1550 netif_rx(skb);
1551 stats->rx_packets++;
1552 stats->rx_bytes += length;
1553
1554 return;
1555
1556 drop:
1557 dev_kfree_skb(skb);
1558 stats->rx_errors++;
1559 stats->rx_dropped++;
1560}
1561
1562static void orinoco_rx_isr_tasklet(unsigned long data)
1563{
1564 struct net_device *dev = (struct net_device *) data;
1565 struct orinoco_private *priv = netdev_priv(dev);
1566 struct orinoco_rx_data *rx_data, *temp;
1567 struct hermes_rx_descriptor *desc;
1568 struct sk_buff *skb;
1569
1570 /* extract desc and skb from queue */
1571 list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) {
1572 desc = rx_data->desc;
1573 skb = rx_data->skb;
1574 list_del(&rx_data->list);
1575 kfree(rx_data);
1576
1577 orinoco_rx(dev, desc, skb);
1578
1579 kfree(desc);
1580 }
1581}
1582
1583/********************************************************************/
1584/* Rx path (info frames) */
1585/********************************************************************/
1586
1587static void print_linkstatus(struct net_device *dev, u16 status)
1588{
1589 char * s;
1590
1591 if (suppress_linkstatus)
1592 return;
1593
1594 switch (status) {
1595 case HERMES_LINKSTATUS_NOT_CONNECTED:
1596 s = "Not Connected";
1597 break;
1598 case HERMES_LINKSTATUS_CONNECTED:
1599 s = "Connected";
1600 break;
1601 case HERMES_LINKSTATUS_DISCONNECTED:
1602 s = "Disconnected";
1603 break;
1604 case HERMES_LINKSTATUS_AP_CHANGE:
1605 s = "AP Changed";
1606 break;
1607 case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
1608 s = "AP Out of Range";
1609 break;
1610 case HERMES_LINKSTATUS_AP_IN_RANGE:
1611 s = "AP In Range";
1612 break;
1613 case HERMES_LINKSTATUS_ASSOC_FAILED:
1614 s = "Association Failed";
1615 break;
1616 default:
1617 s = "UNKNOWN";
1618 }
1619
1620 printk(KERN_INFO "%s: New link status: %s (%04x)\n",
1621 dev->name, s, status);
1622}
1623
1624/* Search scan results for requested BSSID, join it if found */
1625static void orinoco_join_ap(struct work_struct *work)
1626{
1627 struct orinoco_private *priv =
1628 container_of(work, struct orinoco_private, join_work);
1629 struct net_device *dev = priv->ndev;
1630 struct hermes *hw = &priv->hw;
1631 int err;
1632 unsigned long flags;
1633 struct join_req {
1634 u8 bssid[ETH_ALEN];
1635 __le16 channel;
1636 } __attribute__ ((packed)) req;
1637 const int atom_len = offsetof(struct prism2_scan_apinfo, atim);
1638 struct prism2_scan_apinfo *atom = NULL;
1639 int offset = 4;
1640 int found = 0;
1641 u8 *buf;
1642 u16 len;
1643
1644 /* Allocate buffer for scan results */
1645 buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL);
1646 if (! buf)
1647 return;
1648
1649 if (orinoco_lock(priv, &flags) != 0)
1650 goto fail_lock;
1651
1652 /* Sanity checks in case user changed something in the meantime */
1653 if (! priv->bssid_fixed)
1654 goto out;
1655
1656 if (strlen(priv->desired_essid) == 0)
1657 goto out;
1658
1659 /* Read scan results from the firmware */
1660 err = hermes_read_ltv(hw, USER_BAP,
1661 HERMES_RID_SCANRESULTSTABLE,
1662 MAX_SCAN_LEN, &len, buf);
1663 if (err) {
1664 printk(KERN_ERR "%s: Cannot read scan results\n",
1665 dev->name);
1666 goto out;
1667 }
1668
1669 len = HERMES_RECLEN_TO_BYTES(len);
1670
1671 /* Go through the scan results looking for the channel of the AP
1672 * we were requested to join */
1673 for (; offset + atom_len <= len; offset += atom_len) {
1674 atom = (struct prism2_scan_apinfo *) (buf + offset);
1675 if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) {
1676 found = 1;
1677 break;
1678 }
1679 }
1680
1681 if (! found) {
1682 DEBUG(1, "%s: Requested AP not found in scan results\n",
1683 dev->name);
1684 goto out;
1685 }
1686
1687 memcpy(req.bssid, priv->desired_bssid, ETH_ALEN);
1688 req.channel = atom->channel; /* both are little-endian */
1689 err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST,
1690 &req);
1691 if (err)
1692 printk(KERN_ERR "%s: Error issuing join request\n", dev->name);
1693
1694 out:
1695 orinoco_unlock(priv, &flags);
1696
1697 fail_lock:
1698 kfree(buf);
1699}
1700
1701/* Send new BSSID to userspace */
1702static void orinoco_send_bssid_wevent(struct orinoco_private *priv)
1703{
1704 struct net_device *dev = priv->ndev;
1705 struct hermes *hw = &priv->hw;
1706 union iwreq_data wrqu;
1707 int err;
1708
1709 err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENTBSSID,
1710 ETH_ALEN, NULL, wrqu.ap_addr.sa_data);
1711 if (err != 0)
1712 return;
1713
1714 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1715
1716 /* Send event to user space */
1717 wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
1718}
1719
1720static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv)
1721{
1722 struct net_device *dev = priv->ndev;
1723 struct hermes *hw = &priv->hw;
1724 union iwreq_data wrqu;
1725 int err;
1726 u8 buf[88];
1727 u8 *ie;
1728
1729 if (!priv->has_wpa)
1730 return;
1731
1732 err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO,
1733 sizeof(buf), NULL, &buf);
1734 if (err != 0)
1735 return;
1736
1737 ie = orinoco_get_wpa_ie(buf, sizeof(buf));
1738 if (ie) {
1739 int rem = sizeof(buf) - (ie - &buf[0]);
1740 wrqu.data.length = ie[1] + 2;
1741 if (wrqu.data.length > rem)
1742 wrqu.data.length = rem;
1743
1744 if (wrqu.data.length)
1745 /* Send event to user space */
1746 wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, ie);
1747 }
1748}
1749
1750static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv)
1751{
1752 struct net_device *dev = priv->ndev;
1753 struct hermes *hw = &priv->hw;
1754 union iwreq_data wrqu;
1755 int err;
1756 u8 buf[88]; /* TODO: verify max size or IW_GENERIC_IE_MAX */
1757 u8 *ie;
1758
1759 if (!priv->has_wpa)
1760 return;
1761
1762 err = hermes_read_ltv(hw, IRQ_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO,
1763 sizeof(buf), NULL, &buf);
1764 if (err != 0)
1765 return;
1766
1767 ie = orinoco_get_wpa_ie(buf, sizeof(buf));
1768 if (ie) {
1769 int rem = sizeof(buf) - (ie - &buf[0]);
1770 wrqu.data.length = ie[1] + 2;
1771 if (wrqu.data.length > rem)
1772 wrqu.data.length = rem;
1773
1774 if (wrqu.data.length)
1775 /* Send event to user space */
1776 wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, ie);
1777 }
1778}
1779
1780static void orinoco_send_wevents(struct work_struct *work)
1781{
1782 struct orinoco_private *priv =
1783 container_of(work, struct orinoco_private, wevent_work);
1784 unsigned long flags;
1785
1786 if (orinoco_lock(priv, &flags) != 0)
1787 return;
1788
1789 orinoco_send_assocreqie_wevent(priv);
1790 orinoco_send_assocrespie_wevent(priv);
1791 orinoco_send_bssid_wevent(priv);
1792
1793 orinoco_unlock(priv, &flags);
1794}
1795
1796static inline void orinoco_clear_scan_results(struct orinoco_private *priv,
1797 unsigned long scan_age)
1798{
1799 if (priv->has_ext_scan) {
1800 struct xbss_element *bss;
1801 struct xbss_element *tmp_bss;
1802
1803 /* Blow away current list of scan results */
1804 list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
1805 if (!scan_age ||
1806 time_after(jiffies, bss->last_scanned + scan_age)) {
1807 list_move_tail(&bss->list,
1808 &priv->bss_free_list);
1809 /* Don't blow away ->list, just BSS data */
1810 memset(&bss->bss, 0, sizeof(bss->bss));
1811 bss->last_scanned = 0;
1812 }
1813 }
1814 } else {
1815 struct bss_element *bss;
1816 struct bss_element *tmp_bss;
1817
1818 /* Blow away current list of scan results */
1819 list_for_each_entry_safe(bss, tmp_bss, &priv->bss_list, list) {
1820 if (!scan_age ||
1821 time_after(jiffies, bss->last_scanned + scan_age)) {
1822 list_move_tail(&bss->list,
1823 &priv->bss_free_list);
1824 /* Don't blow away ->list, just BSS data */
1825 memset(&bss->bss, 0, sizeof(bss->bss));
1826 bss->last_scanned = 0;
1827 }
1828 }
1829 }
1830}
1831
1832static void orinoco_add_ext_scan_result(struct orinoco_private *priv,
1833 struct agere_ext_scan_info *atom)
1834{
1835 struct xbss_element *bss = NULL;
1836 int found = 0;
1837
1838 /* Try to update an existing bss first */
1839 list_for_each_entry(bss, &priv->bss_list, list) {
1840 if (compare_ether_addr(bss->bss.bssid, atom->bssid))
1841 continue;
1842 /* ESSID lengths */
1843 if (bss->bss.data[1] != atom->data[1])
1844 continue;
1845 if (memcmp(&bss->bss.data[2], &atom->data[2],
1846 atom->data[1]))
1847 continue;
1848 found = 1;
1849 break;
1850 }
1851
1852 /* Grab a bss off the free list */
1853 if (!found && !list_empty(&priv->bss_free_list)) {
1854 bss = list_entry(priv->bss_free_list.next,
1855 struct xbss_element, list);
1856 list_del(priv->bss_free_list.next);
1857
1858 list_add_tail(&bss->list, &priv->bss_list);
1859 }
1860
1861 if (bss) {
1862 /* Always update the BSS to get latest beacon info */
1863 memcpy(&bss->bss, atom, sizeof(bss->bss));
1864 bss->last_scanned = jiffies;
1865 }
1866}
1867
1868static int orinoco_process_scan_results(struct net_device *dev,
1869 unsigned char *buf,
1870 int len)
1871{
1872 struct orinoco_private *priv = netdev_priv(dev);
1873 int offset; /* In the scan data */
1874 union hermes_scan_info *atom;
1875 int atom_len;
1876
1877 switch (priv->firmware_type) {
1878 case FIRMWARE_TYPE_AGERE:
1879 atom_len = sizeof(struct agere_scan_apinfo);
1880 offset = 0;
1881 break;
1882 case FIRMWARE_TYPE_SYMBOL:
1883 /* Lack of documentation necessitates this hack.
1884 * Different firmwares have 68 or 76 byte long atoms.
1885 * We try modulo first. If the length divides by both,
1886 * we check what would be the channel in the second
1887 * frame for a 68-byte atom. 76-byte atoms have 0 there.
1888 * Valid channel cannot be 0. */
1889 if (len % 76)
1890 atom_len = 68;
1891 else if (len % 68)
1892 atom_len = 76;
1893 else if (len >= 1292 && buf[68] == 0)
1894 atom_len = 76;
1895 else
1896 atom_len = 68;
1897 offset = 0;
1898 break;
1899 case FIRMWARE_TYPE_INTERSIL:
1900 offset = 4;
1901 if (priv->has_hostscan) {
1902 atom_len = le16_to_cpup((__le16 *)buf);
1903 /* Sanity check for atom_len */
1904 if (atom_len < sizeof(struct prism2_scan_apinfo)) {
1905 printk(KERN_ERR "%s: Invalid atom_len in scan "
1906 "data: %d\n", dev->name, atom_len);
1907 return -EIO;
1908 }
1909 } else
1910 atom_len = offsetof(struct prism2_scan_apinfo, atim);
1911 break;
1912 default:
1913 return -EOPNOTSUPP;
1914 }
1915
1916 /* Check that we got an whole number of atoms */
1917 if ((len - offset) % atom_len) {
1918 printk(KERN_ERR "%s: Unexpected scan data length %d, "
1919 "atom_len %d, offset %d\n", dev->name, len,
1920 atom_len, offset);
1921 return -EIO;
1922 }
1923
1924 orinoco_clear_scan_results(priv, msecs_to_jiffies(15000));
1925
1926 /* Read the entries one by one */
1927 for (; offset + atom_len <= len; offset += atom_len) {
1928 int found = 0;
1929 struct bss_element *bss = NULL;
1930
1931 /* Get next atom */
1932 atom = (union hermes_scan_info *) (buf + offset);
1933
1934 /* Try to update an existing bss first */
1935 list_for_each_entry(bss, &priv->bss_list, list) {
1936 if (compare_ether_addr(bss->bss.a.bssid, atom->a.bssid))
1937 continue;
1938 if (le16_to_cpu(bss->bss.a.essid_len) !=
1939 le16_to_cpu(atom->a.essid_len))
1940 continue;
1941 if (memcmp(bss->bss.a.essid, atom->a.essid,
1942 le16_to_cpu(atom->a.essid_len)))
1943 continue;
1944 found = 1;
1945 break;
1946 }
1947
1948 /* Grab a bss off the free list */
1949 if (!found && !list_empty(&priv->bss_free_list)) {
1950 bss = list_entry(priv->bss_free_list.next,
1951 struct bss_element, list);
1952 list_del(priv->bss_free_list.next);
1953
1954 list_add_tail(&bss->list, &priv->bss_list);
1955 }
1956
1957 if (bss) {
1958 /* Always update the BSS to get latest beacon info */
1959 memcpy(&bss->bss, atom, sizeof(bss->bss));
1960 bss->last_scanned = jiffies;
1961 }
1962 }
1963
1964 return 0;
1965}
1966
1967static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1968{
1969 struct orinoco_private *priv = netdev_priv(dev);
1970 u16 infofid;
1971 struct {
1972 __le16 len;
1973 __le16 type;
1974 } __attribute__ ((packed)) info;
1975 int len, type;
1976 int err;
1977
1978 /* This is an answer to an INQUIRE command that we did earlier,
1979 * or an information "event" generated by the card
1980 * The controller return to us a pseudo frame containing
1981 * the information in question - Jean II */
1982 infofid = hermes_read_regn(hw, INFOFID);
1983
1984 /* Read the info frame header - don't try too hard */
1985 err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
1986 infofid, 0);
1987 if (err) {
1988 printk(KERN_ERR "%s: error %d reading info frame. "
1989 "Frame dropped.\n", dev->name, err);
1990 return;
1991 }
1992
1993 len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
1994 type = le16_to_cpu(info.type);
1995
1996 switch (type) {
1997 case HERMES_INQ_TALLIES: {
1998 struct hermes_tallies_frame tallies;
1999 struct iw_statistics *wstats = &priv->wstats;
2000
2001 if (len > sizeof(tallies)) {
2002 printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
2003 dev->name, len);
2004 len = sizeof(tallies);
2005 }
2006
2007 err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
2008 infofid, sizeof(info));
2009 if (err)
2010 break;
2011
2012 /* Increment our various counters */
2013 /* wstats->discard.nwid - no wrong BSSID stuff */
2014 wstats->discard.code +=
2015 le16_to_cpu(tallies.RxWEPUndecryptable);
2016 if (len == sizeof(tallies))
2017 wstats->discard.code +=
2018 le16_to_cpu(tallies.RxDiscards_WEPICVError) +
2019 le16_to_cpu(tallies.RxDiscards_WEPExcluded);
2020 wstats->discard.misc +=
2021 le16_to_cpu(tallies.TxDiscardsWrongSA);
2022 wstats->discard.fragment +=
2023 le16_to_cpu(tallies.RxMsgInBadMsgFragments);
2024 wstats->discard.retries +=
2025 le16_to_cpu(tallies.TxRetryLimitExceeded);
2026 /* wstats->miss.beacon - no match */
2027 }
2028 break;
2029 case HERMES_INQ_LINKSTATUS: {
2030 struct hermes_linkstatus linkstatus;
2031 u16 newstatus;
2032 int connected;
2033
2034 if (priv->iw_mode == IW_MODE_MONITOR)
2035 break;
2036
2037 if (len != sizeof(linkstatus)) {
2038 printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
2039 dev->name, len);
2040 break;
2041 }
2042
2043 err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
2044 infofid, sizeof(info));
2045 if (err)
2046 break;
2047 newstatus = le16_to_cpu(linkstatus.linkstatus);
2048
2049 /* Symbol firmware uses "out of range" to signal that
2050 * the hostscan frame can be requested. */
2051 if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE &&
2052 priv->firmware_type == FIRMWARE_TYPE_SYMBOL &&
2053 priv->has_hostscan && priv->scan_inprogress) {
2054 hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL);
2055 break;
2056 }
2057
2058 connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
2059 || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
2060 || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE);
2061
2062 if (connected)
2063 netif_carrier_on(dev);
2064 else if (!ignore_disconnect)
2065 netif_carrier_off(dev);
2066
2067 if (newstatus != priv->last_linkstatus) {
2068 priv->last_linkstatus = newstatus;
2069 print_linkstatus(dev, newstatus);
2070 /* The info frame contains only one word which is the
2071 * status (see hermes.h). The status is pretty boring
2072 * in itself, that's why we export the new BSSID...
2073 * Jean II */
2074 schedule_work(&priv->wevent_work);
2075 }
2076 }
2077 break;
2078 case HERMES_INQ_SCAN:
2079 if (!priv->scan_inprogress && priv->bssid_fixed &&
2080 priv->firmware_type == FIRMWARE_TYPE_INTERSIL) {
2081 schedule_work(&priv->join_work);
2082 break;
2083 }
2084 /* fall through */
2085 case HERMES_INQ_HOSTSCAN:
2086 case HERMES_INQ_HOSTSCAN_SYMBOL: {
2087 /* Result of a scanning. Contains information about
2088 * cells in the vicinity - Jean II */
2089 union iwreq_data wrqu;
2090 unsigned char *buf;
2091
2092 /* Scan is no longer in progress */
2093 priv->scan_inprogress = 0;
2094
2095 /* Sanity check */
2096 if (len > 4096) {
2097 printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n",
2098 dev->name, len);
2099 break;
2100 }
2101
2102 /* Allocate buffer for results */
2103 buf = kmalloc(len, GFP_ATOMIC);
2104 if (buf == NULL)
2105 /* No memory, so can't printk()... */
2106 break;
2107
2108 /* Read scan data */
2109 err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len,
2110 infofid, sizeof(info));
2111 if (err) {
2112 kfree(buf);
2113 break;
2114 }
2115
2116#ifdef ORINOCO_DEBUG
2117 {
2118 int i;
2119 printk(KERN_DEBUG "Scan result [%02X", buf[0]);
2120 for(i = 1; i < (len * 2); i++)
2121 printk(":%02X", buf[i]);
2122 printk("]\n");
2123 }
2124#endif /* ORINOCO_DEBUG */
2125
2126 if (orinoco_process_scan_results(dev, buf, len) == 0) {
2127 /* Send an empty event to user space.
2128 * We don't send the received data on the event because
2129 * it would require us to do complex transcoding, and
2130 * we want to minimise the work done in the irq handler
2131 * Use a request to extract the data - Jean II */
2132 wrqu.data.length = 0;
2133 wrqu.data.flags = 0;
2134 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
2135 }
2136 kfree(buf);
2137 }
2138 break;
2139 case HERMES_INQ_CHANNELINFO:
2140 {
2141 struct agere_ext_scan_info *bss;
2142
2143 if (!priv->scan_inprogress) {
2144 printk(KERN_DEBUG "%s: Got chaninfo without scan, "
2145 "len=%d\n", dev->name, len);
2146 break;
2147 }
2148
2149 /* An empty result indicates that the scan is complete */
2150 if (len == 0) {
2151 union iwreq_data wrqu;
2152
2153 /* Scan is no longer in progress */
2154 priv->scan_inprogress = 0;
2155
2156 wrqu.data.length = 0;
2157 wrqu.data.flags = 0;
2158 wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
2159 break;
2160 }
2161
2162 /* Sanity check */
2163 else if (len > sizeof(*bss)) {
2164 printk(KERN_WARNING
2165 "%s: Ext scan results too large (%d bytes). "
2166 "Truncating results to %zd bytes.\n",
2167 dev->name, len, sizeof(*bss));
2168 len = sizeof(*bss);
2169 } else if (len < (offsetof(struct agere_ext_scan_info,
2170 data) + 2)) {
2171 /* Drop this result now so we don't have to
2172 * keep checking later */
2173 printk(KERN_WARNING
2174 "%s: Ext scan results too short (%d bytes)\n",
2175 dev->name, len);
2176 break;
2177 }
2178
2179 bss = kmalloc(sizeof(*bss), GFP_ATOMIC);
2180 if (bss == NULL)
2181 break;
2182
2183 /* Read scan data */
2184 err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len,
2185 infofid, sizeof(info));
2186 if (err) {
2187 kfree(bss);
2188 break;
2189 }
2190
2191 orinoco_add_ext_scan_result(priv, bss);
2192
2193 kfree(bss);
2194 break;
2195 }
2196 case HERMES_INQ_SEC_STAT_AGERE:
2197 /* Security status (Agere specific) */
2198 /* Ignore this frame for now */
2199 if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
2200 break;
2201 /* fall through */
2202 default:
2203 printk(KERN_DEBUG "%s: Unknown information frame received: "
2204 "type 0x%04x, length %d\n", dev->name, type, len);
2205 /* We don't actually do anything about it */
2206 break;
2207 }
2208}
2209
2210static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
2211{
2212 if (net_ratelimit())
2213 printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
2214}
2215
2216/********************************************************************/
2217/* Internal hardware control routines */
2218/********************************************************************/
2219
2220int __orinoco_up(struct net_device *dev)
2221{
2222 struct orinoco_private *priv = netdev_priv(dev);
2223 struct hermes *hw = &priv->hw;
2224 int err;
2225
2226 netif_carrier_off(dev); /* just to make sure */
2227
2228 err = __orinoco_program_rids(dev);
2229 if (err) {
2230 printk(KERN_ERR "%s: Error %d configuring card\n",
2231 dev->name, err);
2232 return err;
2233 }
2234
2235 /* Fire things up again */
2236 hermes_set_irqmask(hw, ORINOCO_INTEN);
2237 err = hermes_enable_port(hw, 0);
2238 if (err) {
2239 printk(KERN_ERR "%s: Error %d enabling MAC port\n",
2240 dev->name, err);
2241 return err;
2242 }
2243
2244 netif_start_queue(dev);
2245
2246 return 0;
2247}
2248
2249int __orinoco_down(struct net_device *dev)
2250{
2251 struct orinoco_private *priv = netdev_priv(dev);
2252 struct hermes *hw = &priv->hw;
2253 int err;
2254
2255 netif_stop_queue(dev);
2256
2257 if (! priv->hw_unavailable) {
2258 if (! priv->broken_disableport) {
2259 err = hermes_disable_port(hw, 0);
2260 if (err) {
2261 /* Some firmwares (e.g. Intersil 1.3.x) seem
2262 * to have problems disabling the port, oh
2263 * well, too bad. */
2264 printk(KERN_WARNING "%s: Error %d disabling MAC port\n",
2265 dev->name, err);
2266 priv->broken_disableport = 1;
2267 }
2268 }
2269 hermes_set_irqmask(hw, 0);
2270 hermes_write_regn(hw, EVACK, 0xffff);
2271 }
2272
2273 /* firmware will have to reassociate */
2274 netif_carrier_off(dev);
2275 priv->last_linkstatus = 0xffff;
2276
2277 return 0;
2278}
2279
2280static int orinoco_allocate_fid(struct net_device *dev)
2281{
2282 struct orinoco_private *priv = netdev_priv(dev);
2283 struct hermes *hw = &priv->hw;
2284 int err;
2285
2286 err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
2287 if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
2288 /* Try workaround for old Symbol firmware bug */
2289 printk(KERN_WARNING "%s: firmware ALLOC bug detected "
2290 "(old Symbol firmware?). Trying to work around... ",
2291 dev->name);
2292
2293 priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
2294 err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
2295 if (err)
2296 printk("failed!\n");
2297 else
2298 printk("ok.\n");
2299 }
2300
2301 return err;
2302}
2303
2304int orinoco_reinit_firmware(struct net_device *dev)
2305{
2306 struct orinoco_private *priv = netdev_priv(dev);
2307 struct hermes *hw = &priv->hw;
2308 int err;
2309
2310 err = hermes_init(hw);
2311 if (priv->do_fw_download && !err) {
2312 err = orinoco_download(priv);
2313 if (err)
2314 priv->do_fw_download = 0;
2315 }
2316 if (!err)
2317 err = orinoco_allocate_fid(dev);
2318
2319 return err;
2320}
2321
2322static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
2323{
2324 hermes_t *hw = &priv->hw;
2325 int err = 0;
2326
2327 if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
2328 printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
2329 priv->ndev->name, priv->bitratemode);
2330 return -EINVAL;
2331 }
2332
2333 switch (priv->firmware_type) {
2334 case FIRMWARE_TYPE_AGERE:
2335 err = hermes_write_wordrec(hw, USER_BAP,
2336 HERMES_RID_CNFTXRATECONTROL,
2337 bitrate_table[priv->bitratemode].agere_txratectrl);
2338 break;
2339 case FIRMWARE_TYPE_INTERSIL:
2340 case FIRMWARE_TYPE_SYMBOL:
2341 err = hermes_write_wordrec(hw, USER_BAP,
2342 HERMES_RID_CNFTXRATECONTROL,
2343 bitrate_table[priv->bitratemode].intersil_txratectrl);
2344 break;
2345 default:
2346 BUG();
2347 }
2348
2349 return err;
2350}
2351
2352/* Set fixed AP address */
2353static int __orinoco_hw_set_wap(struct orinoco_private *priv)
2354{
2355 int roaming_flag;
2356 int err = 0;
2357 hermes_t *hw = &priv->hw;
2358
2359 switch (priv->firmware_type) {
2360 case FIRMWARE_TYPE_AGERE:
2361 /* not supported */
2362 break;
2363 case FIRMWARE_TYPE_INTERSIL:
2364 if (priv->bssid_fixed)
2365 roaming_flag = 2;
2366 else
2367 roaming_flag = 1;
2368
2369 err = hermes_write_wordrec(hw, USER_BAP,
2370 HERMES_RID_CNFROAMINGMODE,
2371 roaming_flag);
2372 break;
2373 case FIRMWARE_TYPE_SYMBOL:
2374 err = HERMES_WRITE_RECORD(hw, USER_BAP,
2375 HERMES_RID_CNFMANDATORYBSSID_SYMBOL,
2376 &priv->desired_bssid);
2377 break;
2378 }
2379 return err;
2380}
2381
2382/* Change the WEP keys and/or the current keys. Can be called
2383 * either from __orinoco_hw_setup_enc() or directly from
2384 * orinoco_ioctl_setiwencode(). In the later case the association
2385 * with the AP is not broken (if the firmware can handle it),
2386 * which is needed for 802.1x implementations. */
2387static int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv)
2388{
2389 hermes_t *hw = &priv->hw;
2390 int err = 0;
2391
2392 switch (priv->firmware_type) {
2393 case FIRMWARE_TYPE_AGERE:
2394 err = HERMES_WRITE_RECORD(hw, USER_BAP,
2395 HERMES_RID_CNFWEPKEYS_AGERE,
2396 &priv->keys);
2397 if (err)
2398 return err;
2399 err = hermes_write_wordrec(hw, USER_BAP,
2400 HERMES_RID_CNFTXKEY_AGERE,
2401 priv->tx_key);
2402 if (err)
2403 return err;
2404 break;
2405 case FIRMWARE_TYPE_INTERSIL:
2406 case FIRMWARE_TYPE_SYMBOL:
2407 {
2408 int keylen;
2409 int i;
2410
2411 /* Force uniform key length to work around firmware bugs */
2412 keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
2413
2414 if (keylen > LARGE_KEY_SIZE) {
2415 printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
2416 priv->ndev->name, priv->tx_key, keylen);
2417 return -E2BIG;
2418 }
2419
2420 /* Write all 4 keys */
2421 for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
2422 err = hermes_write_ltv(hw, USER_BAP,
2423 HERMES_RID_CNFDEFAULTKEY0 + i,
2424 HERMES_BYTES_TO_RECLEN(keylen),
2425 priv->keys[i].data);
2426 if (err)
2427 return err;
2428 }
2429
2430 /* Write the index of the key used in transmission */
2431 err = hermes_write_wordrec(hw, USER_BAP,
2432 HERMES_RID_CNFWEPDEFAULTKEYID,
2433 priv->tx_key);
2434 if (err)
2435 return err;
2436 }
2437 break;
2438 }
2439
2440 return 0;
2441}
2442
2443static int __orinoco_hw_setup_enc(struct orinoco_private *priv)
2444{
2445 hermes_t *hw = &priv->hw;
2446 int err = 0;
2447 int master_wep_flag;
2448 int auth_flag;
2449 int enc_flag;
2450
2451 /* Setup WEP keys for WEP and WPA */
2452 if (priv->encode_alg)
2453 __orinoco_hw_setup_wepkeys(priv);
2454
2455 if (priv->wep_restrict)
2456 auth_flag = HERMES_AUTH_SHARED_KEY;
2457 else
2458 auth_flag = HERMES_AUTH_OPEN;
2459
2460 if (priv->wpa_enabled)
2461 enc_flag = 2;
2462 else if (priv->encode_alg == IW_ENCODE_ALG_WEP)
2463 enc_flag = 1;
2464 else
2465 enc_flag = 0;
2466
2467 switch (priv->firmware_type) {
2468 case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
2469 if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
2470 /* Enable the shared-key authentication. */
2471 err = hermes_write_wordrec(hw, USER_BAP,
2472 HERMES_RID_CNFAUTHENTICATION_AGERE,
2473 auth_flag);
2474 }
2475 err = hermes_write_wordrec(hw, USER_BAP,
2476 HERMES_RID_CNFWEPENABLED_AGERE,
2477 enc_flag);
2478 if (err)
2479 return err;
2480
2481 if (priv->has_wpa) {
2482 /* Set WPA key management */
2483 err = hermes_write_wordrec(hw, USER_BAP,
2484 HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE,
2485 priv->key_mgmt);
2486 if (err)
2487 return err;
2488 }
2489
2490 break;
2491
2492 case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
2493 case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
2494 if (priv->encode_alg == IW_ENCODE_ALG_WEP) {
2495 if (priv->wep_restrict ||
2496 (priv->firmware_type == FIRMWARE_TYPE_SYMBOL))
2497 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED |
2498 HERMES_WEP_EXCL_UNENCRYPTED;
2499 else
2500 master_wep_flag = HERMES_WEP_PRIVACY_INVOKED;
2501
2502 err = hermes_write_wordrec(hw, USER_BAP,
2503 HERMES_RID_CNFAUTHENTICATION,
2504 auth_flag);
2505 if (err)
2506 return err;
2507 } else
2508 master_wep_flag = 0;
2509
2510 if (priv->iw_mode == IW_MODE_MONITOR)
2511 master_wep_flag |= HERMES_WEP_HOST_DECRYPT;
2512
2513 /* Master WEP setting : on/off */
2514 err = hermes_write_wordrec(hw, USER_BAP,
2515 HERMES_RID_CNFWEPFLAGS_INTERSIL,
2516 master_wep_flag);
2517 if (err)
2518 return err;
2519
2520 break;
2521 }
2522
2523 return 0;
2524}
2525
2526/* key must be 32 bytes, including the tx and rx MIC keys.
2527 * rsc must be 8 bytes
2528 * tsc must be 8 bytes or NULL
2529 */
2530static int __orinoco_hw_set_tkip_key(hermes_t *hw, int key_idx, int set_tx,
2531 u8 *key, u8 *rsc, u8 *tsc)
2532{
2533 struct {
2534 __le16 idx;
2535 u8 rsc[IW_ENCODE_SEQ_MAX_SIZE];
2536 u8 key[TKIP_KEYLEN];
2537 u8 tx_mic[MIC_KEYLEN];
2538 u8 rx_mic[MIC_KEYLEN];
2539 u8 tsc[IW_ENCODE_SEQ_MAX_SIZE];
2540 } __attribute__ ((packed)) buf;
2541 int ret;
2542 int err;
2543 int k;
2544 u16 xmitting;
2545
2546 key_idx &= 0x3;
2547
2548 if (set_tx)
2549 key_idx |= 0x8000;
2550
2551 buf.idx = cpu_to_le16(key_idx);
2552 memcpy(buf.key, key,
2553 sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic));
2554
2555 if (rsc == NULL)
2556 memset(buf.rsc, 0, sizeof(buf.rsc));
2557 else
2558 memcpy(buf.rsc, rsc, sizeof(buf.rsc));
2559
2560 if (tsc == NULL) {
2561 memset(buf.tsc, 0, sizeof(buf.tsc));
2562 buf.tsc[4] = 0x10;
2563 } else {
2564 memcpy(buf.tsc, tsc, sizeof(buf.tsc));
2565 }
2566
2567 /* Wait upto 100ms for tx queue to empty */
2568 k = 100;
2569 do {
2570 k--;
2571 udelay(1000);
2572 ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
2573 &xmitting);
2574 if (ret)
2575 break;
2576 } while ((k > 0) && xmitting);
2577
2578 if (k == 0)
2579 ret = -ETIMEDOUT;
2580
2581 err = HERMES_WRITE_RECORD(hw, USER_BAP,
2582 HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE,
2583 &buf);
2584
2585 return ret ? ret : err;
2586}
2587
2588static int orinoco_clear_tkip_key(struct orinoco_private *priv,
2589 int key_idx)
2590{
2591 hermes_t *hw = &priv->hw;
2592 int err;
2593
2594 memset(&priv->tkip_key[key_idx], 0, sizeof(priv->tkip_key[key_idx]));
2595 err = hermes_write_wordrec(hw, USER_BAP,
2596 HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE,
2597 key_idx);
2598 if (err)
2599 printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n",
2600 priv->ndev->name, err, key_idx);
2601 return err;
2602}
2603
2604static int __orinoco_program_rids(struct net_device *dev)
2605{
2606 struct orinoco_private *priv = netdev_priv(dev);
2607 hermes_t *hw = &priv->hw;
2608 int err;
2609 struct hermes_idstring idbuf;
2610
2611 /* Set the MAC address */
2612 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
2613 HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
2614 if (err) {
2615 printk(KERN_ERR "%s: Error %d setting MAC address\n",
2616 dev->name, err);
2617 return err;
2618 }
2619
2620 /* Set up the link mode */
2621 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE,
2622 priv->port_type);
2623 if (err) {
2624 printk(KERN_ERR "%s: Error %d setting port type\n",
2625 dev->name, err);
2626 return err;
2627 }
2628 /* Set the channel/frequency */
2629 if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
2630 err = hermes_write_wordrec(hw, USER_BAP,
2631 HERMES_RID_CNFOWNCHANNEL,
2632 priv->channel);
2633 if (err) {
2634 printk(KERN_ERR "%s: Error %d setting channel %d\n",
2635 dev->name, err, priv->channel);
2636 return err;
2637 }
2638 }
2639
2640 if (priv->has_ibss) {
2641 u16 createibss;
2642
2643 if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) {
2644 printk(KERN_WARNING "%s: This firmware requires an "
2645 "ESSID in IBSS-Ad-Hoc mode.\n", dev->name);
2646 /* With wvlan_cs, in this case, we would crash.
2647 * hopefully, this driver will behave better...
2648 * Jean II */
2649 createibss = 0;
2650 } else {
2651 createibss = priv->createibss;
2652 }
2653
2654 err = hermes_write_wordrec(hw, USER_BAP,
2655 HERMES_RID_CNFCREATEIBSS,
2656 createibss);
2657 if (err) {
2658 printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n",
2659 dev->name, err);
2660 return err;
2661 }
2662 }
2663
2664 /* Set the desired BSSID */
2665 err = __orinoco_hw_set_wap(priv);
2666 if (err) {
2667 printk(KERN_ERR "%s: Error %d setting AP address\n",
2668 dev->name, err);
2669 return err;
2670 }
2671 /* Set the desired ESSID */
2672 idbuf.len = cpu_to_le16(strlen(priv->desired_essid));
2673 memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
2674 /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
2675 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
2676 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
2677 &idbuf);
2678 if (err) {
2679 printk(KERN_ERR "%s: Error %d setting OWNSSID\n",
2680 dev->name, err);
2681 return err;
2682 }
2683 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
2684 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
2685 &idbuf);
2686 if (err) {
2687 printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n",
2688 dev->name, err);
2689 return err;
2690 }
2691
2692 /* Set the station name */
2693 idbuf.len = cpu_to_le16(strlen(priv->nick));
2694 memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
2695 err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
2696 HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
2697 &idbuf);
2698 if (err) {
2699 printk(KERN_ERR "%s: Error %d setting nickname\n",
2700 dev->name, err);
2701 return err;
2702 }
2703
2704 /* Set AP density */
2705 if (priv->has_sensitivity) {
2706 err = hermes_write_wordrec(hw, USER_BAP,
2707 HERMES_RID_CNFSYSTEMSCALE,
2708 priv->ap_density);
2709 if (err) {
2710 printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. "
2711 "Disabling sensitivity control\n",
2712 dev->name, err);
2713
2714 priv->has_sensitivity = 0;
2715 }
2716 }
2717
2718 /* Set RTS threshold */
2719 err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
2720 priv->rts_thresh);
2721 if (err) {
2722 printk(KERN_ERR "%s: Error %d setting RTS threshold\n",
2723 dev->name, err);
2724 return err;
2725 }
2726
2727 /* Set fragmentation threshold or MWO robustness */
2728 if (priv->has_mwo)
2729 err = hermes_write_wordrec(hw, USER_BAP,
2730 HERMES_RID_CNFMWOROBUST_AGERE,
2731 priv->mwo_robust);
2732 else
2733 err = hermes_write_wordrec(hw, USER_BAP,
2734 HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
2735 priv->frag_thresh);
2736 if (err) {
2737 printk(KERN_ERR "%s: Error %d setting fragmentation\n",
2738 dev->name, err);
2739 return err;
2740 }
2741
2742 /* Set bitrate */
2743 err = __orinoco_hw_set_bitrate(priv);
2744 if (err) {
2745 printk(KERN_ERR "%s: Error %d setting bitrate\n",
2746 dev->name, err);
2747 return err;
2748 }
2749
2750 /* Set power management */
2751 if (priv->has_pm) {
2752 err = hermes_write_wordrec(hw, USER_BAP,
2753 HERMES_RID_CNFPMENABLED,
2754 priv->pm_on);
2755 if (err) {
2756 printk(KERN_ERR "%s: Error %d setting up PM\n",
2757 dev->name, err);
2758 return err;
2759 }
2760
2761 err = hermes_write_wordrec(hw, USER_BAP,
2762 HERMES_RID_CNFMULTICASTRECEIVE,
2763 priv->pm_mcast);
2764 if (err) {
2765 printk(KERN_ERR "%s: Error %d setting up PM\n",
2766 dev->name, err);
2767 return err;
2768 }
2769 err = hermes_write_wordrec(hw, USER_BAP,
2770 HERMES_RID_CNFMAXSLEEPDURATION,
2771 priv->pm_period);
2772 if (err) {
2773 printk(KERN_ERR "%s: Error %d setting up PM\n",
2774 dev->name, err);
2775 return err;
2776 }
2777 err = hermes_write_wordrec(hw, USER_BAP,
2778 HERMES_RID_CNFPMHOLDOVERDURATION,
2779 priv->pm_timeout);
2780 if (err) {
2781 printk(KERN_ERR "%s: Error %d setting up PM\n",
2782 dev->name, err);
2783 return err;
2784 }
2785 }
2786
2787 /* Set preamble - only for Symbol so far... */
2788 if (priv->has_preamble) {
2789 err = hermes_write_wordrec(hw, USER_BAP,
2790 HERMES_RID_CNFPREAMBLE_SYMBOL,
2791 priv->preamble);
2792 if (err) {
2793 printk(KERN_ERR "%s: Error %d setting preamble\n",
2794 dev->name, err);
2795 return err;
2796 }
2797 }
2798
2799 /* Set up encryption */
2800 if (priv->has_wep || priv->has_wpa) {
2801 err = __orinoco_hw_setup_enc(priv);
2802 if (err) {
2803 printk(KERN_ERR "%s: Error %d activating encryption\n",
2804 dev->name, err);
2805 return err;
2806 }
2807 }
2808
2809 if (priv->iw_mode == IW_MODE_MONITOR) {
2810 /* Enable monitor mode */
2811 dev->type = ARPHRD_IEEE80211;
2812 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
2813 HERMES_TEST_MONITOR, 0, NULL);
2814 } else {
2815 /* Disable monitor mode */
2816 dev->type = ARPHRD_ETHER;
2817 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
2818 HERMES_TEST_STOP, 0, NULL);
2819 }
2820 if (err)
2821 return err;
2822
2823 /* Set promiscuity / multicast*/
2824 priv->promiscuous = 0;
2825 priv->mc_count = 0;
2826
2827 /* FIXME: what about netif_tx_lock */
2828 __orinoco_set_multicast_list(dev);
2829
2830 return 0;
2831}
2832
2833/* FIXME: return int? */
2834static void
2835__orinoco_set_multicast_list(struct net_device *dev)
2836{
2837 struct orinoco_private *priv = netdev_priv(dev);
2838 hermes_t *hw = &priv->hw;
2839 int err = 0;
2840 int promisc, mc_count;
2841
2842 /* The Hermes doesn't seem to have an allmulti mode, so we go
2843 * into promiscuous mode and let the upper levels deal. */
2844 if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
2845 (dev->mc_count > MAX_MULTICAST(priv)) ) {
2846 promisc = 1;
2847 mc_count = 0;
2848 } else {
2849 promisc = 0;
2850 mc_count = dev->mc_count;
2851 }
2852
2853 if (promisc != priv->promiscuous) {
2854 err = hermes_write_wordrec(hw, USER_BAP,
2855 HERMES_RID_CNFPROMISCUOUSMODE,
2856 promisc);
2857 if (err) {
2858 printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
2859 dev->name, err);
2860 } else
2861 priv->promiscuous = promisc;
2862 }
2863
2864 /* If we're not in promiscuous mode, then we need to set the
2865 * group address if either we want to multicast, or if we were
2866 * multicasting and want to stop */
2867 if (! promisc && (mc_count || priv->mc_count) ) {
2868 struct dev_mc_list *p = dev->mc_list;
2869 struct hermes_multicast mclist;
2870 int i;
2871
2872 for (i = 0; i < mc_count; i++) {
2873 /* paranoia: is list shorter than mc_count? */
2874 BUG_ON(! p);
2875 /* paranoia: bad address size in list? */
2876 BUG_ON(p->dmi_addrlen != ETH_ALEN);
2877
2878 memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
2879 p = p->next;
2880 }
2881
2882 if (p)
2883 printk(KERN_WARNING "%s: Multicast list is "
2884 "longer than mc_count\n", dev->name);
2885
2886 err = hermes_write_ltv(hw, USER_BAP,
2887 HERMES_RID_CNFGROUPADDRESSES,
2888 HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN),
2889 &mclist);
2890 if (err)
2891 printk(KERN_ERR "%s: Error %d setting multicast list.\n",
2892 dev->name, err);
2893 else
2894 priv->mc_count = mc_count;
2895 }
2896}
2897
2898/* This must be called from user context, without locks held - use
2899 * schedule_work() */
2900static void orinoco_reset(struct work_struct *work)
2901{
2902 struct orinoco_private *priv =
2903 container_of(work, struct orinoco_private, reset_work);
2904 struct net_device *dev = priv->ndev;
2905 struct hermes *hw = &priv->hw;
2906 int err;
2907 unsigned long flags;
2908
2909 if (orinoco_lock(priv, &flags) != 0)
2910 /* When the hardware becomes available again, whatever
2911 * detects that is responsible for re-initializing
2912 * it. So no need for anything further */
2913 return;
2914
2915 netif_stop_queue(dev);
2916
2917 /* Shut off interrupts. Depending on what state the hardware
2918 * is in, this might not work, but we'll try anyway */
2919 hermes_set_irqmask(hw, 0);
2920 hermes_write_regn(hw, EVACK, 0xffff);
2921
2922 priv->hw_unavailable++;
2923 priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */
2924 netif_carrier_off(dev);
2925
2926 orinoco_unlock(priv, &flags);
2927
2928 /* Scanning support: Cleanup of driver struct */
2929 orinoco_clear_scan_results(priv, 0);
2930 priv->scan_inprogress = 0;
2931
2932 if (priv->hard_reset) {
2933 err = (*priv->hard_reset)(priv);
2934 if (err) {
2935 printk(KERN_ERR "%s: orinoco_reset: Error %d "
2936 "performing hard reset\n", dev->name, err);
2937 goto disable;
2938 }
2939 }
2940
2941 err = orinoco_reinit_firmware(dev);
2942 if (err) {
2943 printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
2944 dev->name, err);
2945 goto disable;
2946 }
2947
2948 spin_lock_irq(&priv->lock); /* This has to be called from user context */
2949
2950 priv->hw_unavailable--;
2951
2952 /* priv->open or priv->hw_unavailable might have changed while
2953 * we dropped the lock */
2954 if (priv->open && (! priv->hw_unavailable)) {
2955 err = __orinoco_up(dev);
2956 if (err) {
2957 printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
2958 dev->name, err);
2959 } else
2960 dev->trans_start = jiffies;
2961 }
2962
2963 spin_unlock_irq(&priv->lock);
2964
2965 return;
2966 disable:
2967 hermes_set_irqmask(hw, 0);
2968 netif_device_detach(dev);
2969 printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
2970}
2971
2972/********************************************************************/
2973/* Interrupt handler */
2974/********************************************************************/
2975
2976static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
2977{
2978 printk(KERN_DEBUG "%s: TICK\n", dev->name);
2979}
2980
2981static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
2982{
2983 /* This seems to happen a fair bit under load, but ignoring it
2984 seems to work fine...*/
2985 printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
2986 dev->name);
2987}
2988
2989irqreturn_t orinoco_interrupt(int irq, void *dev_id)
2990{
2991 struct net_device *dev = dev_id;
2992 struct orinoco_private *priv = netdev_priv(dev);
2993 hermes_t *hw = &priv->hw;
2994 int count = MAX_IRQLOOPS_PER_IRQ;
2995 u16 evstat, events;
2996 /* These are used to detect a runaway interrupt situation */
2997 /* If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy,
2998 * we panic and shut down the hardware */
2999 static int last_irq_jiffy = 0; /* jiffies value the last time
3000 * we were called */
3001 static int loops_this_jiffy = 0;
3002 unsigned long flags;
3003
3004 if (orinoco_lock(priv, &flags) != 0) {
3005 /* If hw is unavailable - we don't know if the irq was
3006 * for us or not */
3007 return IRQ_HANDLED;
3008 }
3009
3010 evstat = hermes_read_regn(hw, EVSTAT);
3011 events = evstat & hw->inten;
3012 if (! events) {
3013 orinoco_unlock(priv, &flags);
3014 return IRQ_NONE;
3015 }
3016
3017 if (jiffies != last_irq_jiffy)
3018 loops_this_jiffy = 0;
3019 last_irq_jiffy = jiffies;
3020
3021 while (events && count--) {
3022 if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
3023 printk(KERN_WARNING "%s: IRQ handler is looping too "
3024 "much! Resetting.\n", dev->name);
3025 /* Disable interrupts for now */
3026 hermes_set_irqmask(hw, 0);
3027 schedule_work(&priv->reset_work);
3028 break;
3029 }
3030
3031 /* Check the card hasn't been removed */
3032 if (! hermes_present(hw)) {
3033 DEBUG(0, "orinoco_interrupt(): card removed\n");
3034 break;
3035 }
3036
3037 if (events & HERMES_EV_TICK)
3038 __orinoco_ev_tick(dev, hw);
3039 if (events & HERMES_EV_WTERR)
3040 __orinoco_ev_wterr(dev, hw);
3041 if (events & HERMES_EV_INFDROP)
3042 __orinoco_ev_infdrop(dev, hw);
3043 if (events & HERMES_EV_INFO)
3044 __orinoco_ev_info(dev, hw);
3045 if (events & HERMES_EV_RX)
3046 __orinoco_ev_rx(dev, hw);
3047 if (events & HERMES_EV_TXEXC)
3048 __orinoco_ev_txexc(dev, hw);
3049 if (events & HERMES_EV_TX)
3050 __orinoco_ev_tx(dev, hw);
3051 if (events & HERMES_EV_ALLOC)
3052 __orinoco_ev_alloc(dev, hw);
3053
3054 hermes_write_regn(hw, EVACK, evstat);
3055
3056 evstat = hermes_read_regn(hw, EVSTAT);
3057 events = evstat & hw->inten;
3058 };
3059
3060 orinoco_unlock(priv, &flags);
3061 return IRQ_HANDLED;
3062}
3063
3064/********************************************************************/
3065/* Initialization */
3066/********************************************************************/
3067
3068struct comp_id {
3069 u16 id, variant, major, minor;
3070} __attribute__ ((packed));
3071
3072static inline fwtype_t determine_firmware_type(struct comp_id *nic_id)
3073{
3074 if (nic_id->id < 0x8000)
3075 return FIRMWARE_TYPE_AGERE;
3076 else if (nic_id->id == 0x8000 && nic_id->major == 0)
3077 return FIRMWARE_TYPE_SYMBOL;
3078 else
3079 return FIRMWARE_TYPE_INTERSIL;
3080}
3081
3082/* Set priv->firmware type, determine firmware properties */
3083static int determine_firmware(struct net_device *dev)
3084{
3085 struct orinoco_private *priv = netdev_priv(dev);
3086 hermes_t *hw = &priv->hw;
3087 int err;
3088 struct comp_id nic_id, sta_id;
3089 unsigned int firmver;
3090 char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2)));
3091
3092 /* Get the hardware version */
3093 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id);
3094 if (err) {
3095 printk(KERN_ERR "%s: Cannot read hardware identity: error %d\n",
3096 dev->name, err);
3097 return err;
3098 }
3099
3100 le16_to_cpus(&nic_id.id);
3101 le16_to_cpus(&nic_id.variant);
3102 le16_to_cpus(&nic_id.major);
3103 le16_to_cpus(&nic_id.minor);
3104 printk(KERN_DEBUG "%s: Hardware identity %04x:%04x:%04x:%04x\n",
3105 dev->name, nic_id.id, nic_id.variant,
3106 nic_id.major, nic_id.minor);
3107
3108 priv->firmware_type = determine_firmware_type(&nic_id);
3109
3110 /* Get the firmware version */
3111 err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
3112 if (err) {
3113 printk(KERN_ERR "%s: Cannot read station identity: error %d\n",
3114 dev->name, err);
3115 return err;
3116 }
3117
3118 le16_to_cpus(&sta_id.id);
3119 le16_to_cpus(&sta_id.variant);
3120 le16_to_cpus(&sta_id.major);
3121 le16_to_cpus(&sta_id.minor);
3122 printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
3123 dev->name, sta_id.id, sta_id.variant,
3124 sta_id.major, sta_id.minor);
3125
3126 switch (sta_id.id) {
3127 case 0x15:
3128 printk(KERN_ERR "%s: Primary firmware is active\n",
3129 dev->name);
3130 return -ENODEV;
3131 case 0x14b:
3132 printk(KERN_ERR "%s: Tertiary firmware is active\n",
3133 dev->name);
3134 return -ENODEV;
3135 case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */
3136 case 0x21: /* Symbol Spectrum24 Trilogy */
3137 break;
3138 default:
3139 printk(KERN_NOTICE "%s: Unknown station ID, please report\n",
3140 dev->name);
3141 break;
3142 }
3143
3144 /* Default capabilities */
3145 priv->has_sensitivity = 1;
3146 priv->has_mwo = 0;
3147 priv->has_preamble = 0;
3148 priv->has_port3 = 1;
3149 priv->has_ibss = 1;
3150 priv->has_wep = 0;
3151 priv->has_big_wep = 0;
3152 priv->has_alt_txcntl = 0;
3153 priv->has_ext_scan = 0;
3154 priv->has_wpa = 0;
3155 priv->do_fw_download = 0;
3156
3157 /* Determine capabilities from the firmware version */
3158 switch (priv->firmware_type) {
3159 case FIRMWARE_TYPE_AGERE:
3160 /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
3161 ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
3162 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
3163 "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor);
3164
3165 firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;
3166
3167 priv->has_ibss = (firmver >= 0x60006);
3168 priv->has_wep = (firmver >= 0x40020);
3169 priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell
3170 Gold cards from the others? */
3171 priv->has_mwo = (firmver >= 0x60000);
3172 priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */
3173 priv->ibss_port = 1;
3174 priv->has_hostscan = (firmver >= 0x8000a);
3175 priv->do_fw_download = 1;
3176 priv->broken_monitor = (firmver >= 0x80000);
3177 priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */
3178 priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */
3179 priv->has_wpa = (firmver >= 0x9002a);
3180 /* Tested with Agere firmware :
3181 * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II
3182 * Tested CableTron firmware : 4.32 => Anton */
3183 break;
3184 case FIRMWARE_TYPE_SYMBOL:
3185 /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */
3186 /* Intel MAC : 00:02:B3:* */
3187 /* 3Com MAC : 00:50:DA:* */
3188 memset(tmp, 0, sizeof(tmp));
3189 /* Get the Symbol firmware version */
3190 err = hermes_read_ltv(hw, USER_BAP,
3191 HERMES_RID_SECONDARYVERSION_SYMBOL,
3192 SYMBOL_MAX_VER_LEN, NULL, &tmp);
3193 if (err) {
3194 printk(KERN_WARNING
3195 "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
3196 dev->name, err);
3197 firmver = 0;
3198 tmp[0] = '\0';
3199 } else {
3200 /* The firmware revision is a string, the format is
3201 * something like : "V2.20-01".
3202 * Quick and dirty parsing... - Jean II
3203 */
3204 firmver = ((tmp[1] - '0') << 16) | ((tmp[3] - '0') << 12)
3205 | ((tmp[4] - '0') << 8) | ((tmp[6] - '0') << 4)
3206 | (tmp[7] - '0');
3207
3208 tmp[SYMBOL_MAX_VER_LEN] = '\0';
3209 }
3210
3211 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
3212 "Symbol %s", tmp);
3213
3214 priv->has_ibss = (firmver >= 0x20000);
3215 priv->has_wep = (firmver >= 0x15012);
3216 priv->has_big_wep = (firmver >= 0x20000);
3217 priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) ||
3218 (firmver >= 0x29000 && firmver < 0x30000) ||
3219 firmver >= 0x31000;
3220 priv->has_preamble = (firmver >= 0x20000);
3221 priv->ibss_port = 4;
3222
3223 /* Symbol firmware is found on various cards, but
3224 * there has been no attempt to check firmware
3225 * download on non-spectrum_cs based cards.
3226 *
3227 * Given that the Agere firmware download works
3228 * differently, we should avoid doing a firmware
3229 * download with the Symbol algorithm on non-spectrum
3230 * cards.
3231 *
3232 * For now we can identify a spectrum_cs based card
3233 * because it has a firmware reset function.
3234 */
3235 priv->do_fw_download = (priv->stop_fw != NULL);
3236
3237 priv->broken_disableport = (firmver == 0x25013) ||
3238 (firmver >= 0x30000 && firmver <= 0x31000);
3239 priv->has_hostscan = (firmver >= 0x31001) ||
3240 (firmver >= 0x29057 && firmver < 0x30000);
3241 /* Tested with Intel firmware : 0x20015 => Jean II */
3242 /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
3243 break;
3244 case FIRMWARE_TYPE_INTERSIL:
3245 /* D-Link, Linksys, Adtron, ZoomAir, and many others...
3246 * Samsung, Compaq 100/200 and Proxim are slightly
3247 * different and less well tested */
3248 /* D-Link MAC : 00:40:05:* */
3249 /* Addtron MAC : 00:90:D1:* */
3250 snprintf(priv->fw_name, sizeof(priv->fw_name) - 1,
3251 "Intersil %d.%d.%d", sta_id.major, sta_id.minor,
3252 sta_id.variant);
3253
3254 firmver = ((unsigned long)sta_id.major << 16) |
3255 ((unsigned long)sta_id.minor << 8) | sta_id.variant;
3256
3257 priv->has_ibss = (firmver >= 0x000700); /* FIXME */
3258 priv->has_big_wep = priv->has_wep = (firmver >= 0x000800);
3259 priv->has_pm = (firmver >= 0x000700);
3260 priv->has_hostscan = (firmver >= 0x010301);
3261
3262 if (firmver >= 0x000800)
3263 priv->ibss_port = 0;
3264 else {
3265 printk(KERN_NOTICE "%s: Intersil firmware earlier "
3266 "than v0.8.x - several features not supported\n",
3267 dev->name);
3268 priv->ibss_port = 1;
3269 }
3270 break;
3271 }
3272 printk(KERN_DEBUG "%s: Firmware determined as %s\n", dev->name,
3273 priv->fw_name);
3274
3275 return 0;
3276}
3277
3278static int orinoco_init(struct net_device *dev)
3279{
3280 struct orinoco_private *priv = netdev_priv(dev);
3281 hermes_t *hw = &priv->hw;
3282 int err = 0;
3283 struct hermes_idstring nickbuf;
3284 u16 reclen;
3285 int len;
3286
3287 /* No need to lock, the hw_unavailable flag is already set in
3288 * alloc_orinocodev() */
3289 priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN;
3290
3291 /* Initialize the firmware */
3292 err = hermes_init(hw);
3293 if (err != 0) {
3294 printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
3295 dev->name, err);
3296 goto out;
3297 }
3298
3299 err = determine_firmware(dev);
3300 if (err != 0) {
3301 printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
3302 dev->name);
3303 goto out;
3304 }
3305
3306 if (priv->do_fw_download) {
3307 err = orinoco_download(priv);
3308 if (err)
3309 priv->do_fw_download = 0;
3310
3311 /* Check firmware version again */
3312 err = determine_firmware(dev);
3313 if (err != 0) {
3314 printk(KERN_ERR "%s: Incompatible firmware, aborting\n",
3315 dev->name);
3316 goto out;
3317 }
3318 }
3319
3320 if (priv->has_port3)
3321 printk(KERN_DEBUG "%s: Ad-hoc demo mode supported\n", dev->name);
3322 if (priv->has_ibss)
3323 printk(KERN_DEBUG "%s: IEEE standard IBSS ad-hoc mode supported\n",
3324 dev->name);
3325 if (priv->has_wep) {
3326 printk(KERN_DEBUG "%s: WEP supported, ", dev->name);
3327 if (priv->has_big_wep)
3328 printk("104-bit key\n");
3329 else
3330 printk("40-bit key\n");
3331 }
3332 if (priv->has_wpa) {
3333 printk(KERN_DEBUG "%s: WPA-PSK supported\n", dev->name);
3334 if (orinoco_mic_init(priv)) {
3335 printk(KERN_ERR "%s: Failed to setup MIC crypto "
3336 "algorithm. Disabling WPA support\n", dev->name);
3337 priv->has_wpa = 0;
3338 }
3339 }
3340
3341 /* Now we have the firmware capabilities, allocate appropiate
3342 * sized scan buffers */
3343 if (orinoco_bss_data_allocate(priv))
3344 goto out;
3345 orinoco_bss_data_init(priv);
3346
3347 /* Get the MAC address */
3348 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
3349 ETH_ALEN, NULL, dev->dev_addr);
3350 if (err) {
3351 printk(KERN_WARNING "%s: failed to read MAC address!\n",
3352 dev->name);
3353 goto out;
3354 }
3355
3356 printk(KERN_DEBUG "%s: MAC address %pM\n",
3357 dev->name, dev->dev_addr);
3358
3359 /* Get the station name */
3360 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
3361 sizeof(nickbuf), &reclen, &nickbuf);
3362 if (err) {
3363 printk(KERN_ERR "%s: failed to read station name\n",
3364 dev->name);
3365 goto out;
3366 }
3367 if (nickbuf.len)
3368 len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len));
3369 else
3370 len = min(IW_ESSID_MAX_SIZE, 2 * reclen);
3371 memcpy(priv->nick, &nickbuf.val, len);
3372 priv->nick[len] = '\0';
3373
3374 printk(KERN_DEBUG "%s: Station name \"%s\"\n", dev->name, priv->nick);
3375
3376 err = orinoco_allocate_fid(dev);
3377 if (err) {
3378 printk(KERN_ERR "%s: failed to allocate NIC buffer!\n",
3379 dev->name);
3380 goto out;
3381 }
3382
3383 /* Get allowed channels */
3384 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST,
3385 &priv->channel_mask);
3386 if (err) {
3387 printk(KERN_ERR "%s: failed to read channel list!\n",
3388 dev->name);
3389 goto out;
3390 }
3391
3392 /* Get initial AP density */
3393 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE,
3394 &priv->ap_density);
3395 if (err || priv->ap_density < 1 || priv->ap_density > 3) {
3396 priv->has_sensitivity = 0;
3397 }
3398
3399 /* Get initial RTS threshold */
3400 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD,
3401 &priv->rts_thresh);
3402 if (err) {
3403 printk(KERN_ERR "%s: failed to read RTS threshold!\n",
3404 dev->name);
3405 goto out;
3406 }
3407
3408 /* Get initial fragmentation settings */
3409 if (priv->has_mwo)
3410 err = hermes_read_wordrec(hw, USER_BAP,
3411 HERMES_RID_CNFMWOROBUST_AGERE,
3412 &priv->mwo_robust);
3413 else
3414 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
3415 &priv->frag_thresh);
3416 if (err) {
3417 printk(KERN_ERR "%s: failed to read fragmentation settings!\n",
3418 dev->name);
3419 goto out;
3420 }
3421
3422 /* Power management setup */
3423 if (priv->has_pm) {
3424 priv->pm_on = 0;
3425 priv->pm_mcast = 1;
3426 err = hermes_read_wordrec(hw, USER_BAP,
3427 HERMES_RID_CNFMAXSLEEPDURATION,
3428 &priv->pm_period);
3429 if (err) {
3430 printk(KERN_ERR "%s: failed to read power management period!\n",
3431 dev->name);
3432 goto out;
3433 }
3434 err = hermes_read_wordrec(hw, USER_BAP,
3435 HERMES_RID_CNFPMHOLDOVERDURATION,
3436 &priv->pm_timeout);
3437 if (err) {
3438 printk(KERN_ERR "%s: failed to read power management timeout!\n",
3439 dev->name);
3440 goto out;
3441 }
3442 }
3443
3444 /* Preamble setup */
3445 if (priv->has_preamble) {
3446 err = hermes_read_wordrec(hw, USER_BAP,
3447 HERMES_RID_CNFPREAMBLE_SYMBOL,
3448 &priv->preamble);
3449 if (err)
3450 goto out;
3451 }
3452
3453 /* Set up the default configuration */
3454 priv->iw_mode = IW_MODE_INFRA;
3455 /* By default use IEEE/IBSS ad-hoc mode if we have it */
3456 priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
3457 set_port_type(priv);
3458 priv->channel = 0; /* use firmware default */
3459
3460 priv->promiscuous = 0;
3461 priv->encode_alg = IW_ENCODE_ALG_NONE;
3462 priv->tx_key = 0;
3463 priv->wpa_enabled = 0;
3464 priv->tkip_cm_active = 0;
3465 priv->key_mgmt = 0;
3466 priv->wpa_ie_len = 0;
3467 priv->wpa_ie = NULL;
3468
3469 /* Make the hardware available, as long as it hasn't been
3470 * removed elsewhere (e.g. by PCMCIA hot unplug) */
3471 spin_lock_irq(&priv->lock);
3472 priv->hw_unavailable--;
3473 spin_unlock_irq(&priv->lock);
3474
3475 printk(KERN_DEBUG "%s: ready\n", dev->name);
3476
3477 out:
3478 return err;
3479}
3480
3481struct net_device
3482*alloc_orinocodev(int sizeof_card,
3483 struct device *device,
3484 int (*hard_reset)(struct orinoco_private *),
3485 int (*stop_fw)(struct orinoco_private *, int))
3486{
3487 struct net_device *dev;
3488 struct orinoco_private *priv;
3489
3490 dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
3491 if (! dev)
3492 return NULL;
3493 priv = netdev_priv(dev);
3494 priv->ndev = dev;
3495 if (sizeof_card)
3496 priv->card = (void *)((unsigned long)priv
3497 + sizeof(struct orinoco_private));
3498 else
3499 priv->card = NULL;
3500 priv->dev = device;
3501
3502 /* Setup / override net_device fields */
3503 dev->init = orinoco_init;
3504 dev->hard_start_xmit = orinoco_xmit;
3505 dev->tx_timeout = orinoco_tx_timeout;
3506 dev->watchdog_timeo = HZ; /* 1 second timeout */
3507 dev->get_stats = orinoco_get_stats;
3508 dev->ethtool_ops = &orinoco_ethtool_ops;
3509 dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
3510#ifdef WIRELESS_SPY
3511 priv->wireless_data.spy_data = &priv->spy_data;
3512 dev->wireless_data = &priv->wireless_data;
3513#endif
3514 dev->change_mtu = orinoco_change_mtu;
3515 dev->set_multicast_list = orinoco_set_multicast_list;
3516 /* we use the default eth_mac_addr for setting the MAC addr */
3517
3518 /* Reserve space in skb for the SNAP header */
3519 dev->hard_header_len += ENCAPS_OVERHEAD;
3520
3521 /* Set up default callbacks */
3522 dev->open = orinoco_open;
3523 dev->stop = orinoco_stop;
3524 priv->hard_reset = hard_reset;
3525 priv->stop_fw = stop_fw;
3526
3527 spin_lock_init(&priv->lock);
3528 priv->open = 0;
3529 priv->hw_unavailable = 1; /* orinoco_init() must clear this
3530 * before anything else touches the
3531 * hardware */
3532 INIT_WORK(&priv->reset_work, orinoco_reset);
3533 INIT_WORK(&priv->join_work, orinoco_join_ap);
3534 INIT_WORK(&priv->wevent_work, orinoco_send_wevents);
3535
3536 INIT_LIST_HEAD(&priv->rx_list);
3537 tasklet_init(&priv->rx_tasklet, orinoco_rx_isr_tasklet,
3538 (unsigned long) dev);
3539
3540 netif_carrier_off(dev);
3541 priv->last_linkstatus = 0xffff;
3542
3543 priv->cached_fw = NULL;
3544
3545 return dev;
3546}
3547
3548void free_orinocodev(struct net_device *dev)
3549{
3550 struct orinoco_private *priv = netdev_priv(dev);
3551
3552 /* No need to empty priv->rx_list: if the tasklet is scheduled
3553 * when we call tasklet_kill it will run one final time,
3554 * emptying the list */
3555 tasklet_kill(&priv->rx_tasklet);
3556 if (priv->cached_fw)
3557 release_firmware(priv->cached_fw);
3558 priv->cached_fw = NULL;
3559 priv->wpa_ie_len = 0;
3560 kfree(priv->wpa_ie);
3561 orinoco_mic_free(priv);
3562 orinoco_bss_data_free(priv);
3563 free_netdev(dev);
3564}
3565
3566/********************************************************************/
3567/* Wireless extensions */
3568/********************************************************************/
3569
3570/* Return : < 0 -> error code ; >= 0 -> length */
3571static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
3572 char buf[IW_ESSID_MAX_SIZE+1])
3573{
3574 hermes_t *hw = &priv->hw;
3575 int err = 0;
3576 struct hermes_idstring essidbuf;
3577 char *p = (char *)(&essidbuf.val);
3578 int len;
3579 unsigned long flags;
3580
3581 if (orinoco_lock(priv, &flags) != 0)
3582 return -EBUSY;
3583
3584 if (strlen(priv->desired_essid) > 0) {
3585 /* We read the desired SSID from the hardware rather
3586 than from priv->desired_essid, just in case the
3587 firmware is allowed to change it on us. I'm not
3588 sure about this */
3589 /* My guess is that the OWNSSID should always be whatever
3590 * we set to the card, whereas CURRENT_SSID is the one that
3591 * may change... - Jean II */
3592 u16 rid;
3593
3594 *active = 1;
3595
3596 rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
3597 HERMES_RID_CNFDESIREDSSID;
3598
3599 err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
3600 NULL, &essidbuf);
3601 if (err)
3602 goto fail_unlock;
3603 } else {
3604 *active = 0;
3605
3606 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
3607 sizeof(essidbuf), NULL, &essidbuf);
3608 if (err)
3609 goto fail_unlock;
3610 }
3611
3612 len = le16_to_cpu(essidbuf.len);
3613 BUG_ON(len > IW_ESSID_MAX_SIZE);
3614
3615 memset(buf, 0, IW_ESSID_MAX_SIZE);
3616 memcpy(buf, p, len);
3617 err = len;
3618
3619 fail_unlock:
3620 orinoco_unlock(priv, &flags);
3621
3622 return err;
3623}
3624
3625static long orinoco_hw_get_freq(struct orinoco_private *priv)
3626{
3627
3628 hermes_t *hw = &priv->hw;
3629 int err = 0;
3630 u16 channel;
3631 long freq = 0;
3632 unsigned long flags;
3633
3634 if (orinoco_lock(priv, &flags) != 0)
3635 return -EBUSY;
3636
3637 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
3638 if (err)
3639 goto out;
3640
3641 /* Intersil firmware 1.3.5 returns 0 when the interface is down */
3642 if (channel == 0) {
3643 err = -EBUSY;
3644 goto out;
3645 }
3646
3647 if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
3648 printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
3649 priv->ndev->name, channel);
3650 err = -EBUSY;
3651 goto out;
3652
3653 }
3654 freq = channel_frequency[channel-1] * 100000;
3655
3656 out:
3657 orinoco_unlock(priv, &flags);
3658
3659 if (err > 0)
3660 err = -EBUSY;
3661 return err ? err : freq;
3662}
3663
3664static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
3665 int *numrates, s32 *rates, int max)
3666{
3667 hermes_t *hw = &priv->hw;
3668 struct hermes_idstring list;
3669 unsigned char *p = (unsigned char *)&list.val;
3670 int err = 0;
3671 int num;
3672 int i;
3673 unsigned long flags;
3674
3675 if (orinoco_lock(priv, &flags) != 0)
3676 return -EBUSY;
3677
3678 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
3679 sizeof(list), NULL, &list);
3680 orinoco_unlock(priv, &flags);
3681
3682 if (err)
3683 return err;
3684
3685 num = le16_to_cpu(list.len);
3686 *numrates = num;
3687 num = min(num, max);
3688
3689 for (i = 0; i < num; i++) {
3690 rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
3691 }
3692
3693 return 0;
3694}
3695
3696static int orinoco_ioctl_getname(struct net_device *dev,
3697 struct iw_request_info *info,
3698 char *name,
3699 char *extra)
3700{
3701 struct orinoco_private *priv = netdev_priv(dev);
3702 int numrates;
3703 int err;
3704
3705 err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
3706
3707 if (!err && (numrates > 2))
3708 strcpy(name, "IEEE 802.11b");
3709 else
3710 strcpy(name, "IEEE 802.11-DS");
3711
3712 return 0;
3713}
3714
3715static int orinoco_ioctl_setwap(struct net_device *dev,
3716 struct iw_request_info *info,
3717 struct sockaddr *ap_addr,
3718 char *extra)
3719{
3720 struct orinoco_private *priv = netdev_priv(dev);
3721 int err = -EINPROGRESS; /* Call commit handler */
3722 unsigned long flags;
3723 static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
3724 static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
3725
3726 if (orinoco_lock(priv, &flags) != 0)
3727 return -EBUSY;
3728
3729 /* Enable automatic roaming - no sanity checks are needed */
3730 if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 ||
3731 memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) {
3732 priv->bssid_fixed = 0;
3733 memset(priv->desired_bssid, 0, ETH_ALEN);
3734
3735 /* "off" means keep existing connection */
3736 if (ap_addr->sa_data[0] == 0) {
3737 __orinoco_hw_set_wap(priv);
3738 err = 0;
3739 }
3740 goto out;
3741 }
3742
3743 if (priv->firmware_type == FIRMWARE_TYPE_AGERE) {
3744 printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't "
3745 "support manual roaming\n",
3746 dev->name);
3747 err = -EOPNOTSUPP;
3748 goto out;
3749 }
3750
3751 if (priv->iw_mode != IW_MODE_INFRA) {
3752 printk(KERN_WARNING "%s: Manual roaming supported only in "
3753 "managed mode\n", dev->name);
3754 err = -EOPNOTSUPP;
3755 goto out;
3756 }
3757
3758 /* Intersil firmware hangs without Desired ESSID */
3759 if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL &&
3760 strlen(priv->desired_essid) == 0) {
3761 printk(KERN_WARNING "%s: Desired ESSID must be set for "
3762 "manual roaming\n", dev->name);
3763 err = -EOPNOTSUPP;
3764 goto out;
3765 }
3766
3767 /* Finally, enable manual roaming */
3768 priv->bssid_fixed = 1;
3769 memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN);
3770
3771 out:
3772 orinoco_unlock(priv, &flags);
3773 return err;
3774}
3775
3776static int orinoco_ioctl_getwap(struct net_device *dev,
3777 struct iw_request_info *info,
3778 struct sockaddr *ap_addr,
3779 char *extra)
3780{
3781 struct orinoco_private *priv = netdev_priv(dev);
3782
3783 hermes_t *hw = &priv->hw;
3784 int err = 0;
3785 unsigned long flags;
3786
3787 if (orinoco_lock(priv, &flags) != 0)
3788 return -EBUSY;
3789
3790 ap_addr->sa_family = ARPHRD_ETHER;
3791 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
3792 ETH_ALEN, NULL, ap_addr->sa_data);
3793
3794 orinoco_unlock(priv, &flags);
3795
3796 return err;
3797}
3798
3799static int orinoco_ioctl_setmode(struct net_device *dev,
3800 struct iw_request_info *info,
3801 u32 *mode,
3802 char *extra)
3803{
3804 struct orinoco_private *priv = netdev_priv(dev);
3805 int err = -EINPROGRESS; /* Call commit handler */
3806 unsigned long flags;
3807
3808 if (priv->iw_mode == *mode)
3809 return 0;
3810
3811 if (orinoco_lock(priv, &flags) != 0)
3812 return -EBUSY;
3813
3814 switch (*mode) {
3815 case IW_MODE_ADHOC:
3816 if (!priv->has_ibss && !priv->has_port3)
3817 err = -EOPNOTSUPP;
3818 break;
3819
3820 case IW_MODE_INFRA:
3821 break;
3822
3823 case IW_MODE_MONITOR:
3824 if (priv->broken_monitor && !force_monitor) {
3825 printk(KERN_WARNING "%s: Monitor mode support is "
3826 "buggy in this firmware, not enabling\n",
3827 dev->name);
3828 err = -EOPNOTSUPP;
3829 }
3830 break;
3831
3832 default:
3833 err = -EOPNOTSUPP;
3834 break;
3835 }
3836
3837 if (err == -EINPROGRESS) {
3838 priv->iw_mode = *mode;
3839 set_port_type(priv);
3840 }
3841
3842 orinoco_unlock(priv, &flags);
3843
3844 return err;
3845}
3846
3847static int orinoco_ioctl_getmode(struct net_device *dev,
3848 struct iw_request_info *info,
3849 u32 *mode,
3850 char *extra)
3851{
3852 struct orinoco_private *priv = netdev_priv(dev);
3853
3854 *mode = priv->iw_mode;
3855 return 0;
3856}
3857
3858static int orinoco_ioctl_getiwrange(struct net_device *dev,
3859 struct iw_request_info *info,
3860 struct iw_point *rrq,
3861 char *extra)
3862{
3863 struct orinoco_private *priv = netdev_priv(dev);
3864 int err = 0;
3865 struct iw_range *range = (struct iw_range *) extra;
3866 int numrates;
3867 int i, k;
3868
3869 rrq->length = sizeof(struct iw_range);
3870 memset(range, 0, sizeof(struct iw_range));
3871
3872 range->we_version_compiled = WIRELESS_EXT;
3873 range->we_version_source = 22;
3874
3875 /* Set available channels/frequencies */
3876 range->num_channels = NUM_CHANNELS;
3877 k = 0;
3878 for (i = 0; i < NUM_CHANNELS; i++) {
3879 if (priv->channel_mask & (1 << i)) {
3880 range->freq[k].i = i + 1;
3881 range->freq[k].m = channel_frequency[i] * 100000;
3882 range->freq[k].e = 1;
3883 k++;
3884 }
3885
3886 if (k >= IW_MAX_FREQUENCIES)
3887 break;
3888 }
3889 range->num_frequency = k;
3890 range->sensitivity = 3;
3891
3892 if (priv->has_wep) {
3893 range->max_encoding_tokens = ORINOCO_MAX_KEYS;
3894 range->encoding_size[0] = SMALL_KEY_SIZE;
3895 range->num_encoding_sizes = 1;
3896
3897 if (priv->has_big_wep) {
3898 range->encoding_size[1] = LARGE_KEY_SIZE;
3899 range->num_encoding_sizes = 2;
3900 }
3901 }
3902
3903 if (priv->has_wpa)
3904 range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
3905
3906 if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))){
3907 /* Quality stats meaningless in ad-hoc mode */
3908 } else {
3909 range->max_qual.qual = 0x8b - 0x2f;
3910 range->max_qual.level = 0x2f - 0x95 - 1;
3911 range->max_qual.noise = 0x2f - 0x95 - 1;
3912 /* Need to get better values */
3913 range->avg_qual.qual = 0x24;
3914 range->avg_qual.level = 0xC2;
3915 range->avg_qual.noise = 0x9E;
3916 }
3917
3918 err = orinoco_hw_get_bitratelist(priv, &numrates,
3919 range->bitrate, IW_MAX_BITRATES);
3920 if (err)
3921 return err;
3922 range->num_bitrates = numrates;
3923
3924 /* Set an indication of the max TCP throughput in bit/s that we can
3925 * expect using this interface. May be use for QoS stuff...
3926 * Jean II */
3927 if (numrates > 2)
3928 range->throughput = 5 * 1000 * 1000; /* ~5 Mb/s */
3929 else
3930 range->throughput = 1.5 * 1000 * 1000; /* ~1.5 Mb/s */
3931
3932 range->min_rts = 0;
3933 range->max_rts = 2347;
3934 range->min_frag = 256;
3935 range->max_frag = 2346;
3936
3937 range->min_pmp = 0;
3938 range->max_pmp = 65535000;
3939 range->min_pmt = 0;
3940 range->max_pmt = 65535 * 1000; /* ??? */
3941 range->pmp_flags = IW_POWER_PERIOD;
3942 range->pmt_flags = IW_POWER_TIMEOUT;
3943 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
3944
3945 range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
3946 range->retry_flags = IW_RETRY_LIMIT;
3947 range->r_time_flags = IW_RETRY_LIFETIME;
3948 range->min_retry = 0;
3949 range->max_retry = 65535; /* ??? */
3950 range->min_r_time = 0;
3951 range->max_r_time = 65535 * 1000; /* ??? */
3952
3953 if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
3954 range->scan_capa = IW_SCAN_CAPA_ESSID;
3955 else
3956 range->scan_capa = IW_SCAN_CAPA_NONE;
3957
3958 /* Event capability (kernel) */
3959 IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
3960 /* Event capability (driver) */
3961 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
3962 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
3963 IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
3964 IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
3965
3966 return 0;
3967}
3968
3969static int orinoco_ioctl_setiwencode(struct net_device *dev,
3970 struct iw_request_info *info,
3971 struct iw_point *erq,
3972 char *keybuf)
3973{
3974 struct orinoco_private *priv = netdev_priv(dev);
3975 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
3976 int setindex = priv->tx_key;
3977 int encode_alg = priv->encode_alg;
3978 int restricted = priv->wep_restrict;
3979 u16 xlen = 0;
3980 int err = -EINPROGRESS; /* Call commit handler */
3981 unsigned long flags;
3982
3983 if (! priv->has_wep)
3984 return -EOPNOTSUPP;
3985
3986 if (erq->pointer) {
3987 /* We actually have a key to set - check its length */
3988 if (erq->length > LARGE_KEY_SIZE)
3989 return -E2BIG;
3990
3991 if ( (erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep )
3992 return -E2BIG;
3993 }
3994
3995 if (orinoco_lock(priv, &flags) != 0)
3996 return -EBUSY;
3997
3998 /* Clear any TKIP key we have */
3999 if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_ALG_TKIP))
4000 (void) orinoco_clear_tkip_key(priv, setindex);
4001
4002 if (erq->length > 0) {
4003 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
4004 index = priv->tx_key;
4005
4006 /* Adjust key length to a supported value */
4007 if (erq->length > SMALL_KEY_SIZE) {
4008 xlen = LARGE_KEY_SIZE;
4009 } else if (erq->length > 0) {
4010 xlen = SMALL_KEY_SIZE;
4011 } else
4012 xlen = 0;
4013
4014 /* Switch on WEP if off */
4015 if ((encode_alg != IW_ENCODE_ALG_WEP) && (xlen > 0)) {
4016 setindex = index;
4017 encode_alg = IW_ENCODE_ALG_WEP;
4018 }
4019 } else {
4020 /* Important note : if the user do "iwconfig eth0 enc off",
4021 * we will arrive there with an index of -1. This is valid
4022 * but need to be taken care off... Jean II */
4023 if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) {
4024 if((index != -1) || (erq->flags == 0)) {
4025 err = -EINVAL;
4026 goto out;
4027 }
4028 } else {
4029 /* Set the index : Check that the key is valid */
4030 if(priv->keys[index].len == 0) {
4031 err = -EINVAL;
4032 goto out;
4033 }
4034 setindex = index;
4035 }
4036 }
4037
4038 if (erq->flags & IW_ENCODE_DISABLED)
4039 encode_alg = IW_ENCODE_ALG_NONE;
4040 if (erq->flags & IW_ENCODE_OPEN)
4041 restricted = 0;
4042 if (erq->flags & IW_ENCODE_RESTRICTED)
4043 restricted = 1;
4044
4045 if (erq->pointer && erq->length > 0) {
4046 priv->keys[index].len = cpu_to_le16(xlen);
4047 memset(priv->keys[index].data, 0,
4048 sizeof(priv->keys[index].data));
4049 memcpy(priv->keys[index].data, keybuf, erq->length);
4050 }
4051 priv->tx_key = setindex;
4052
4053 /* Try fast key change if connected and only keys are changed */
4054 if ((priv->encode_alg == encode_alg) &&
4055 (priv->wep_restrict == restricted) &&
4056 netif_carrier_ok(dev)) {
4057 err = __orinoco_hw_setup_wepkeys(priv);
4058 /* No need to commit if successful */
4059 goto out;
4060 }
4061
4062 priv->encode_alg = encode_alg;
4063 priv->wep_restrict = restricted;
4064
4065 out:
4066 orinoco_unlock(priv, &flags);
4067
4068 return err;
4069}
4070
4071static int orinoco_ioctl_getiwencode(struct net_device *dev,
4072 struct iw_request_info *info,
4073 struct iw_point *erq,
4074 char *keybuf)
4075{
4076 struct orinoco_private *priv = netdev_priv(dev);
4077 int index = (erq->flags & IW_ENCODE_INDEX) - 1;
4078 u16 xlen = 0;
4079 unsigned long flags;
4080
4081 if (! priv->has_wep)
4082 return -EOPNOTSUPP;
4083
4084 if (orinoco_lock(priv, &flags) != 0)
4085 return -EBUSY;
4086
4087 if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
4088 index = priv->tx_key;
4089
4090 erq->flags = 0;
4091 if (!priv->encode_alg)
4092 erq->flags |= IW_ENCODE_DISABLED;
4093 erq->flags |= index + 1;
4094
4095 if (priv->wep_restrict)
4096 erq->flags |= IW_ENCODE_RESTRICTED;
4097 else
4098 erq->flags |= IW_ENCODE_OPEN;
4099
4100 xlen = le16_to_cpu(priv->keys[index].len);
4101
4102 erq->length = xlen;
4103
4104 memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
4105
4106 orinoco_unlock(priv, &flags);
4107 return 0;
4108}
4109
4110static int orinoco_ioctl_setessid(struct net_device *dev,
4111 struct iw_request_info *info,
4112 struct iw_point *erq,
4113 char *essidbuf)
4114{
4115 struct orinoco_private *priv = netdev_priv(dev);
4116 unsigned long flags;
4117
4118 /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
4119 * anyway... - Jean II */
4120
4121 /* Hum... Should not use Wireless Extension constant (may change),
4122 * should use our own... - Jean II */
4123 if (erq->length > IW_ESSID_MAX_SIZE)
4124 return -E2BIG;
4125
4126 if (orinoco_lock(priv, &flags) != 0)
4127 return -EBUSY;
4128
4129 /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
4130 memset(priv->desired_essid, 0, sizeof(priv->desired_essid));
4131
4132 /* If not ANY, get the new ESSID */
4133 if (erq->flags) {
4134 memcpy(priv->desired_essid, essidbuf, erq->length);
4135 }
4136
4137 orinoco_unlock(priv, &flags);
4138
4139 return -EINPROGRESS; /* Call commit handler */
4140}
4141
4142static int orinoco_ioctl_getessid(struct net_device *dev,
4143 struct iw_request_info *info,
4144 struct iw_point *erq,
4145 char *essidbuf)
4146{
4147 struct orinoco_private *priv = netdev_priv(dev);
4148 int active;
4149 int err = 0;
4150 unsigned long flags;
4151
4152 if (netif_running(dev)) {
4153 err = orinoco_hw_get_essid(priv, &active, essidbuf);
4154 if (err < 0)
4155 return err;
4156 erq->length = err;
4157 } else {
4158 if (orinoco_lock(priv, &flags) != 0)
4159 return -EBUSY;
4160 memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE);
4161 erq->length = strlen(priv->desired_essid);
4162 orinoco_unlock(priv, &flags);
4163 }
4164
4165 erq->flags = 1;
4166
4167 return 0;
4168}
4169
4170static int orinoco_ioctl_setnick(struct net_device *dev,
4171 struct iw_request_info *info,
4172 struct iw_point *nrq,
4173 char *nickbuf)
4174{
4175 struct orinoco_private *priv = netdev_priv(dev);
4176 unsigned long flags;
4177
4178 if (nrq->length > IW_ESSID_MAX_SIZE)
4179 return -E2BIG;
4180
4181 if (orinoco_lock(priv, &flags) != 0)
4182 return -EBUSY;
4183
4184 memset(priv->nick, 0, sizeof(priv->nick));
4185 memcpy(priv->nick, nickbuf, nrq->length);
4186
4187 orinoco_unlock(priv, &flags);
4188
4189 return -EINPROGRESS; /* Call commit handler */
4190}
4191
4192static int orinoco_ioctl_getnick(struct net_device *dev,
4193 struct iw_request_info *info,
4194 struct iw_point *nrq,
4195 char *nickbuf)
4196{
4197 struct orinoco_private *priv = netdev_priv(dev);
4198 unsigned long flags;
4199
4200 if (orinoco_lock(priv, &flags) != 0)
4201 return -EBUSY;
4202
4203 memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE);
4204 orinoco_unlock(priv, &flags);
4205
4206 nrq->length = strlen(priv->nick);
4207
4208 return 0;
4209}
4210
4211static int orinoco_ioctl_setfreq(struct net_device *dev,
4212 struct iw_request_info *info,
4213 struct iw_freq *frq,
4214 char *extra)
4215{
4216 struct orinoco_private *priv = netdev_priv(dev);
4217 int chan = -1;
4218 unsigned long flags;
4219 int err = -EINPROGRESS; /* Call commit handler */
4220
4221 /* In infrastructure mode the AP sets the channel */
4222 if (priv->iw_mode == IW_MODE_INFRA)
4223 return -EBUSY;
4224
4225 if ( (frq->e == 0) && (frq->m <= 1000) ) {
4226 /* Setting by channel number */
4227 chan = frq->m;
4228 } else {
4229 /* Setting by frequency - search the table */
4230 int mult = 1;
4231 int i;
4232
4233 for (i = 0; i < (6 - frq->e); i++)
4234 mult *= 10;
4235
4236 for (i = 0; i < NUM_CHANNELS; i++)
4237 if (frq->m == (channel_frequency[i] * mult))
4238 chan = i+1;
4239 }
4240
4241 if ( (chan < 1) || (chan > NUM_CHANNELS) ||
4242 ! (priv->channel_mask & (1 << (chan-1)) ) )
4243 return -EINVAL;
4244
4245 if (orinoco_lock(priv, &flags) != 0)
4246 return -EBUSY;
4247
4248 priv->channel = chan;
4249 if (priv->iw_mode == IW_MODE_MONITOR) {
4250 /* Fast channel change - no commit if successful */
4251 hermes_t *hw = &priv->hw;
4252 err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
4253 HERMES_TEST_SET_CHANNEL,
4254 chan, NULL);
4255 }
4256 orinoco_unlock(priv, &flags);
4257
4258 return err;
4259}
4260
4261static int orinoco_ioctl_getfreq(struct net_device *dev,
4262 struct iw_request_info *info,
4263 struct iw_freq *frq,
4264 char *extra)
4265{
4266 struct orinoco_private *priv = netdev_priv(dev);
4267 int tmp;
4268
4269 /* Locking done in there */
4270 tmp = orinoco_hw_get_freq(priv);
4271 if (tmp < 0) {
4272 return tmp;
4273 }
4274
4275 frq->m = tmp;
4276 frq->e = 1;
4277
4278 return 0;
4279}
4280
4281static int orinoco_ioctl_getsens(struct net_device *dev,
4282 struct iw_request_info *info,
4283 struct iw_param *srq,
4284 char *extra)
4285{
4286 struct orinoco_private *priv = netdev_priv(dev);
4287 hermes_t *hw = &priv->hw;
4288 u16 val;
4289 int err;
4290 unsigned long flags;
4291
4292 if (!priv->has_sensitivity)
4293 return -EOPNOTSUPP;
4294
4295 if (orinoco_lock(priv, &flags) != 0)
4296 return -EBUSY;
4297 err = hermes_read_wordrec(hw, USER_BAP,
4298 HERMES_RID_CNFSYSTEMSCALE, &val);
4299 orinoco_unlock(priv, &flags);
4300
4301 if (err)
4302 return err;
4303
4304 srq->value = val;
4305 srq->fixed = 0; /* auto */
4306
4307 return 0;
4308}
4309
4310static int orinoco_ioctl_setsens(struct net_device *dev,
4311 struct iw_request_info *info,
4312 struct iw_param *srq,
4313 char *extra)
4314{
4315 struct orinoco_private *priv = netdev_priv(dev);
4316 int val = srq->value;
4317 unsigned long flags;
4318
4319 if (!priv->has_sensitivity)
4320 return -EOPNOTSUPP;
4321
4322 if ((val < 1) || (val > 3))
4323 return -EINVAL;
4324
4325 if (orinoco_lock(priv, &flags) != 0)
4326 return -EBUSY;
4327 priv->ap_density = val;
4328 orinoco_unlock(priv, &flags);
4329
4330 return -EINPROGRESS; /* Call commit handler */
4331}
4332
4333static int orinoco_ioctl_setrts(struct net_device *dev,
4334 struct iw_request_info *info,
4335 struct iw_param *rrq,
4336 char *extra)
4337{
4338 struct orinoco_private *priv = netdev_priv(dev);
4339 int val = rrq->value;
4340 unsigned long flags;
4341
4342 if (rrq->disabled)
4343 val = 2347;
4344
4345 if ( (val < 0) || (val > 2347) )
4346 return -EINVAL;
4347
4348 if (orinoco_lock(priv, &flags) != 0)
4349 return -EBUSY;
4350
4351 priv->rts_thresh = val;
4352 orinoco_unlock(priv, &flags);
4353
4354 return -EINPROGRESS; /* Call commit handler */
4355}
4356
4357static int orinoco_ioctl_getrts(struct net_device *dev,
4358 struct iw_request_info *info,
4359 struct iw_param *rrq,
4360 char *extra)
4361{
4362 struct orinoco_private *priv = netdev_priv(dev);
4363
4364 rrq->value = priv->rts_thresh;
4365 rrq->disabled = (rrq->value == 2347);
4366 rrq->fixed = 1;
4367
4368 return 0;
4369}
4370
4371static int orinoco_ioctl_setfrag(struct net_device *dev,
4372 struct iw_request_info *info,
4373 struct iw_param *frq,
4374 char *extra)
4375{
4376 struct orinoco_private *priv = netdev_priv(dev);
4377 int err = -EINPROGRESS; /* Call commit handler */
4378 unsigned long flags;
4379
4380 if (orinoco_lock(priv, &flags) != 0)
4381 return -EBUSY;
4382
4383 if (priv->has_mwo) {
4384 if (frq->disabled)
4385 priv->mwo_robust = 0;
4386 else {
4387 if (frq->fixed)
4388 printk(KERN_WARNING "%s: Fixed fragmentation is "
4389 "not supported on this firmware. "
4390 "Using MWO robust instead.\n", dev->name);
4391 priv->mwo_robust = 1;
4392 }
4393 } else {
4394 if (frq->disabled)
4395 priv->frag_thresh = 2346;
4396 else {
4397 if ( (frq->value < 256) || (frq->value > 2346) )
4398 err = -EINVAL;
4399 else
4400 priv->frag_thresh = frq->value & ~0x1; /* must be even */
4401 }
4402 }
4403
4404 orinoco_unlock(priv, &flags);
4405
4406 return err;
4407}
4408
4409static int orinoco_ioctl_getfrag(struct net_device *dev,
4410 struct iw_request_info *info,
4411 struct iw_param *frq,
4412 char *extra)
4413{
4414 struct orinoco_private *priv = netdev_priv(dev);
4415 hermes_t *hw = &priv->hw;
4416 int err;
4417 u16 val;
4418 unsigned long flags;
4419
4420 if (orinoco_lock(priv, &flags) != 0)
4421 return -EBUSY;
4422
4423 if (priv->has_mwo) {
4424 err = hermes_read_wordrec(hw, USER_BAP,
4425 HERMES_RID_CNFMWOROBUST_AGERE,
4426 &val);
4427 if (err)
4428 val = 0;
4429
4430 frq->value = val ? 2347 : 0;
4431 frq->disabled = ! val;
4432 frq->fixed = 0;
4433 } else {
4434 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFFRAGMENTATIONTHRESHOLD,
4435 &val);
4436 if (err)
4437 val = 0;
4438
4439 frq->value = val;
4440 frq->disabled = (val >= 2346);
4441 frq->fixed = 1;
4442 }
4443
4444 orinoco_unlock(priv, &flags);
4445
4446 return err;
4447}
4448
4449static int orinoco_ioctl_setrate(struct net_device *dev,
4450 struct iw_request_info *info,
4451 struct iw_param *rrq,
4452 char *extra)
4453{
4454 struct orinoco_private *priv = netdev_priv(dev);
4455 int ratemode = -1;
4456 int bitrate; /* 100s of kilobits */
4457 int i;
4458 unsigned long flags;
4459
4460 /* As the user space doesn't know our highest rate, it uses -1
4461 * to ask us to set the highest rate. Test it using "iwconfig
4462 * ethX rate auto" - Jean II */
4463 if (rrq->value == -1)
4464 bitrate = 110;
4465 else {
4466 if (rrq->value % 100000)
4467 return -EINVAL;
4468 bitrate = rrq->value / 100000;
4469 }
4470
4471 if ( (bitrate != 10) && (bitrate != 20) &&
4472 (bitrate != 55) && (bitrate != 110) )
4473 return -EINVAL;
4474
4475 for (i = 0; i < BITRATE_TABLE_SIZE; i++)
4476 if ( (bitrate_table[i].bitrate == bitrate) &&
4477 (bitrate_table[i].automatic == ! rrq->fixed) ) {
4478 ratemode = i;
4479 break;
4480 }
4481
4482 if (ratemode == -1)
4483 return -EINVAL;
4484
4485 if (orinoco_lock(priv, &flags) != 0)
4486 return -EBUSY;
4487 priv->bitratemode = ratemode;
4488 orinoco_unlock(priv, &flags);
4489
4490 return -EINPROGRESS;
4491}
4492
4493static int orinoco_ioctl_getrate(struct net_device *dev,
4494 struct iw_request_info *info,
4495 struct iw_param *rrq,
4496 char *extra)
4497{
4498 struct orinoco_private *priv = netdev_priv(dev);
4499 hermes_t *hw = &priv->hw;
4500 int err = 0;
4501 int ratemode;
4502 int i;
4503 u16 val;
4504 unsigned long flags;
4505
4506 if (orinoco_lock(priv, &flags) != 0)
4507 return -EBUSY;
4508
4509 ratemode = priv->bitratemode;
4510
4511 BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
4512
4513 rrq->value = bitrate_table[ratemode].bitrate * 100000;
4514 rrq->fixed = ! bitrate_table[ratemode].automatic;
4515 rrq->disabled = 0;
4516
4517 /* If the interface is running we try to find more about the
4518 current mode */
4519 if (netif_running(dev)) {
4520 err = hermes_read_wordrec(hw, USER_BAP,
4521 HERMES_RID_CURRENTTXRATE, &val);
4522 if (err)
4523 goto out;
4524
4525 switch (priv->firmware_type) {
4526 case FIRMWARE_TYPE_AGERE: /* Lucent style rate */
4527 /* Note : in Lucent firmware, the return value of
4528 * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s,
4529 * and therefore is totally different from the
4530 * encoding of HERMES_RID_CNFTXRATECONTROL.
4531 * Don't forget that 6Mb/s is really 5.5Mb/s */
4532 if (val == 6)
4533 rrq->value = 5500000;
4534 else
4535 rrq->value = val * 1000000;
4536 break;
4537 case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
4538 case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
4539 for (i = 0; i < BITRATE_TABLE_SIZE; i++)
4540 if (bitrate_table[i].intersil_txratectrl == val) {
4541 ratemode = i;
4542 break;
4543 }
4544 if (i >= BITRATE_TABLE_SIZE)
4545 printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n",
4546 dev->name, val);
4547
4548 rrq->value = bitrate_table[ratemode].bitrate * 100000;
4549 break;
4550 default:
4551 BUG();
4552 }
4553 }
4554
4555 out:
4556 orinoco_unlock(priv, &flags);
4557
4558 return err;
4559}
4560
4561static int orinoco_ioctl_setpower(struct net_device *dev,
4562 struct iw_request_info *info,
4563 struct iw_param *prq,
4564 char *extra)
4565{
4566 struct orinoco_private *priv = netdev_priv(dev);
4567 int err = -EINPROGRESS; /* Call commit handler */
4568 unsigned long flags;
4569
4570 if (orinoco_lock(priv, &flags) != 0)
4571 return -EBUSY;
4572
4573 if (prq->disabled) {
4574 priv->pm_on = 0;
4575 } else {
4576 switch (prq->flags & IW_POWER_MODE) {
4577 case IW_POWER_UNICAST_R:
4578 priv->pm_mcast = 0;
4579 priv->pm_on = 1;
4580 break;
4581 case IW_POWER_ALL_R:
4582 priv->pm_mcast = 1;
4583 priv->pm_on = 1;
4584 break;
4585 case IW_POWER_ON:
4586 /* No flags : but we may have a value - Jean II */
4587 break;
4588 default:
4589 err = -EINVAL;
4590 goto out;
4591 }
4592
4593 if (prq->flags & IW_POWER_TIMEOUT) {
4594 priv->pm_on = 1;
4595 priv->pm_timeout = prq->value / 1000;
4596 }
4597 if (prq->flags & IW_POWER_PERIOD) {
4598 priv->pm_on = 1;
4599 priv->pm_period = prq->value / 1000;
4600 }
4601 /* It's valid to not have a value if we are just toggling
4602 * the flags... Jean II */
4603 if(!priv->pm_on) {
4604 err = -EINVAL;
4605 goto out;
4606 }
4607 }
4608
4609 out:
4610 orinoco_unlock(priv, &flags);
4611
4612 return err;
4613}
4614
4615static int orinoco_ioctl_getpower(struct net_device *dev,
4616 struct iw_request_info *info,
4617 struct iw_param *prq,
4618 char *extra)
4619{
4620 struct orinoco_private *priv = netdev_priv(dev);
4621 hermes_t *hw = &priv->hw;
4622 int err = 0;
4623 u16 enable, period, timeout, mcast;
4624 unsigned long flags;
4625
4626 if (orinoco_lock(priv, &flags) != 0)
4627 return -EBUSY;
4628
4629 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, &enable);
4630 if (err)
4631 goto out;
4632
4633 err = hermes_read_wordrec(hw, USER_BAP,
4634 HERMES_RID_CNFMAXSLEEPDURATION, &period);
4635 if (err)
4636 goto out;
4637
4638 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMHOLDOVERDURATION, &timeout);
4639 if (err)
4640 goto out;
4641
4642 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFMULTICASTRECEIVE, &mcast);
4643 if (err)
4644 goto out;
4645
4646 prq->disabled = !enable;
4647 /* Note : by default, display the period */
4648 if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
4649 prq->flags = IW_POWER_TIMEOUT;
4650 prq->value = timeout * 1000;
4651 } else {
4652 prq->flags = IW_POWER_PERIOD;
4653 prq->value = period * 1000;
4654 }
4655 if (mcast)
4656 prq->flags |= IW_POWER_ALL_R;
4657 else
4658 prq->flags |= IW_POWER_UNICAST_R;
4659
4660 out:
4661 orinoco_unlock(priv, &flags);
4662
4663 return err;
4664}
4665
4666static int orinoco_ioctl_set_encodeext(struct net_device *dev,
4667 struct iw_request_info *info,
4668 union iwreq_data *wrqu,
4669 char *extra)
4670{
4671 struct orinoco_private *priv = netdev_priv(dev);
4672 struct iw_point *encoding = &wrqu->encoding;
4673 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
4674 int idx, alg = ext->alg, set_key = 1;
4675 unsigned long flags;
4676 int err = -EINVAL;
4677 u16 key_len;
4678
4679 if (orinoco_lock(priv, &flags) != 0)
4680 return -EBUSY;
4681
4682 /* Determine and validate the key index */
4683 idx = encoding->flags & IW_ENCODE_INDEX;
4684 if (idx) {
4685 if ((idx < 1) || (idx > 4))
4686 goto out;
4687 idx--;
4688 } else
4689 idx = priv->tx_key;
4690
4691 if (encoding->flags & IW_ENCODE_DISABLED)
4692 alg = IW_ENCODE_ALG_NONE;
4693
4694 if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) {
4695 /* Clear any TKIP TX key we had */
4696 (void) orinoco_clear_tkip_key(priv, priv->tx_key);
4697 }
4698
4699 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
4700 priv->tx_key = idx;
4701 set_key = ((alg == IW_ENCODE_ALG_TKIP) ||
4702 (ext->key_len > 0)) ? 1 : 0;
4703 }
4704
4705 if (set_key) {
4706 /* Set the requested key first */
4707 switch (alg) {
4708 case IW_ENCODE_ALG_NONE:
4709 priv->encode_alg = alg;
4710 priv->keys[idx].len = 0;
4711 break;
4712
4713 case IW_ENCODE_ALG_WEP:
4714 if (ext->key_len > SMALL_KEY_SIZE)
4715 key_len = LARGE_KEY_SIZE;
4716 else if (ext->key_len > 0)
4717 key_len = SMALL_KEY_SIZE;
4718 else
4719 goto out;
4720
4721 priv->encode_alg = alg;
4722 priv->keys[idx].len = cpu_to_le16(key_len);
4723
4724 key_len = min(ext->key_len, key_len);
4725
4726 memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
4727 memcpy(priv->keys[idx].data, ext->key, key_len);
4728 break;
4729
4730 case IW_ENCODE_ALG_TKIP:
4731 {
4732 hermes_t *hw = &priv->hw;
4733 u8 *tkip_iv = NULL;
4734
4735 if (!priv->has_wpa ||
4736 (ext->key_len > sizeof(priv->tkip_key[0])))
4737 goto out;
4738
4739 priv->encode_alg = alg;
4740 memset(&priv->tkip_key[idx], 0,
4741 sizeof(priv->tkip_key[idx]));
4742 memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
4743
4744 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
4745 tkip_iv = &ext->rx_seq[0];
4746
4747 err = __orinoco_hw_set_tkip_key(hw, idx,
4748 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
4749 (u8 *) &priv->tkip_key[idx],
4750 tkip_iv, NULL);
4751 if (err)
4752 printk(KERN_ERR "%s: Error %d setting TKIP key"
4753 "\n", dev->name, err);
4754
4755 goto out;
4756 }
4757 default:
4758 goto out;
4759 }
4760 }
4761 err = -EINPROGRESS;
4762 out:
4763 orinoco_unlock(priv, &flags);
4764
4765 return err;
4766}
4767
4768static int orinoco_ioctl_get_encodeext(struct net_device *dev,
4769 struct iw_request_info *info,
4770 union iwreq_data *wrqu,
4771 char *extra)
4772{
4773 struct orinoco_private *priv = netdev_priv(dev);
4774 struct iw_point *encoding = &wrqu->encoding;
4775 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
4776 int idx, max_key_len;
4777 unsigned long flags;
4778 int err;
4779
4780 if (orinoco_lock(priv, &flags) != 0)
4781 return -EBUSY;
4782
4783 err = -EINVAL;
4784 max_key_len = encoding->length - sizeof(*ext);
4785 if (max_key_len < 0)
4786 goto out;
4787
4788 idx = encoding->flags & IW_ENCODE_INDEX;
4789 if (idx) {
4790 if ((idx < 1) || (idx > 4))
4791 goto out;
4792 idx--;
4793 } else
4794 idx = priv->tx_key;
4795
4796 encoding->flags = idx + 1;
4797 memset(ext, 0, sizeof(*ext));
4798
4799 ext->alg = priv->encode_alg;
4800 switch (priv->encode_alg) {
4801 case IW_ENCODE_ALG_NONE:
4802 ext->key_len = 0;
4803 encoding->flags |= IW_ENCODE_DISABLED;
4804 break;
4805 case IW_ENCODE_ALG_WEP:
4806 ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
4807 max_key_len);
4808 memcpy(ext->key, priv->keys[idx].data, ext->key_len);
4809 encoding->flags |= IW_ENCODE_ENABLED;
4810 break;
4811 case IW_ENCODE_ALG_TKIP:
4812 ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
4813 max_key_len);
4814 memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
4815 encoding->flags |= IW_ENCODE_ENABLED;
4816 break;
4817 }
4818
4819 err = 0;
4820 out:
4821 orinoco_unlock(priv, &flags);
4822
4823 return err;
4824}
4825
4826static int orinoco_ioctl_set_auth(struct net_device *dev,
4827 struct iw_request_info *info,
4828 union iwreq_data *wrqu, char *extra)
4829{
4830 struct orinoco_private *priv = netdev_priv(dev);
4831 hermes_t *hw = &priv->hw;
4832 struct iw_param *param = &wrqu->param;
4833 unsigned long flags;
4834 int ret = -EINPROGRESS;
4835
4836 if (orinoco_lock(priv, &flags) != 0)
4837 return -EBUSY;
4838
4839 switch (param->flags & IW_AUTH_INDEX) {
4840 case IW_AUTH_WPA_VERSION:
4841 case IW_AUTH_CIPHER_PAIRWISE:
4842 case IW_AUTH_CIPHER_GROUP:
4843 case IW_AUTH_RX_UNENCRYPTED_EAPOL:
4844 case IW_AUTH_PRIVACY_INVOKED:
4845 case IW_AUTH_DROP_UNENCRYPTED:
4846 /*
4847 * orinoco does not use these parameters
4848 */
4849 break;
4850
4851 case IW_AUTH_KEY_MGMT:
4852 /* wl_lkm implies value 2 == PSK for Hermes I
4853 * which ties in with WEXT
4854 * no other hints tho :(
4855 */
4856 priv->key_mgmt = param->value;
4857 break;
4858
4859 case IW_AUTH_TKIP_COUNTERMEASURES:
4860 /* When countermeasures are enabled, shut down the
4861 * card; when disabled, re-enable the card. This must
4862 * take effect immediately.
4863 *
4864 * TODO: Make sure that the EAPOL message is getting
4865 * out before card disabled
4866 */
4867 if (param->value) {
4868 priv->tkip_cm_active = 1;
4869 ret = hermes_enable_port(hw, 0);
4870 } else {
4871 priv->tkip_cm_active = 0;
4872 ret = hermes_disable_port(hw, 0);
4873 }
4874 break;
4875
4876 case IW_AUTH_80211_AUTH_ALG:
4877 if (param->value & IW_AUTH_ALG_SHARED_KEY)
4878 priv->wep_restrict = 1;
4879 else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM)
4880 priv->wep_restrict = 0;
4881 else
4882 ret = -EINVAL;
4883 break;
4884
4885 case IW_AUTH_WPA_ENABLED:
4886 if (priv->has_wpa) {
4887 priv->wpa_enabled = param->value ? 1 : 0;
4888 } else {
4889 if (param->value)
4890 ret = -EOPNOTSUPP;
4891 /* else silently accept disable of WPA */
4892 priv->wpa_enabled = 0;
4893 }
4894 break;
4895
4896 default:
4897 ret = -EOPNOTSUPP;
4898 }
4899
4900 orinoco_unlock(priv, &flags);
4901 return ret;
4902}
4903
4904static int orinoco_ioctl_get_auth(struct net_device *dev,
4905 struct iw_request_info *info,
4906 union iwreq_data *wrqu, char *extra)
4907{
4908 struct orinoco_private *priv = netdev_priv(dev);
4909 struct iw_param *param = &wrqu->param;
4910 unsigned long flags;
4911 int ret = 0;
4912
4913 if (orinoco_lock(priv, &flags) != 0)
4914 return -EBUSY;
4915
4916 switch (param->flags & IW_AUTH_INDEX) {
4917 case IW_AUTH_KEY_MGMT:
4918 param->value = priv->key_mgmt;
4919 break;
4920
4921 case IW_AUTH_TKIP_COUNTERMEASURES:
4922 param->value = priv->tkip_cm_active;
4923 break;
4924
4925 case IW_AUTH_80211_AUTH_ALG:
4926 if (priv->wep_restrict)
4927 param->value = IW_AUTH_ALG_SHARED_KEY;
4928 else
4929 param->value = IW_AUTH_ALG_OPEN_SYSTEM;
4930 break;
4931
4932 case IW_AUTH_WPA_ENABLED:
4933 param->value = priv->wpa_enabled;
4934 break;
4935
4936 default:
4937 ret = -EOPNOTSUPP;
4938 }
4939
4940 orinoco_unlock(priv, &flags);
4941 return ret;
4942}
4943
4944static int orinoco_ioctl_set_genie(struct net_device *dev,
4945 struct iw_request_info *info,
4946 union iwreq_data *wrqu, char *extra)
4947{
4948 struct orinoco_private *priv = netdev_priv(dev);
4949 u8 *buf;
4950 unsigned long flags;
4951 int err = 0;
4952
4953 /* cut off at IEEE80211_MAX_DATA_LEN */
4954 if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) ||
4955 (wrqu->data.length && (extra == NULL)))
4956 return -EINVAL;
4957
4958 if (orinoco_lock(priv, &flags) != 0)
4959 return -EBUSY;
4960
4961 if (wrqu->data.length) {
4962 buf = kmalloc(wrqu->data.length, GFP_KERNEL);
4963 if (buf == NULL) {
4964 err = -ENOMEM;
4965 goto out;
4966 }
4967
4968 memcpy(buf, extra, wrqu->data.length);
4969 kfree(priv->wpa_ie);
4970 priv->wpa_ie = buf;
4971 priv->wpa_ie_len = wrqu->data.length;
4972 } else {
4973 kfree(priv->wpa_ie);
4974 priv->wpa_ie = NULL;
4975 priv->wpa_ie_len = 0;
4976 }
4977
4978 if (priv->wpa_ie) {
4979 /* Looks like wl_lkm wants to check the auth alg, and
4980 * somehow pass it to the firmware.
4981 * Instead it just calls the key mgmt rid
4982 * - we do this in set auth.
4983 */
4984 }
4985
4986out:
4987 orinoco_unlock(priv, &flags);
4988 return err;
4989}
4990
4991static int orinoco_ioctl_get_genie(struct net_device *dev,
4992 struct iw_request_info *info,
4993 union iwreq_data *wrqu, char *extra)
4994{
4995 struct orinoco_private *priv = netdev_priv(dev);
4996 unsigned long flags;
4997 int err = 0;
4998
4999 if (orinoco_lock(priv, &flags) != 0)
5000 return -EBUSY;
5001
5002 if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) {
5003 wrqu->data.length = 0;
5004 goto out;
5005 }
5006
5007 if (wrqu->data.length < priv->wpa_ie_len) {
5008 err = -E2BIG;
5009 goto out;
5010 }
5011
5012 wrqu->data.length = priv->wpa_ie_len;
5013 memcpy(extra, priv->wpa_ie, priv->wpa_ie_len);
5014
5015out:
5016 orinoco_unlock(priv, &flags);
5017 return err;
5018}
5019
5020static int orinoco_ioctl_set_mlme(struct net_device *dev,
5021 struct iw_request_info *info,
5022 union iwreq_data *wrqu, char *extra)
5023{
5024 struct orinoco_private *priv = netdev_priv(dev);
5025 hermes_t *hw = &priv->hw;
5026 struct iw_mlme *mlme = (struct iw_mlme *)extra;
5027 unsigned long flags;
5028 int ret = 0;
5029
5030 if (orinoco_lock(priv, &flags) != 0)
5031 return -EBUSY;
5032
5033 switch (mlme->cmd) {
5034 case IW_MLME_DEAUTH:
5035 /* silently ignore */
5036 break;
5037
5038 case IW_MLME_DISASSOC:
5039 {
5040 struct {
5041 u8 addr[ETH_ALEN];
5042 __le16 reason_code;
5043 } __attribute__ ((packed)) buf;
5044
5045 memcpy(buf.addr, mlme->addr.sa_data, ETH_ALEN);
5046 buf.reason_code = cpu_to_le16(mlme->reason_code);
5047 ret = HERMES_WRITE_RECORD(hw, USER_BAP,
5048 HERMES_RID_CNFDISASSOCIATE,
5049 &buf);
5050 break;
5051 }
5052 default:
5053 ret = -EOPNOTSUPP;
5054 }
5055
5056 orinoco_unlock(priv, &flags);
5057 return ret;
5058}
5059
5060static int orinoco_ioctl_getretry(struct net_device *dev,
5061 struct iw_request_info *info,
5062 struct iw_param *rrq,
5063 char *extra)
5064{
5065 struct orinoco_private *priv = netdev_priv(dev);
5066 hermes_t *hw = &priv->hw;
5067 int err = 0;
5068 u16 short_limit, long_limit, lifetime;
5069 unsigned long flags;
5070
5071 if (orinoco_lock(priv, &flags) != 0)
5072 return -EBUSY;
5073
5074 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT,
5075 &short_limit);
5076 if (err)
5077 goto out;
5078
5079 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT,
5080 &long_limit);
5081 if (err)
5082 goto out;
5083
5084 err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME,
5085 &lifetime);
5086 if (err)
5087 goto out;
5088
5089 rrq->disabled = 0; /* Can't be disabled */
5090
5091 /* Note : by default, display the retry number */
5092 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
5093 rrq->flags = IW_RETRY_LIFETIME;
5094 rrq->value = lifetime * 1000; /* ??? */
5095 } else {
5096 /* By default, display the min number */
5097 if ((rrq->flags & IW_RETRY_LONG)) {
5098 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG;
5099 rrq->value = long_limit;
5100 } else {
5101 rrq->flags = IW_RETRY_LIMIT;
5102 rrq->value = short_limit;
5103 if(short_limit != long_limit)
5104 rrq->flags |= IW_RETRY_SHORT;
5105 }
5106 }
5107
5108 out:
5109 orinoco_unlock(priv, &flags);
5110
5111 return err;
5112}
5113
5114static int orinoco_ioctl_reset(struct net_device *dev,
5115 struct iw_request_info *info,
5116 void *wrqu,
5117 char *extra)
5118{
5119 struct orinoco_private *priv = netdev_priv(dev);
5120
5121 if (! capable(CAP_NET_ADMIN))
5122 return -EPERM;
5123
5124 if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) {
5125 printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
5126
5127 /* Firmware reset */
5128 orinoco_reset(&priv->reset_work);
5129 } else {
5130 printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);
5131
5132 schedule_work(&priv->reset_work);
5133 }
5134
5135 return 0;
5136}
5137
5138static int orinoco_ioctl_setibssport(struct net_device *dev,
5139 struct iw_request_info *info,
5140 void *wrqu,
5141 char *extra)
5142
5143{
5144 struct orinoco_private *priv = netdev_priv(dev);
5145 int val = *( (int *) extra );
5146 unsigned long flags;
5147
5148 if (orinoco_lock(priv, &flags) != 0)
5149 return -EBUSY;
5150
5151 priv->ibss_port = val ;
5152
5153 /* Actually update the mode we are using */
5154 set_port_type(priv);
5155
5156 orinoco_unlock(priv, &flags);
5157 return -EINPROGRESS; /* Call commit handler */
5158}
5159
5160static int orinoco_ioctl_getibssport(struct net_device *dev,
5161 struct iw_request_info *info,
5162 void *wrqu,
5163 char *extra)
5164{
5165 struct orinoco_private *priv = netdev_priv(dev);
5166 int *val = (int *) extra;
5167
5168 *val = priv->ibss_port;
5169 return 0;
5170}
5171
5172static int orinoco_ioctl_setport3(struct net_device *dev,
5173 struct iw_request_info *info,
5174 void *wrqu,
5175 char *extra)
5176{
5177 struct orinoco_private *priv = netdev_priv(dev);
5178 int val = *( (int *) extra );
5179 int err = 0;
5180 unsigned long flags;
5181
5182 if (orinoco_lock(priv, &flags) != 0)
5183 return -EBUSY;
5184
5185 switch (val) {
5186 case 0: /* Try to do IEEE ad-hoc mode */
5187 if (! priv->has_ibss) {
5188 err = -EINVAL;
5189 break;
5190 }
5191 priv->prefer_port3 = 0;
5192
5193 break;
5194
5195 case 1: /* Try to do Lucent proprietary ad-hoc mode */
5196 if (! priv->has_port3) {
5197 err = -EINVAL;
5198 break;
5199 }
5200 priv->prefer_port3 = 1;
5201 break;
5202
5203 default:
5204 err = -EINVAL;
5205 }
5206
5207 if (! err) {
5208 /* Actually update the mode we are using */
5209 set_port_type(priv);
5210 err = -EINPROGRESS;
5211 }
5212
5213 orinoco_unlock(priv, &flags);
5214
5215 return err;
5216}
5217
5218static int orinoco_ioctl_getport3(struct net_device *dev,
5219 struct iw_request_info *info,
5220 void *wrqu,
5221 char *extra)
5222{
5223 struct orinoco_private *priv = netdev_priv(dev);
5224 int *val = (int *) extra;
5225
5226 *val = priv->prefer_port3;
5227 return 0;
5228}
5229
5230static int orinoco_ioctl_setpreamble(struct net_device *dev,
5231 struct iw_request_info *info,
5232 void *wrqu,
5233 char *extra)
5234{
5235 struct orinoco_private *priv = netdev_priv(dev);
5236 unsigned long flags;
5237 int val;
5238
5239 if (! priv->has_preamble)
5240 return -EOPNOTSUPP;
5241
5242 /* 802.11b has recently defined some short preamble.
5243 * Basically, the Phy header has been reduced in size.
5244 * This increase performance, especially at high rates
5245 * (the preamble is transmitted at 1Mb/s), unfortunately
5246 * this give compatibility troubles... - Jean II */
5247 val = *( (int *) extra );
5248
5249 if (orinoco_lock(priv, &flags) != 0)
5250 return -EBUSY;
5251
5252 if (val)
5253 priv->preamble = 1;
5254 else
5255 priv->preamble = 0;
5256
5257 orinoco_unlock(priv, &flags);
5258
5259 return -EINPROGRESS; /* Call commit handler */
5260}
5261
5262static int orinoco_ioctl_getpreamble(struct net_device *dev,
5263 struct iw_request_info *info,
5264 void *wrqu,
5265 char *extra)
5266{
5267 struct orinoco_private *priv = netdev_priv(dev);
5268 int *val = (int *) extra;
5269
5270 if (! priv->has_preamble)
5271 return -EOPNOTSUPP;
5272
5273 *val = priv->preamble;
5274 return 0;
5275}
5276
5277/* ioctl interface to hermes_read_ltv()
5278 * To use with iwpriv, pass the RID as the token argument, e.g.
5279 * iwpriv get_rid [0xfc00]
5280 * At least Wireless Tools 25 is required to use iwpriv.
5281 * For Wireless Tools 25 and 26 append "dummy" are the end. */
5282static int orinoco_ioctl_getrid(struct net_device *dev,
5283 struct iw_request_info *info,
5284 struct iw_point *data,
5285 char *extra)
5286{
5287 struct orinoco_private *priv = netdev_priv(dev);
5288 hermes_t *hw = &priv->hw;
5289 int rid = data->flags;
5290 u16 length;
5291 int err;
5292 unsigned long flags;
5293
5294 /* It's a "get" function, but we don't want users to access the
5295 * WEP key and other raw firmware data */
5296 if (! capable(CAP_NET_ADMIN))
5297 return -EPERM;
5298
5299 if (rid < 0xfc00 || rid > 0xffff)
5300 return -EINVAL;
5301
5302 if (orinoco_lock(priv, &flags) != 0)
5303 return -EBUSY;
5304
5305 err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length,
5306 extra);
5307 if (err)
5308 goto out;
5309
5310 data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length),
5311 MAX_RID_LEN);
5312
5313 out:
5314 orinoco_unlock(priv, &flags);
5315 return err;
5316}
5317
5318/* Trigger a scan (look for other cells in the vicinity) */
5319static int orinoco_ioctl_setscan(struct net_device *dev,
5320 struct iw_request_info *info,
5321 struct iw_point *srq,
5322 char *extra)
5323{
5324 struct orinoco_private *priv = netdev_priv(dev);
5325 hermes_t *hw = &priv->hw;
5326 struct iw_scan_req *si = (struct iw_scan_req *) extra;
5327 int err = 0;
5328 unsigned long flags;
5329
5330 /* Note : you may have realised that, as this is a SET operation,
5331 * this is privileged and therefore a normal user can't
5332 * perform scanning.
5333 * This is not an error, while the device perform scanning,
5334 * traffic doesn't flow, so it's a perfect DoS...
5335 * Jean II */
5336
5337 if (orinoco_lock(priv, &flags) != 0)
5338 return -EBUSY;
5339
5340 /* Scanning with port 0 disabled would fail */
5341 if (!netif_running(dev)) {
5342 err = -ENETDOWN;
5343 goto out;
5344 }
5345
5346 /* In monitor mode, the scan results are always empty.
5347 * Probe responses are passed to the driver as received
5348 * frames and could be processed in software. */
5349 if (priv->iw_mode == IW_MODE_MONITOR) {
5350 err = -EOPNOTSUPP;
5351 goto out;
5352 }
5353
5354 /* Note : because we don't lock out the irq handler, the way
5355 * we access scan variables in priv is critical.
5356 * o scan_inprogress : not touched by irq handler
5357 * o scan_mode : not touched by irq handler
5358 * Before modifying anything on those variables, please think hard !
5359 * Jean II */
5360
5361 /* Save flags */
5362 priv->scan_mode = srq->flags;
5363
5364 /* Always trigger scanning, even if it's in progress.
5365 * This way, if the info frame get lost, we will recover somewhat
5366 * gracefully - Jean II */
5367
5368 if (priv->has_hostscan) {
5369 switch (priv->firmware_type) {
5370 case FIRMWARE_TYPE_SYMBOL:
5371 err = hermes_write_wordrec(hw, USER_BAP,
5372 HERMES_RID_CNFHOSTSCAN_SYMBOL,
5373 HERMES_HOSTSCAN_SYMBOL_ONCE |
5374 HERMES_HOSTSCAN_SYMBOL_BCAST);
5375 break;
5376 case FIRMWARE_TYPE_INTERSIL: {
5377 __le16 req[3];
5378
5379 req[0] = cpu_to_le16(0x3fff); /* All channels */
5380 req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */
5381 req[2] = 0; /* Any ESSID */
5382 err = HERMES_WRITE_RECORD(hw, USER_BAP,
5383 HERMES_RID_CNFHOSTSCAN, &req);
5384 }
5385 break;
5386 case FIRMWARE_TYPE_AGERE:
5387 if (priv->scan_mode & IW_SCAN_THIS_ESSID) {
5388 struct hermes_idstring idbuf;
5389 size_t len = min(sizeof(idbuf.val),
5390 (size_t) si->essid_len);
5391 idbuf.len = cpu_to_le16(len);
5392 memcpy(idbuf.val, si->essid, len);
5393
5394 err = hermes_write_ltv(hw, USER_BAP,
5395 HERMES_RID_CNFSCANSSID_AGERE,
5396 HERMES_BYTES_TO_RECLEN(len + 2),
5397 &idbuf);
5398 } else
5399 err = hermes_write_wordrec(hw, USER_BAP,
5400 HERMES_RID_CNFSCANSSID_AGERE,
5401 0); /* Any ESSID */
5402 if (err)
5403 break;
5404
5405 if (priv->has_ext_scan) {
5406 /* Clear scan results at the start of
5407 * an extended scan */
5408 orinoco_clear_scan_results(priv,
5409 msecs_to_jiffies(15000));
5410
5411 /* TODO: Is this available on older firmware?
5412 * Can we use it to scan specific channels
5413 * for IW_SCAN_THIS_FREQ? */
5414 err = hermes_write_wordrec(hw, USER_BAP,
5415 HERMES_RID_CNFSCANCHANNELS2GHZ,
5416 0x7FFF);
5417 if (err)
5418 goto out;
5419
5420 err = hermes_inquire(hw,
5421 HERMES_INQ_CHANNELINFO);
5422 } else
5423 err = hermes_inquire(hw, HERMES_INQ_SCAN);
5424 break;
5425 }
5426 } else
5427 err = hermes_inquire(hw, HERMES_INQ_SCAN);
5428
5429 /* One more client */
5430 if (! err)
5431 priv->scan_inprogress = 1;
5432
5433 out:
5434 orinoco_unlock(priv, &flags);
5435 return err;
5436}
5437
5438#define MAX_CUSTOM_LEN 64
5439
5440/* Translate scan data returned from the card to a card independant
5441 * format that the Wireless Tools will understand - Jean II */
5442static inline char *orinoco_translate_scan(struct net_device *dev,
5443 struct iw_request_info *info,
5444 char *current_ev,
5445 char *end_buf,
5446 union hermes_scan_info *bss,
5447 unsigned int last_scanned)
5448{
5449 struct orinoco_private *priv = netdev_priv(dev);
5450 u16 capabilities;
5451 u16 channel;
5452 struct iw_event iwe; /* Temporary buffer */
5453 char custom[MAX_CUSTOM_LEN];
5454
5455 memset(&iwe, 0, sizeof(iwe));
5456
5457 /* First entry *MUST* be the AP MAC address */
5458 iwe.cmd = SIOCGIWAP;
5459 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
5460 memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN);
5461 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5462 &iwe, IW_EV_ADDR_LEN);
5463
5464 /* Other entries will be displayed in the order we give them */
5465
5466 /* Add the ESSID */
5467 iwe.u.data.length = le16_to_cpu(bss->a.essid_len);
5468 if (iwe.u.data.length > 32)
5469 iwe.u.data.length = 32;
5470 iwe.cmd = SIOCGIWESSID;
5471 iwe.u.data.flags = 1;
5472 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5473 &iwe, bss->a.essid);
5474
5475 /* Add mode */
5476 iwe.cmd = SIOCGIWMODE;
5477 capabilities = le16_to_cpu(bss->a.capabilities);
5478 if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
5479 if (capabilities & WLAN_CAPABILITY_ESS)
5480 iwe.u.mode = IW_MODE_MASTER;
5481 else
5482 iwe.u.mode = IW_MODE_ADHOC;
5483 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5484 &iwe, IW_EV_UINT_LEN);
5485 }
5486
5487 channel = bss->s.channel;
5488 if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
5489 /* Add channel and frequency */
5490 iwe.cmd = SIOCGIWFREQ;
5491 iwe.u.freq.m = channel;
5492 iwe.u.freq.e = 0;
5493 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5494 &iwe, IW_EV_FREQ_LEN);
5495
5496 iwe.u.freq.m = channel_frequency[channel-1] * 100000;
5497 iwe.u.freq.e = 1;
5498 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5499 &iwe, IW_EV_FREQ_LEN);
5500 }
5501
5502 /* Add quality statistics. level and noise in dB. No link quality */
5503 iwe.cmd = IWEVQUAL;
5504 iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
5505 iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95;
5506 iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95;
5507 /* Wireless tools prior to 27.pre22 will show link quality
5508 * anyway, so we provide a reasonable value. */
5509 if (iwe.u.qual.level > iwe.u.qual.noise)
5510 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
5511 else
5512 iwe.u.qual.qual = 0;
5513 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5514 &iwe, IW_EV_QUAL_LEN);
5515
5516 /* Add encryption capability */
5517 iwe.cmd = SIOCGIWENCODE;
5518 if (capabilities & WLAN_CAPABILITY_PRIVACY)
5519 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
5520 else
5521 iwe.u.data.flags = IW_ENCODE_DISABLED;
5522 iwe.u.data.length = 0;
5523 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5524 &iwe, NULL);
5525
5526 /* Bit rate is not available in Lucent/Agere firmwares */
5527 if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
5528 char *current_val = current_ev + iwe_stream_lcp_len(info);
5529 int i;
5530 int step;
5531
5532 if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
5533 step = 2;
5534 else
5535 step = 1;
5536
5537 iwe.cmd = SIOCGIWRATE;
5538 /* Those two flags are ignored... */
5539 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
5540 /* Max 10 values */
5541 for (i = 0; i < 10; i += step) {
5542 /* NULL terminated */
5543 if (bss->p.rates[i] == 0x0)
5544 break;
5545 /* Bit rate given in 500 kb/s units (+ 0x80) */
5546 iwe.u.bitrate.value =
5547 ((bss->p.rates[i] & 0x7f) * 500000);
5548 current_val = iwe_stream_add_value(info, current_ev,
5549 current_val,
5550 end_buf, &iwe,
5551 IW_EV_PARAM_LEN);
5552 }
5553 /* Check if we added any event */
5554 if ((current_val - current_ev) > iwe_stream_lcp_len(info))
5555 current_ev = current_val;
5556 }
5557
5558 /* Beacon interval */
5559 iwe.cmd = IWEVCUSTOM;
5560 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
5561 "bcn_int=%d",
5562 le16_to_cpu(bss->a.beacon_interv));
5563 if (iwe.u.data.length)
5564 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5565 &iwe, custom);
5566
5567 /* Capabilites */
5568 iwe.cmd = IWEVCUSTOM;
5569 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
5570 "capab=0x%04x",
5571 capabilities);
5572 if (iwe.u.data.length)
5573 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5574 &iwe, custom);
5575
5576 /* Add EXTRA: Age to display seconds since last beacon/probe response
5577 * for given network. */
5578 iwe.cmd = IWEVCUSTOM;
5579 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
5580 " Last beacon: %dms ago",
5581 jiffies_to_msecs(jiffies - last_scanned));
5582 if (iwe.u.data.length)
5583 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5584 &iwe, custom);
5585
5586 return current_ev;
5587}
5588
5589static inline char *orinoco_translate_ext_scan(struct net_device *dev,
5590 struct iw_request_info *info,
5591 char *current_ev,
5592 char *end_buf,
5593 struct agere_ext_scan_info *bss,
5594 unsigned int last_scanned)
5595{
5596 u16 capabilities;
5597 u16 channel;
5598 struct iw_event iwe; /* Temporary buffer */
5599 char custom[MAX_CUSTOM_LEN];
5600 u8 *ie;
5601
5602 memset(&iwe, 0, sizeof(iwe));
5603
5604 /* First entry *MUST* be the AP MAC address */
5605 iwe.cmd = SIOCGIWAP;
5606 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
5607 memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
5608 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5609 &iwe, IW_EV_ADDR_LEN);
5610
5611 /* Other entries will be displayed in the order we give them */
5612
5613 /* Add the ESSID */
5614 ie = bss->data;
5615 iwe.u.data.length = ie[1];
5616 if (iwe.u.data.length) {
5617 if (iwe.u.data.length > 32)
5618 iwe.u.data.length = 32;
5619 iwe.cmd = SIOCGIWESSID;
5620 iwe.u.data.flags = 1;
5621 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5622 &iwe, &ie[2]);
5623 }
5624
5625 /* Add mode */
5626 capabilities = le16_to_cpu(bss->capabilities);
5627 if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
5628 iwe.cmd = SIOCGIWMODE;
5629 if (capabilities & WLAN_CAPABILITY_ESS)
5630 iwe.u.mode = IW_MODE_MASTER;
5631 else
5632 iwe.u.mode = IW_MODE_ADHOC;
5633 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5634 &iwe, IW_EV_UINT_LEN);
5635 }
5636
5637 ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS);
5638 channel = ie ? ie[2] : 0;
5639 if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
5640 /* Add channel and frequency */
5641 iwe.cmd = SIOCGIWFREQ;
5642 iwe.u.freq.m = channel;
5643 iwe.u.freq.e = 0;
5644 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5645 &iwe, IW_EV_FREQ_LEN);
5646
5647 iwe.u.freq.m = channel_frequency[channel-1] * 100000;
5648 iwe.u.freq.e = 1;
5649 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5650 &iwe, IW_EV_FREQ_LEN);
5651 }
5652
5653 /* Add quality statistics. level and noise in dB. No link quality */
5654 iwe.cmd = IWEVQUAL;
5655 iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
5656 iwe.u.qual.level = bss->level - 0x95;
5657 iwe.u.qual.noise = bss->noise - 0x95;
5658 /* Wireless tools prior to 27.pre22 will show link quality
5659 * anyway, so we provide a reasonable value. */
5660 if (iwe.u.qual.level > iwe.u.qual.noise)
5661 iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
5662 else
5663 iwe.u.qual.qual = 0;
5664 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
5665 &iwe, IW_EV_QUAL_LEN);
5666
5667 /* Add encryption capability */
5668 iwe.cmd = SIOCGIWENCODE;
5669 if (capabilities & WLAN_CAPABILITY_PRIVACY)
5670 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
5671 else
5672 iwe.u.data.flags = IW_ENCODE_DISABLED;
5673 iwe.u.data.length = 0;
5674 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5675 &iwe, NULL);
5676
5677 /* WPA IE */
5678 ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data));
5679 if (ie) {
5680 iwe.cmd = IWEVGENIE;
5681 iwe.u.data.length = ie[1] + 2;
5682 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5683 &iwe, ie);
5684 }
5685
5686 /* RSN IE */
5687 ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN);
5688 if (ie) {
5689 iwe.cmd = IWEVGENIE;
5690 iwe.u.data.length = ie[1] + 2;
5691 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5692 &iwe, ie);
5693 }
5694
5695 ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES);
5696 if (ie) {
5697 char *p = current_ev + iwe_stream_lcp_len(info);
5698 int i;
5699
5700 iwe.cmd = SIOCGIWRATE;
5701 /* Those two flags are ignored... */
5702 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
5703
5704 for (i = 2; i < (ie[1] + 2); i++) {
5705 iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000);
5706 p = iwe_stream_add_value(info, current_ev, p, end_buf,
5707 &iwe, IW_EV_PARAM_LEN);
5708 }
5709 /* Check if we added any event */
5710 if (p > (current_ev + iwe_stream_lcp_len(info)))
5711 current_ev = p;
5712 }
5713
5714 /* Timestamp */
5715 iwe.cmd = IWEVCUSTOM;
5716 iwe.u.data.length =
5717 snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx",
5718 (unsigned long long) le64_to_cpu(bss->timestamp));
5719 if (iwe.u.data.length)
5720 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5721 &iwe, custom);
5722
5723 /* Beacon interval */
5724 iwe.cmd = IWEVCUSTOM;
5725 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
5726 "bcn_int=%d",
5727 le16_to_cpu(bss->beacon_interval));
5728 if (iwe.u.data.length)
5729 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5730 &iwe, custom);
5731
5732 /* Capabilites */
5733 iwe.cmd = IWEVCUSTOM;
5734 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
5735 "capab=0x%04x",
5736 capabilities);
5737 if (iwe.u.data.length)
5738 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5739 &iwe, custom);
5740
5741 /* Add EXTRA: Age to display seconds since last beacon/probe response
5742 * for given network. */
5743 iwe.cmd = IWEVCUSTOM;
5744 iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
5745 " Last beacon: %dms ago",
5746 jiffies_to_msecs(jiffies - last_scanned));
5747 if (iwe.u.data.length)
5748 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
5749 &iwe, custom);
5750
5751 return current_ev;
5752}
5753
5754/* Return results of a scan */
5755static int orinoco_ioctl_getscan(struct net_device *dev,
5756 struct iw_request_info *info,
5757 struct iw_point *srq,
5758 char *extra)
5759{
5760 struct orinoco_private *priv = netdev_priv(dev);
5761 int err = 0;
5762 unsigned long flags;
5763 char *current_ev = extra;
5764
5765 if (orinoco_lock(priv, &flags) != 0)
5766 return -EBUSY;
5767
5768 if (priv->scan_inprogress) {
5769 /* Important note : we don't want to block the caller
5770 * until results are ready for various reasons.
5771 * First, managing wait queues is complex and racy.
5772 * Second, we grab some rtnetlink lock before comming
5773 * here (in dev_ioctl()).
5774 * Third, we generate an Wireless Event, so the
5775 * caller can wait itself on that - Jean II */
5776 err = -EAGAIN;
5777 goto out;
5778 }
5779
5780 if (priv->has_ext_scan) {
5781 struct xbss_element *bss;
5782
5783 list_for_each_entry(bss, &priv->bss_list, list) {
5784 /* Translate this entry to WE format */
5785 current_ev =
5786 orinoco_translate_ext_scan(dev, info,
5787 current_ev,
5788 extra + srq->length,
5789 &bss->bss,
5790 bss->last_scanned);
5791
5792 /* Check if there is space for one more entry */
5793 if ((extra + srq->length - current_ev)
5794 <= IW_EV_ADDR_LEN) {
5795 /* Ask user space to try again with a
5796 * bigger buffer */
5797 err = -E2BIG;
5798 goto out;
5799 }
5800 }
5801
5802 } else {
5803 struct bss_element *bss;
5804
5805 list_for_each_entry(bss, &priv->bss_list, list) {
5806 /* Translate this entry to WE format */
5807 current_ev = orinoco_translate_scan(dev, info,
5808 current_ev,
5809 extra + srq->length,
5810 &bss->bss,
5811 bss->last_scanned);
5812
5813 /* Check if there is space for one more entry */
5814 if ((extra + srq->length - current_ev)
5815 <= IW_EV_ADDR_LEN) {
5816 /* Ask user space to try again with a
5817 * bigger buffer */
5818 err = -E2BIG;
5819 goto out;
5820 }
5821 }
5822 }
5823
5824 srq->length = (current_ev - extra);
5825 srq->flags = (__u16) priv->scan_mode;
5826
5827out:
5828 orinoco_unlock(priv, &flags);
5829 return err;
5830}
5831
5832/* Commit handler, called after set operations */
5833static int orinoco_ioctl_commit(struct net_device *dev,
5834 struct iw_request_info *info,
5835 void *wrqu,
5836 char *extra)
5837{
5838 struct orinoco_private *priv = netdev_priv(dev);
5839 struct hermes *hw = &priv->hw;
5840 unsigned long flags;
5841 int err = 0;
5842
5843 if (!priv->open)
5844 return 0;
5845
5846 if (priv->broken_disableport) {
5847 orinoco_reset(&priv->reset_work);
5848 return 0;
5849 }
5850
5851 if (orinoco_lock(priv, &flags) != 0)
5852 return err;
5853
5854 err = hermes_disable_port(hw, 0);
5855 if (err) {
5856 printk(KERN_WARNING "%s: Unable to disable port "
5857 "while reconfiguring card\n", dev->name);
5858 priv->broken_disableport = 1;
5859 goto out;
5860 }
5861
5862 err = __orinoco_program_rids(dev);
5863 if (err) {
5864 printk(KERN_WARNING "%s: Unable to reconfigure card\n",
5865 dev->name);
5866 goto out;
5867 }
5868
5869 err = hermes_enable_port(hw, 0);
5870 if (err) {
5871 printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
5872 dev->name);
5873 goto out;
5874 }
5875
5876 out:
5877 if (err) {
5878 printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
5879 schedule_work(&priv->reset_work);
5880 err = 0;
5881 }
5882
5883 orinoco_unlock(priv, &flags);
5884 return err;
5885}
5886
5887static const struct iw_priv_args orinoco_privtab[] = {
5888 { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
5889 { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
5890 { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
5891 0, "set_port3" },
5892 { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
5893 "get_port3" },
5894 { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
5895 0, "set_preamble" },
5896 { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
5897 "get_preamble" },
5898 { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
5899 0, "set_ibssport" },
5900 { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
5901 "get_ibssport" },
5902 { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN,
5903 "get_rid" },
5904};
5905
5906
5907/*
5908 * Structures to export the Wireless Handlers
5909 */
5910
5911#define STD_IW_HANDLER(id, func) \
5912 [IW_IOCTL_IDX(id)] = (iw_handler) func
5913static const iw_handler orinoco_handler[] = {
5914 STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit),
5915 STD_IW_HANDLER(SIOCGIWNAME, orinoco_ioctl_getname),
5916 STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq),
5917 STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq),
5918 STD_IW_HANDLER(SIOCSIWMODE, orinoco_ioctl_setmode),
5919 STD_IW_HANDLER(SIOCGIWMODE, orinoco_ioctl_getmode),
5920 STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens),
5921 STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens),
5922 STD_IW_HANDLER(SIOCGIWRANGE, orinoco_ioctl_getiwrange),
5923 STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy),
5924 STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy),
5925 STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy),
5926 STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy),
5927 STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap),
5928 STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap),
5929 STD_IW_HANDLER(SIOCSIWSCAN, orinoco_ioctl_setscan),
5930 STD_IW_HANDLER(SIOCGIWSCAN, orinoco_ioctl_getscan),
5931 STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid),
5932 STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid),
5933 STD_IW_HANDLER(SIOCSIWNICKN, orinoco_ioctl_setnick),
5934 STD_IW_HANDLER(SIOCGIWNICKN, orinoco_ioctl_getnick),
5935 STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate),
5936 STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate),
5937 STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts),
5938 STD_IW_HANDLER(SIOCGIWRTS, orinoco_ioctl_getrts),
5939 STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag),
5940 STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag),
5941 STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry),
5942 STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode),
5943 STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode),
5944 STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower),
5945 STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower),
5946 STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie),
5947 STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie),
5948 STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme),
5949 STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth),
5950 STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth),
5951 STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext),
5952 STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext),
5953};
5954
5955
5956/*
5957 Added typecasting since we no longer use iwreq_data -- Moustafa
5958 */
5959static const iw_handler orinoco_private_handler[] = {
5960 [0] = (iw_handler) orinoco_ioctl_reset,
5961 [1] = (iw_handler) orinoco_ioctl_reset,
5962 [2] = (iw_handler) orinoco_ioctl_setport3,
5963 [3] = (iw_handler) orinoco_ioctl_getport3,
5964 [4] = (iw_handler) orinoco_ioctl_setpreamble,
5965 [5] = (iw_handler) orinoco_ioctl_getpreamble,
5966 [6] = (iw_handler) orinoco_ioctl_setibssport,
5967 [7] = (iw_handler) orinoco_ioctl_getibssport,
5968 [9] = (iw_handler) orinoco_ioctl_getrid,
5969};
5970
5971static const struct iw_handler_def orinoco_handler_def = {
5972 .num_standard = ARRAY_SIZE(orinoco_handler),
5973 .num_private = ARRAY_SIZE(orinoco_private_handler),
5974 .num_private_args = ARRAY_SIZE(orinoco_privtab),
5975 .standard = orinoco_handler,
5976 .private = orinoco_private_handler,
5977 .private_args = orinoco_privtab,
5978 .get_wireless_stats = orinoco_get_wireless_stats,
5979};
5980
5981static void orinoco_get_drvinfo(struct net_device *dev,
5982 struct ethtool_drvinfo *info)
5983{
5984 struct orinoco_private *priv = netdev_priv(dev);
5985
5986 strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
5987 strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1);
5988 strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1);
5989 if (dev->dev.parent)
5990 strncpy(info->bus_info, dev->dev.parent->bus_id,
5991 sizeof(info->bus_info) - 1);
5992 else
5993 snprintf(info->bus_info, sizeof(info->bus_info) - 1,
5994 "PCMCIA %p", priv->hw.iobase);
5995}
5996
5997static const struct ethtool_ops orinoco_ethtool_ops = {
5998 .get_drvinfo = orinoco_get_drvinfo,
5999 .get_link = ethtool_op_get_link,
6000};
6001
6002/********************************************************************/
6003/* Module initialization */
6004/********************************************************************/
6005
6006EXPORT_SYMBOL(alloc_orinocodev);
6007EXPORT_SYMBOL(free_orinocodev);
6008
6009EXPORT_SYMBOL(__orinoco_up);
6010EXPORT_SYMBOL(__orinoco_down);
6011EXPORT_SYMBOL(orinoco_reinit_firmware);
6012
6013EXPORT_SYMBOL(orinoco_interrupt);
6014
6015/* Can't be declared "const" or the whole __initdata section will
6016 * become const */
6017static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
6018 " (David Gibson <hermes@gibson.dropbear.id.au>, "
6019 "Pavel Roskin <proski@gnu.org>, et al)";
6020
6021static int __init init_orinoco(void)
6022{
6023 printk(KERN_DEBUG "%s\n", version);
6024 return 0;
6025}
6026
6027static void __exit exit_orinoco(void)
6028{
6029}
6030
6031module_init(init_orinoco);
6032module_exit(exit_orinoco);
diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h
new file mode 100644
index 000000000000..8c2953834923
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco.h
@@ -0,0 +1,218 @@
1/* orinoco.h
2 *
3 * Common definitions to all pieces of the various orinoco
4 * drivers
5 */
6
7#ifndef _ORINOCO_H
8#define _ORINOCO_H
9
10#define DRIVER_VERSION "0.15"
11
12#include <linux/interrupt.h>
13#include <linux/netdevice.h>
14#include <linux/wireless.h>
15#include <net/iw_handler.h>
16
17#include "hermes.h"
18
19/* To enable debug messages */
20//#define ORINOCO_DEBUG 3
21
22#define WIRELESS_SPY // enable iwspy support
23
24#define MAX_SCAN_LEN 4096
25
26#define ORINOCO_MAX_KEY_SIZE 14
27#define ORINOCO_MAX_KEYS 4
28
29struct orinoco_key {
30 __le16 len; /* always stored as little-endian */
31 char data[ORINOCO_MAX_KEY_SIZE];
32} __attribute__ ((packed));
33
34#define TKIP_KEYLEN 16
35#define MIC_KEYLEN 8
36
37struct orinoco_tkip_key {
38 u8 tkip[TKIP_KEYLEN];
39 u8 tx_mic[MIC_KEYLEN];
40 u8 rx_mic[MIC_KEYLEN];
41};
42
43typedef enum {
44 FIRMWARE_TYPE_AGERE,
45 FIRMWARE_TYPE_INTERSIL,
46 FIRMWARE_TYPE_SYMBOL
47} fwtype_t;
48
49struct bss_element {
50 union hermes_scan_info bss;
51 unsigned long last_scanned;
52 struct list_head list;
53};
54
55struct xbss_element {
56 struct agere_ext_scan_info bss;
57 unsigned long last_scanned;
58 struct list_head list;
59};
60
61struct hermes_rx_descriptor;
62
63struct orinoco_rx_data {
64 struct hermes_rx_descriptor *desc;
65 struct sk_buff *skb;
66 struct list_head list;
67};
68
69struct firmware;
70
71struct orinoco_private {
72 void *card; /* Pointer to card dependent structure */
73 struct device *dev;
74 int (*hard_reset)(struct orinoco_private *);
75 int (*stop_fw)(struct orinoco_private *, int);
76
77 /* Synchronisation stuff */
78 spinlock_t lock;
79 int hw_unavailable;
80 struct work_struct reset_work;
81
82 /* Interrupt tasklets */
83 struct tasklet_struct rx_tasklet;
84 struct list_head rx_list;
85 struct orinoco_rx_data *rx_data;
86
87 /* driver state */
88 int open;
89 u16 last_linkstatus;
90 struct work_struct join_work;
91 struct work_struct wevent_work;
92
93 /* Net device stuff */
94 struct net_device *ndev;
95 struct net_device_stats stats;
96 struct iw_statistics wstats;
97
98 /* Hardware control variables */
99 hermes_t hw;
100 u16 txfid;
101
102 /* Capabilities of the hardware/firmware */
103 fwtype_t firmware_type;
104 char fw_name[32];
105 int ibss_port;
106 int nicbuf_size;
107 u16 channel_mask;
108
109 /* Boolean capabilities */
110 unsigned int has_ibss:1;
111 unsigned int has_port3:1;
112 unsigned int has_wep:1;
113 unsigned int has_big_wep:1;
114 unsigned int has_mwo:1;
115 unsigned int has_pm:1;
116 unsigned int has_preamble:1;
117 unsigned int has_sensitivity:1;
118 unsigned int has_hostscan:1;
119 unsigned int has_alt_txcntl:1;
120 unsigned int has_ext_scan:1;
121 unsigned int has_wpa:1;
122 unsigned int do_fw_download:1;
123 unsigned int broken_disableport:1;
124 unsigned int broken_monitor:1;
125
126 /* Configuration paramaters */
127 u32 iw_mode;
128 int prefer_port3;
129 u16 encode_alg, wep_restrict, tx_key;
130 struct orinoco_key keys[ORINOCO_MAX_KEYS];
131 int bitratemode;
132 char nick[IW_ESSID_MAX_SIZE+1];
133 char desired_essid[IW_ESSID_MAX_SIZE+1];
134 char desired_bssid[ETH_ALEN];
135 int bssid_fixed;
136 u16 frag_thresh, mwo_robust;
137 u16 channel;
138 u16 ap_density, rts_thresh;
139 u16 pm_on, pm_mcast, pm_period, pm_timeout;
140 u16 preamble;
141#ifdef WIRELESS_SPY
142 struct iw_spy_data spy_data; /* iwspy support */
143 struct iw_public_data wireless_data;
144#endif
145
146 /* Configuration dependent variables */
147 int port_type, createibss;
148 int promiscuous, mc_count;
149
150 /* Scanning support */
151 struct list_head bss_list;
152 struct list_head bss_free_list;
153 void *bss_xbss_data;
154
155 int scan_inprogress; /* Scan pending... */
156 u32 scan_mode; /* Type of scan done */
157
158 /* WPA support */
159 u8 *wpa_ie;
160 int wpa_ie_len;
161
162 struct orinoco_tkip_key tkip_key[ORINOCO_MAX_KEYS];
163 struct crypto_hash *rx_tfm_mic;
164 struct crypto_hash *tx_tfm_mic;
165
166 unsigned int wpa_enabled:1;
167 unsigned int tkip_cm_active:1;
168 unsigned int key_mgmt:3;
169
170 /* Cached in memory firmware to use in ->resume */
171 const struct firmware *cached_fw;
172};
173
174#ifdef ORINOCO_DEBUG
175extern int orinoco_debug;
176#define DEBUG(n, args...) do { if (orinoco_debug>(n)) printk(KERN_DEBUG args); } while(0)
177#else
178#define DEBUG(n, args...) do { } while (0)
179#endif /* ORINOCO_DEBUG */
180
181/********************************************************************/
182/* Exported prototypes */
183/********************************************************************/
184
185extern struct net_device *alloc_orinocodev(
186 int sizeof_card, struct device *device,
187 int (*hard_reset)(struct orinoco_private *),
188 int (*stop_fw)(struct orinoco_private *, int));
189extern void free_orinocodev(struct net_device *dev);
190extern int __orinoco_up(struct net_device *dev);
191extern int __orinoco_down(struct net_device *dev);
192extern int orinoco_reinit_firmware(struct net_device *dev);
193extern irqreturn_t orinoco_interrupt(int irq, void * dev_id);
194
195/********************************************************************/
196/* Locking and synchronization functions */
197/********************************************************************/
198
199static inline int orinoco_lock(struct orinoco_private *priv,
200 unsigned long *flags)
201{
202 spin_lock_irqsave(&priv->lock, *flags);
203 if (priv->hw_unavailable) {
204 DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n",
205 priv->ndev);
206 spin_unlock_irqrestore(&priv->lock, *flags);
207 return -EBUSY;
208 }
209 return 0;
210}
211
212static inline void orinoco_unlock(struct orinoco_private *priv,
213 unsigned long *flags)
214{
215 spin_unlock_irqrestore(&priv->lock, *flags);
216}
217
218#endif /* _ORINOCO_H */
diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c
new file mode 100644
index 000000000000..6fcf2bda7cdf
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco_cs.c
@@ -0,0 +1,533 @@
1/* orinoco_cs.c (formerly known as dldwd_cs.c)
2 *
3 * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such
4 * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/
5 * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others).
6 * It should also be usable on various Prism II based cards such as the
7 * Linksys, D-Link and Farallon Skyline. It should also work on Symbol
8 * cards such as the 3Com AirConnect and Ericsson WLAN.
9 *
10 * Copyright notice & release notes in file orinoco.c
11 */
12
13#define DRIVER_NAME "orinoco_cs"
14#define PFX DRIVER_NAME ": "
15
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/init.h>
19#include <linux/delay.h>
20#include <pcmcia/cs_types.h>
21#include <pcmcia/cs.h>
22#include <pcmcia/cistpl.h>
23#include <pcmcia/cisreg.h>
24#include <pcmcia/ds.h>
25
26#include "orinoco.h"
27
28/********************************************************************/
29/* Module stuff */
30/********************************************************************/
31
32MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
33MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco, Prism II based and similar wireless cards");
34MODULE_LICENSE("Dual MPL/GPL");
35
36/* Module parameters */
37
38/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
39 * don't have any CIS entry for it. This workaround it... */
40static int ignore_cis_vcc; /* = 0 */
41module_param(ignore_cis_vcc, int, 0);
42MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
43
44/********************************************************************/
45/* Data structures */
46/********************************************************************/
47
48/* PCMCIA specific device information (goes in the card field of
49 * struct orinoco_private */
50struct orinoco_pccard {
51 struct pcmcia_device *p_dev;
52 dev_node_t node;
53
54 /* Used to handle hard reset */
55 /* yuck, we need this hack to work around the insanity of the
56 * PCMCIA layer */
57 unsigned long hard_reset_in_progress;
58};
59
60
61/********************************************************************/
62/* Function prototypes */
63/********************************************************************/
64
65static int orinoco_cs_config(struct pcmcia_device *link);
66static void orinoco_cs_release(struct pcmcia_device *link);
67static void orinoco_cs_detach(struct pcmcia_device *p_dev);
68
69/********************************************************************/
70/* Device methods */
71/********************************************************************/
72
73static int
74orinoco_cs_hard_reset(struct orinoco_private *priv)
75{
76 struct orinoco_pccard *card = priv->card;
77 struct pcmcia_device *link = card->p_dev;
78 int err;
79
80 /* We need atomic ops here, because we're not holding the lock */
81 set_bit(0, &card->hard_reset_in_progress);
82
83 err = pcmcia_reset_card(link->socket);
84 if (err)
85 return err;
86
87 msleep(100);
88 clear_bit(0, &card->hard_reset_in_progress);
89
90 return 0;
91}
92
93/********************************************************************/
94/* PCMCIA stuff */
95/********************************************************************/
96
97/*
98 * This creates an "instance" of the driver, allocating local data
99 * structures for one device. The device is registered with Card
100 * Services.
101 *
102 * The dev_link structure is initialized, but we don't actually
103 * configure the card at this point -- we wait until we receive a card
104 * insertion event. */
105static int
106orinoco_cs_probe(struct pcmcia_device *link)
107{
108 struct net_device *dev;
109 struct orinoco_private *priv;
110 struct orinoco_pccard *card;
111
112 dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
113 orinoco_cs_hard_reset, NULL);
114 if (! dev)
115 return -ENOMEM;
116 priv = netdev_priv(dev);
117 card = priv->card;
118
119 /* Link both structures together */
120 card->p_dev = link;
121 link->priv = dev;
122
123 /* Interrupt setup */
124 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
125 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
126 link->irq.Handler = orinoco_interrupt;
127 link->irq.Instance = dev;
128
129 /* General socket configuration defaults can go here. In this
130 * client, we assume very little, and rely on the CIS for
131 * almost everything. In most clients, many details (i.e.,
132 * number, sizes, and attributes of IO windows) are fixed by
133 * the nature of the device, and can be hard-wired here. */
134 link->conf.Attributes = 0;
135 link->conf.IntType = INT_MEMORY_AND_IO;
136
137 return orinoco_cs_config(link);
138} /* orinoco_cs_attach */
139
140/*
141 * This deletes a driver "instance". The device is de-registered with
142 * Card Services. If it has been released, all local data structures
143 * are freed. Otherwise, the structures will be freed when the device
144 * is released.
145 */
146static void orinoco_cs_detach(struct pcmcia_device *link)
147{
148 struct net_device *dev = link->priv;
149
150 if (link->dev_node)
151 unregister_netdev(dev);
152
153 orinoco_cs_release(link);
154
155 free_orinocodev(dev);
156} /* orinoco_cs_detach */
157
158/*
159 * orinoco_cs_config() is scheduled to run after a CARD_INSERTION
160 * event is received, to configure the PCMCIA socket, and to make the
161 * device available to the system.
162 */
163
164#define CS_CHECK(fn, ret) do { \
165 last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; \
166 } while (0)
167
168static int orinoco_cs_config_check(struct pcmcia_device *p_dev,
169 cistpl_cftable_entry_t *cfg,
170 cistpl_cftable_entry_t *dflt,
171 unsigned int vcc,
172 void *priv_data)
173{
174 if (cfg->index == 0)
175 goto next_entry;
176
177 /* Use power settings for Vcc and Vpp if present */
178 /* Note that the CIS values need to be rescaled */
179 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
180 if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
181 DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
182 if (!ignore_cis_vcc)
183 goto next_entry;
184 }
185 } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
186 if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
187 DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
188 if (!ignore_cis_vcc)
189 goto next_entry;
190 }
191 }
192
193 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
194 p_dev->conf.Vpp =
195 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
196 else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
197 p_dev->conf.Vpp =
198 dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
199
200 /* Do we need to allocate an interrupt? */
201 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
202
203 /* IO window settings */
204 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
205 if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
206 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
207 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
208 if (!(io->flags & CISTPL_IO_8BIT))
209 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
210 if (!(io->flags & CISTPL_IO_16BIT))
211 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
212 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
213 p_dev->io.BasePort1 = io->win[0].base;
214 p_dev->io.NumPorts1 = io->win[0].len;
215 if (io->nwin > 1) {
216 p_dev->io.Attributes2 = p_dev->io.Attributes1;
217 p_dev->io.BasePort2 = io->win[1].base;
218 p_dev->io.NumPorts2 = io->win[1].len;
219 }
220
221 /* This reserves IO space but doesn't actually enable it */
222 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
223 goto next_entry;
224 }
225 return 0;
226
227next_entry:
228 pcmcia_disable_device(p_dev);
229 return -ENODEV;
230};
231
232static int
233orinoco_cs_config(struct pcmcia_device *link)
234{
235 struct net_device *dev = link->priv;
236 struct orinoco_private *priv = netdev_priv(dev);
237 struct orinoco_pccard *card = priv->card;
238 hermes_t *hw = &priv->hw;
239 int last_fn, last_ret;
240 void __iomem *mem;
241
242 /*
243 * In this loop, we scan the CIS for configuration table
244 * entries, each of which describes a valid card
245 * configuration, including voltage, IO window, memory window,
246 * and interrupt settings.
247 *
248 * We make no assumptions about the card to be configured: we
249 * use just the information available in the CIS. In an ideal
250 * world, this would work for any PCMCIA card, but it requires
251 * a complete and accurate CIS. In practice, a driver usually
252 * "knows" most of these things without consulting the CIS,
253 * and most client drivers will only use the CIS to fill in
254 * implementation-defined details.
255 */
256 last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL);
257 if (last_ret) {
258 if (!ignore_cis_vcc)
259 printk(KERN_ERR PFX "GetNextTuple(): No matching "
260 "CIS configuration. Maybe you need the "
261 "ignore_cis_vcc=1 parameter.\n");
262 cs_error(link, RequestIO, last_ret);
263 goto failed;
264 }
265
266 /*
267 * Allocate an interrupt line. Note that this does not assign
268 * a handler to the interrupt, unless the 'Handler' member of
269 * the irq structure is initialized.
270 */
271 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
272
273 /* We initialize the hermes structure before completing PCMCIA
274 * configuration just in case the interrupt handler gets
275 * called. */
276 mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
277 if (!mem)
278 goto cs_failed;
279
280 hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
281
282 /*
283 * This actually configures the PCMCIA socket -- setting up
284 * the I/O windows and the interrupt mapping, and putting the
285 * card and host interface into "Memory and IO" mode.
286 */
287 CS_CHECK(RequestConfiguration,
288 pcmcia_request_configuration(link, &link->conf));
289
290 /* Ok, we have the configuration, prepare to register the netdev */
291 dev->base_addr = link->io.BasePort1;
292 dev->irq = link->irq.AssignedIRQ;
293 card->node.major = card->node.minor = 0;
294
295 SET_NETDEV_DEV(dev, &handle_to_dev(link));
296 /* Tell the stack we exist */
297 if (register_netdev(dev) != 0) {
298 printk(KERN_ERR PFX "register_netdev() failed\n");
299 goto failed;
300 }
301
302 /* At this point, the dev_node_t structure(s) needs to be
303 * initialized and arranged in a linked list at link->dev_node. */
304 strcpy(card->node.dev_name, dev->name);
305 link->dev_node = &card->node; /* link->dev_node being non-NULL is also
306 used to indicate that the
307 net_device has been registered */
308
309 /* Finally, report what we've done */
310 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
311 "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
312 link->irq.AssignedIRQ, link->io.BasePort1,
313 link->io.BasePort1 + link->io.NumPorts1 - 1);
314 return 0;
315
316 cs_failed:
317 cs_error(link, last_fn, last_ret);
318
319 failed:
320 orinoco_cs_release(link);
321 return -ENODEV;
322} /* orinoco_cs_config */
323
324/*
325 * After a card is removed, orinoco_cs_release() will unregister the
326 * device, and release the PCMCIA configuration. If the device is
327 * still open, this will be postponed until it is closed.
328 */
329static void
330orinoco_cs_release(struct pcmcia_device *link)
331{
332 struct net_device *dev = link->priv;
333 struct orinoco_private *priv = netdev_priv(dev);
334 unsigned long flags;
335
336 /* We're committed to taking the device away now, so mark the
337 * hardware as unavailable */
338 spin_lock_irqsave(&priv->lock, flags);
339 priv->hw_unavailable++;
340 spin_unlock_irqrestore(&priv->lock, flags);
341
342 pcmcia_disable_device(link);
343 if (priv->hw.iobase)
344 ioport_unmap(priv->hw.iobase);
345} /* orinoco_cs_release */
346
347static int orinoco_cs_suspend(struct pcmcia_device *link)
348{
349 struct net_device *dev = link->priv;
350 struct orinoco_private *priv = netdev_priv(dev);
351 struct orinoco_pccard *card = priv->card;
352 int err = 0;
353 unsigned long flags;
354
355 /* This is probably racy, but I can't think of
356 a better way, short of rewriting the PCMCIA
357 layer to not suck :-( */
358 if (! test_bit(0, &card->hard_reset_in_progress)) {
359 spin_lock_irqsave(&priv->lock, flags);
360
361 err = __orinoco_down(dev);
362 if (err)
363 printk(KERN_WARNING "%s: Error %d downing interface\n",
364 dev->name, err);
365
366 netif_device_detach(dev);
367 priv->hw_unavailable++;
368
369 spin_unlock_irqrestore(&priv->lock, flags);
370 }
371
372 return 0;
373}
374
375static int orinoco_cs_resume(struct pcmcia_device *link)
376{
377 struct net_device *dev = link->priv;
378 struct orinoco_private *priv = netdev_priv(dev);
379 struct orinoco_pccard *card = priv->card;
380 int err = 0;
381 unsigned long flags;
382
383 if (! test_bit(0, &card->hard_reset_in_progress)) {
384 err = orinoco_reinit_firmware(dev);
385 if (err) {
386 printk(KERN_ERR "%s: Error %d re-initializing firmware\n",
387 dev->name, err);
388 return -EIO;
389 }
390
391 spin_lock_irqsave(&priv->lock, flags);
392
393 netif_device_attach(dev);
394 priv->hw_unavailable--;
395
396 if (priv->open && ! priv->hw_unavailable) {
397 err = __orinoco_up(dev);
398 if (err)
399 printk(KERN_ERR "%s: Error %d restarting card\n",
400 dev->name, err);
401 }
402
403 spin_unlock_irqrestore(&priv->lock, flags);
404 }
405
406 return err;
407}
408
409
410/********************************************************************/
411/* Module initialization */
412/********************************************************************/
413
414/* Can't be declared "const" or the whole __initdata section will
415 * become const */
416static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
417 " (David Gibson <hermes@gibson.dropbear.id.au>, "
418 "Pavel Roskin <proski@gnu.org>, et al)";
419
420static struct pcmcia_device_id orinoco_cs_ids[] = {
421 PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */
422 PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */
423 PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */
424 PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */
425 PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */
426 PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */
427 PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */
428 PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */
429 PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */
430 PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */
431 PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */
432 PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */
433 PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */
434 PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */
435 PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */
436 PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */
437 PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */
438 PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */
439 PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */
440 PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */
441 PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */
442 PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */
443 PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */
444 PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */
445 PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */
446 PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */
447 PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */
448 PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */
449 PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9),
450 PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3),
451 PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5),
452 PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2),
453 PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092),
454 PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f),
455 PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842),
456 PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e),
457 PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169),
458 PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb),
459 PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3),
460 PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18),
461 PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90),
462 PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b),
463 PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39),
464 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584),
465 PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9),
466 PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae),
467 PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac),
468 PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab),
469 PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916),
470 PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146),
471 PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3),
472 PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c),
473 PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0),
474 PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077),
475 PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18),
476 PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77),
477 PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf),
478 PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2),
479 PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92),
480 PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395),
481 PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a),
482 PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410),
483 PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3),
484 PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01),
485 PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a),
486 PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1),
487 PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1),
488 PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767),
489 PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6),
490 PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed),
491 PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39),
492 PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264),
493 PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178),
494 PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9),
495 PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26),
496 PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b),
497 PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757),
498 PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a),
499 PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e),
500 PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39),
501 PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee),
502 PCMCIA_DEVICE_NULL,
503};
504MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids);
505
506static struct pcmcia_driver orinoco_driver = {
507 .owner = THIS_MODULE,
508 .drv = {
509 .name = DRIVER_NAME,
510 },
511 .probe = orinoco_cs_probe,
512 .remove = orinoco_cs_detach,
513 .id_table = orinoco_cs_ids,
514 .suspend = orinoco_cs_suspend,
515 .resume = orinoco_cs_resume,
516};
517
518static int __init
519init_orinoco_cs(void)
520{
521 printk(KERN_DEBUG "%s\n", version);
522
523 return pcmcia_register_driver(&orinoco_driver);
524}
525
526static void __exit
527exit_orinoco_cs(void)
528{
529 pcmcia_unregister_driver(&orinoco_driver);
530}
531
532module_init(init_orinoco_cs);
533module_exit(exit_orinoco_cs);
diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c
new file mode 100644
index 000000000000..2fc86596302e
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco_nortel.c
@@ -0,0 +1,324 @@
1/* orinoco_nortel.c
2 *
3 * Driver for Prism II devices which would usually be driven by orinoco_cs,
4 * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in
5 * Nortel emobility, Symbol LA-4113 and Symbol LA-4123.
6 *
7 * Copyright (C) 2002 Tobias Hoffmann
8 * (C) 2003 Christoph Jungegger <disdos@traum404.de>
9 *
10 * Some of this code is borrowed from orinoco_plx.c
11 * Copyright (C) 2001 Daniel Barlow
12 * Some of this code is borrowed from orinoco_pci.c
13 * Copyright (C) 2001 Jean Tourrilhes
14 * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
15 * has been copied from it. linux-wlan-ng-0.1.10 is originally :
16 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
17 *
18 * The contents of this file are subject to the Mozilla Public License
19 * Version 1.1 (the "License"); you may not use this file except in
20 * compliance with the License. You may obtain a copy of the License
21 * at http://www.mozilla.org/MPL/
22 *
23 * Software distributed under the License is distributed on an "AS IS"
24 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
25 * the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * Alternatively, the contents of this file may be used under the
29 * terms of the GNU General Public License version 2 (the "GPL"), in
30 * which case the provisions of the GPL are applicable instead of the
31 * above. If you wish to allow the use of your version of this file
32 * only under the terms of the GPL and not to allow others to use your
33 * version of this file under the MPL, indicate your decision by
34 * deleting the provisions above and replace them with the notice and
35 * other provisions required by the GPL. If you do not delete the
36 * provisions above, a recipient may use your version of this file
37 * under either the MPL or the GPL.
38 */
39
40#define DRIVER_NAME "orinoco_nortel"
41#define PFX DRIVER_NAME ": "
42
43#include <linux/module.h>
44#include <linux/kernel.h>
45#include <linux/init.h>
46#include <linux/delay.h>
47#include <linux/pci.h>
48#include <pcmcia/cisreg.h>
49
50#include "orinoco.h"
51#include "orinoco_pci.h"
52
53#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */
54#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
55
56
57/*
58 * Do a soft reset of the card using the Configuration Option Register
59 * We need this to get going...
60 * This is the part of the code that is strongly inspired from wlan-ng
61 *
62 * Note bis : Don't try to access HERMES_CMD during the reset phase.
63 * It just won't work !
64 */
65static int orinoco_nortel_cor_reset(struct orinoco_private *priv)
66{
67 struct orinoco_pci_card *card = priv->card;
68
69 /* Assert the reset until the card notices */
70 iowrite16(8, card->bridge_io + 2);
71 ioread16(card->attr_io + COR_OFFSET);
72 iowrite16(0x80, card->attr_io + COR_OFFSET);
73 mdelay(1);
74
75 /* Give time for the card to recover from this hard effort */
76 iowrite16(0, card->attr_io + COR_OFFSET);
77 iowrite16(0, card->attr_io + COR_OFFSET);
78 mdelay(1);
79
80 /* Set COR as usual */
81 iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
82 iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
83 mdelay(1);
84
85 iowrite16(0x228, card->bridge_io + 2);
86
87 return 0;
88}
89
90static int orinoco_nortel_hw_init(struct orinoco_pci_card *card)
91{
92 int i;
93 u32 reg;
94
95 /* Setup bridge */
96 if (ioread16(card->bridge_io) & 1) {
97 printk(KERN_ERR PFX "brg1 answer1 wrong\n");
98 return -EBUSY;
99 }
100 iowrite16(0x118, card->bridge_io + 2);
101 iowrite16(0x108, card->bridge_io + 2);
102 mdelay(30);
103 iowrite16(0x8, card->bridge_io + 2);
104 for (i = 0; i < 30; i++) {
105 mdelay(30);
106 if (ioread16(card->bridge_io) & 0x10) {
107 break;
108 }
109 }
110 if (i == 30) {
111 printk(KERN_ERR PFX "brg1 timed out\n");
112 return -EBUSY;
113 }
114 if (ioread16(card->attr_io + COR_OFFSET) & 1) {
115 printk(KERN_ERR PFX "brg2 answer1 wrong\n");
116 return -EBUSY;
117 }
118 if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) {
119 printk(KERN_ERR PFX "brg2 answer2 wrong\n");
120 return -EBUSY;
121 }
122 if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) {
123 printk(KERN_ERR PFX "brg2 answer3 wrong\n");
124 return -EBUSY;
125 }
126
127 /* Set the PCMCIA COR register */
128 iowrite16(COR_VALUE, card->attr_io + COR_OFFSET);
129 mdelay(1);
130 reg = ioread16(card->attr_io + COR_OFFSET);
131 if (reg != COR_VALUE) {
132 printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n",
133 reg);
134 return -EBUSY;
135 }
136
137 /* Set LEDs */
138 iowrite16(1, card->bridge_io + 10);
139 return 0;
140}
141
142static int orinoco_nortel_init_one(struct pci_dev *pdev,
143 const struct pci_device_id *ent)
144{
145 int err;
146 struct orinoco_private *priv;
147 struct orinoco_pci_card *card;
148 struct net_device *dev;
149 void __iomem *hermes_io, *bridge_io, *attr_io;
150
151 err = pci_enable_device(pdev);
152 if (err) {
153 printk(KERN_ERR PFX "Cannot enable PCI device\n");
154 return err;
155 }
156
157 err = pci_request_regions(pdev, DRIVER_NAME);
158 if (err) {
159 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
160 goto fail_resources;
161 }
162
163 bridge_io = pci_iomap(pdev, 0, 0);
164 if (!bridge_io) {
165 printk(KERN_ERR PFX "Cannot map bridge registers\n");
166 err = -EIO;
167 goto fail_map_bridge;
168 }
169
170 attr_io = pci_iomap(pdev, 1, 0);
171 if (!attr_io) {
172 printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
173 err = -EIO;
174 goto fail_map_attr;
175 }
176
177 hermes_io = pci_iomap(pdev, 2, 0);
178 if (!hermes_io) {
179 printk(KERN_ERR PFX "Cannot map chipset registers\n");
180 err = -EIO;
181 goto fail_map_hermes;
182 }
183
184 /* Allocate network device */
185 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
186 orinoco_nortel_cor_reset, NULL);
187 if (!dev) {
188 printk(KERN_ERR PFX "Cannot allocate network device\n");
189 err = -ENOMEM;
190 goto fail_alloc;
191 }
192
193 priv = netdev_priv(dev);
194 card = priv->card;
195 card->bridge_io = bridge_io;
196 card->attr_io = attr_io;
197 SET_NETDEV_DEV(dev, &pdev->dev);
198
199 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
200
201 err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
202 dev->name, dev);
203 if (err) {
204 printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
205 err = -EBUSY;
206 goto fail_irq;
207 }
208
209 err = orinoco_nortel_hw_init(card);
210 if (err) {
211 printk(KERN_ERR PFX "Hardware initialization failed\n");
212 goto fail;
213 }
214
215 err = orinoco_nortel_cor_reset(priv);
216 if (err) {
217 printk(KERN_ERR PFX "Initial reset failed\n");
218 goto fail;
219 }
220
221 err = register_netdev(dev);
222 if (err) {
223 printk(KERN_ERR PFX "Cannot register network device\n");
224 goto fail;
225 }
226
227 pci_set_drvdata(pdev, dev);
228 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
229 pci_name(pdev));
230
231 return 0;
232
233 fail:
234 free_irq(pdev->irq, dev);
235
236 fail_irq:
237 pci_set_drvdata(pdev, NULL);
238 free_orinocodev(dev);
239
240 fail_alloc:
241 pci_iounmap(pdev, hermes_io);
242
243 fail_map_hermes:
244 pci_iounmap(pdev, attr_io);
245
246 fail_map_attr:
247 pci_iounmap(pdev, bridge_io);
248
249 fail_map_bridge:
250 pci_release_regions(pdev);
251
252 fail_resources:
253 pci_disable_device(pdev);
254
255 return err;
256}
257
258static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev)
259{
260 struct net_device *dev = pci_get_drvdata(pdev);
261 struct orinoco_private *priv = netdev_priv(dev);
262 struct orinoco_pci_card *card = priv->card;
263
264 /* Clear LEDs */
265 iowrite16(0, card->bridge_io + 10);
266
267 unregister_netdev(dev);
268 free_irq(pdev->irq, dev);
269 pci_set_drvdata(pdev, NULL);
270 free_orinocodev(dev);
271 pci_iounmap(pdev, priv->hw.iobase);
272 pci_iounmap(pdev, card->attr_io);
273 pci_iounmap(pdev, card->bridge_io);
274 pci_release_regions(pdev);
275 pci_disable_device(pdev);
276}
277
278static struct pci_device_id orinoco_nortel_id_table[] = {
279 /* Nortel emobility PCI */
280 {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,},
281 /* Symbol LA-4123 PCI */
282 {0x1562, 0x0001, PCI_ANY_ID, PCI_ANY_ID,},
283 {0,},
284};
285
286MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table);
287
288static struct pci_driver orinoco_nortel_driver = {
289 .name = DRIVER_NAME,
290 .id_table = orinoco_nortel_id_table,
291 .probe = orinoco_nortel_init_one,
292 .remove = __devexit_p(orinoco_nortel_remove_one),
293 .suspend = orinoco_pci_suspend,
294 .resume = orinoco_pci_resume,
295};
296
297static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
298 " (Tobias Hoffmann & Christoph Jungegger <disdos@traum404.de>)";
299MODULE_AUTHOR("Christoph Jungegger <disdos@traum404.de>");
300MODULE_DESCRIPTION
301 ("Driver for wireless LAN cards using the Nortel PCI bridge");
302MODULE_LICENSE("Dual MPL/GPL");
303
304static int __init orinoco_nortel_init(void)
305{
306 printk(KERN_DEBUG "%s\n", version);
307 return pci_register_driver(&orinoco_nortel_driver);
308}
309
310static void __exit orinoco_nortel_exit(void)
311{
312 pci_unregister_driver(&orinoco_nortel_driver);
313}
314
315module_init(orinoco_nortel_init);
316module_exit(orinoco_nortel_exit);
317
318/*
319 * Local variables:
320 * c-indent-level: 8
321 * c-basic-offset: 8
322 * tab-width: 8
323 * End:
324 */
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c
new file mode 100644
index 000000000000..4ebd638a073e
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco_pci.c
@@ -0,0 +1,264 @@
1/* orinoco_pci.c
2 *
3 * Driver for Prism 2.5/3 devices that have a direct PCI interface
4 * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge).
5 * The card contains only one PCI region, which contains all the usual
6 * hermes registers, as well as the COR register.
7 *
8 * Current maintainers are:
9 * Pavel Roskin <proski AT gnu.org>
10 * and David Gibson <hermes AT gibson.dropbear.id.au>
11 *
12 * Some of this code is borrowed from orinoco_plx.c
13 * Copyright (C) 2001 Daniel Barlow <dan AT telent.net>
14 * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing
15 * has been copied from it. linux-wlan-ng-0.1.10 is originally :
16 * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved.
17 * This file originally written by:
18 * Copyright (C) 2001 Jean Tourrilhes <jt AT hpl.hp.com>
19 * And is now maintained by:
20 * (C) Copyright David Gibson, IBM Corp. 2002-2003.
21 *
22 * The contents of this file are subject to the Mozilla Public License
23 * Version 1.1 (the "License"); you may not use this file except in
24 * compliance with the License. You may obtain a copy of the License
25 * at http://www.mozilla.org/MPL/
26 *
27 * Software distributed under the License is distributed on an "AS IS"
28 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
29 * the License for the specific language governing rights and
30 * limitations under the License.
31 *
32 * Alternatively, the contents of this file may be used under the
33 * terms of the GNU General Public License version 2 (the "GPL"), in
34 * which case the provisions of the GPL are applicable instead of the
35 * above. If you wish to allow the use of your version of this file
36 * only under the terms of the GPL and not to allow others to use your
37 * version of this file under the MPL, indicate your decision by
38 * deleting the provisions above and replace them with the notice and
39 * other provisions required by the GPL. If you do not delete the
40 * provisions above, a recipient may use your version of this file
41 * under either the MPL or the GPL.
42 */
43
44#define DRIVER_NAME "orinoco_pci"
45#define PFX DRIVER_NAME ": "
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/delay.h>
51#include <linux/pci.h>
52
53#include "orinoco.h"
54#include "orinoco_pci.h"
55
56/* Offset of the COR register of the PCI card */
57#define HERMES_PCI_COR (0x26)
58
59/* Bitmask to reset the card */
60#define HERMES_PCI_COR_MASK (0x0080)
61
62/* Magic timeouts for doing the reset.
63 * Those times are straight from wlan-ng, and it is claimed that they
64 * are necessary. Alan will kill me. Take your time and grab a coffee. */
65#define HERMES_PCI_COR_ONT (250) /* ms */
66#define HERMES_PCI_COR_OFFT (500) /* ms */
67#define HERMES_PCI_COR_BUSYT (500) /* ms */
68
69/*
70 * Do a soft reset of the card using the Configuration Option Register
71 * We need this to get going...
72 * This is the part of the code that is strongly inspired from wlan-ng
73 *
74 * Note : This code is done with irq enabled. This mean that many
75 * interrupts will occur while we are there. This is why we use the
76 * jiffies to regulate time instead of a straight mdelay(). Usually we
77 * need only around 245 iteration of the loop to do 250 ms delay.
78 *
79 * Note bis : Don't try to access HERMES_CMD during the reset phase.
80 * It just won't work !
81 */
82static int orinoco_pci_cor_reset(struct orinoco_private *priv)
83{
84 hermes_t *hw = &priv->hw;
85 unsigned long timeout;
86 u16 reg;
87
88 /* Assert the reset until the card notices */
89 hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK);
90 mdelay(HERMES_PCI_COR_ONT);
91
92 /* Give time for the card to recover from this hard effort */
93 hermes_write_regn(hw, PCI_COR, 0x0000);
94 mdelay(HERMES_PCI_COR_OFFT);
95
96 /* The card is ready when it's no longer busy */
97 timeout = jiffies + (HERMES_PCI_COR_BUSYT * HZ / 1000);
98 reg = hermes_read_regn(hw, CMD);
99 while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
100 mdelay(1);
101 reg = hermes_read_regn(hw, CMD);
102 }
103
104 /* Still busy? */
105 if (reg & HERMES_CMD_BUSY) {
106 printk(KERN_ERR PFX "Busy timeout\n");
107 return -ETIMEDOUT;
108 }
109
110 return 0;
111}
112
113static int orinoco_pci_init_one(struct pci_dev *pdev,
114 const struct pci_device_id *ent)
115{
116 int err;
117 struct orinoco_private *priv;
118 struct orinoco_pci_card *card;
119 struct net_device *dev;
120 void __iomem *hermes_io;
121
122 err = pci_enable_device(pdev);
123 if (err) {
124 printk(KERN_ERR PFX "Cannot enable PCI device\n");
125 return err;
126 }
127
128 err = pci_request_regions(pdev, DRIVER_NAME);
129 if (err) {
130 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
131 goto fail_resources;
132 }
133
134 hermes_io = pci_iomap(pdev, 0, 0);
135 if (!hermes_io) {
136 printk(KERN_ERR PFX "Cannot remap chipset registers\n");
137 err = -EIO;
138 goto fail_map_hermes;
139 }
140
141 /* Allocate network device */
142 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
143 orinoco_pci_cor_reset, NULL);
144 if (!dev) {
145 printk(KERN_ERR PFX "Cannot allocate network device\n");
146 err = -ENOMEM;
147 goto fail_alloc;
148 }
149
150 priv = netdev_priv(dev);
151 card = priv->card;
152 SET_NETDEV_DEV(dev, &pdev->dev);
153
154 hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING);
155
156 err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
157 dev->name, dev);
158 if (err) {
159 printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
160 err = -EBUSY;
161 goto fail_irq;
162 }
163
164 err = orinoco_pci_cor_reset(priv);
165 if (err) {
166 printk(KERN_ERR PFX "Initial reset failed\n");
167 goto fail;
168 }
169
170 err = register_netdev(dev);
171 if (err) {
172 printk(KERN_ERR PFX "Cannot register network device\n");
173 goto fail;
174 }
175
176 pci_set_drvdata(pdev, dev);
177 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
178 pci_name(pdev));
179
180 return 0;
181
182 fail:
183 free_irq(pdev->irq, dev);
184
185 fail_irq:
186 pci_set_drvdata(pdev, NULL);
187 free_orinocodev(dev);
188
189 fail_alloc:
190 pci_iounmap(pdev, hermes_io);
191
192 fail_map_hermes:
193 pci_release_regions(pdev);
194
195 fail_resources:
196 pci_disable_device(pdev);
197
198 return err;
199}
200
201static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev)
202{
203 struct net_device *dev = pci_get_drvdata(pdev);
204 struct orinoco_private *priv = netdev_priv(dev);
205
206 unregister_netdev(dev);
207 free_irq(pdev->irq, dev);
208 pci_set_drvdata(pdev, NULL);
209 free_orinocodev(dev);
210 pci_iounmap(pdev, priv->hw.iobase);
211 pci_release_regions(pdev);
212 pci_disable_device(pdev);
213}
214
215static struct pci_device_id orinoco_pci_id_table[] = {
216 /* Intersil Prism 3 */
217 {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,},
218 /* Intersil Prism 2.5 */
219 {0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,},
220 /* Samsung MagicLAN SWL-2210P */
221 {0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,},
222 {0,},
223};
224
225MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table);
226
227static struct pci_driver orinoco_pci_driver = {
228 .name = DRIVER_NAME,
229 .id_table = orinoco_pci_id_table,
230 .probe = orinoco_pci_init_one,
231 .remove = __devexit_p(orinoco_pci_remove_one),
232 .suspend = orinoco_pci_suspend,
233 .resume = orinoco_pci_resume,
234};
235
236static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
237 " (Pavel Roskin <proski@gnu.org>,"
238 " David Gibson <hermes@gibson.dropbear.id.au> &"
239 " Jean Tourrilhes <jt@hpl.hp.com>)";
240MODULE_AUTHOR("Pavel Roskin <proski@gnu.org> & David Gibson <hermes@gibson.dropbear.id.au>");
241MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface");
242MODULE_LICENSE("Dual MPL/GPL");
243
244static int __init orinoco_pci_init(void)
245{
246 printk(KERN_DEBUG "%s\n", version);
247 return pci_register_driver(&orinoco_pci_driver);
248}
249
250static void __exit orinoco_pci_exit(void)
251{
252 pci_unregister_driver(&orinoco_pci_driver);
253}
254
255module_init(orinoco_pci_init);
256module_exit(orinoco_pci_exit);
257
258/*
259 * Local variables:
260 * c-indent-level: 8
261 * c-basic-offset: 8
262 * tab-width: 8
263 * End:
264 */
diff --git a/drivers/net/wireless/orinoco/orinoco_pci.h b/drivers/net/wireless/orinoco/orinoco_pci.h
new file mode 100644
index 000000000000..f4e5e06760c1
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco_pci.h
@@ -0,0 +1,109 @@
1/* orinoco_pci.h
2 *
3 * Common code for all Orinoco drivers for PCI devices, including
4 * both native PCI and PCMCIA-to-PCI bridges.
5 *
6 * Copyright (C) 2005, Pavel Roskin.
7 * See orinoco.c for license.
8 */
9
10#ifndef _ORINOCO_PCI_H
11#define _ORINOCO_PCI_H
12
13#include <linux/netdevice.h>
14
15/* Driver specific data */
16struct orinoco_pci_card {
17 void __iomem *bridge_io;
18 void __iomem *attr_io;
19};
20
21#ifdef CONFIG_PM
22static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state)
23{
24 struct net_device *dev = pci_get_drvdata(pdev);
25 struct orinoco_private *priv = netdev_priv(dev);
26 unsigned long flags;
27 int err;
28
29 err = orinoco_lock(priv, &flags);
30 if (err) {
31 printk(KERN_ERR "%s: cannot lock hardware for suspend\n",
32 dev->name);
33 return err;
34 }
35
36 err = __orinoco_down(dev);
37 if (err)
38 printk(KERN_WARNING "%s: error %d bringing interface down "
39 "for suspend\n", dev->name, err);
40
41 netif_device_detach(dev);
42
43 priv->hw_unavailable++;
44
45 orinoco_unlock(priv, &flags);
46
47 free_irq(pdev->irq, dev);
48 pci_save_state(pdev);
49 pci_disable_device(pdev);
50 pci_set_power_state(pdev, PCI_D3hot);
51
52 return 0;
53}
54
55static int orinoco_pci_resume(struct pci_dev *pdev)
56{
57 struct net_device *dev = pci_get_drvdata(pdev);
58 struct orinoco_private *priv = netdev_priv(dev);
59 unsigned long flags;
60 int err;
61
62 pci_set_power_state(pdev, 0);
63 err = pci_enable_device(pdev);
64 if (err) {
65 printk(KERN_ERR "%s: pci_enable_device failed on resume\n",
66 dev->name);
67 return err;
68 }
69 pci_restore_state(pdev);
70
71 err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
72 dev->name, dev);
73 if (err) {
74 printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n",
75 dev->name);
76 pci_disable_device(pdev);
77 return -EBUSY;
78 }
79
80 err = orinoco_reinit_firmware(dev);
81 if (err) {
82 printk(KERN_ERR "%s: error %d re-initializing firmware "
83 "on resume\n", dev->name, err);
84 return err;
85 }
86
87 spin_lock_irqsave(&priv->lock, flags);
88
89 netif_device_attach(dev);
90
91 priv->hw_unavailable--;
92
93 if (priv->open && (! priv->hw_unavailable)) {
94 err = __orinoco_up(dev);
95 if (err)
96 printk(KERN_ERR "%s: Error %d restarting card on resume\n",
97 dev->name, err);
98 }
99
100 spin_unlock_irqrestore(&priv->lock, flags);
101
102 return 0;
103}
104#else
105#define orinoco_pci_suspend NULL
106#define orinoco_pci_resume NULL
107#endif
108
109#endif /* _ORINOCO_PCI_H */
diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c
new file mode 100644
index 000000000000..ef761857bb38
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco_plx.c
@@ -0,0 +1,371 @@
1/* orinoco_plx.c
2 *
3 * Driver for Prism II devices which would usually be driven by orinoco_cs,
4 * but are connected to the PCI bus by a PLX9052.
5 *
6 * Current maintainers are:
7 * Pavel Roskin <proski AT gnu.org>
8 * and David Gibson <hermes AT gibson.dropbear.id.au>
9 *
10 * (C) Copyright David Gibson, IBM Corp. 2001-2003.
11 * Copyright (C) 2001 Daniel Barlow
12 *
13 * The contents of this file are subject to the Mozilla Public License
14 * Version 1.1 (the "License"); you may not use this file except in
15 * compliance with the License. You may obtain a copy of the License
16 * at http://www.mozilla.org/MPL/
17 *
18 * Software distributed under the License is distributed on an "AS IS"
19 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
20 * the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * Alternatively, the contents of this file may be used under the
24 * terms of the GNU General Public License version 2 (the "GPL"), in
25 * which case the provisions of the GPL are applicable instead of the
26 * above. If you wish to allow the use of your version of this file
27 * only under the terms of the GPL and not to allow others to use your
28 * version of this file under the MPL, indicate your decision by
29 * deleting the provisions above and replace them with the notice and
30 * other provisions required by the GPL. If you do not delete the
31 * provisions above, a recipient may use your version of this file
32 * under either the MPL or the GPL.
33 *
34 * Here's the general details on how the PLX9052 adapter works:
35 *
36 * - Two PCI I/O address spaces, one 0x80 long which contains the
37 * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA
38 * slot I/O address space.
39 *
40 * - One PCI memory address space, mapped to the PCMCIA attribute space
41 * (containing the CIS).
42 *
43 * Using the later, you can read through the CIS data to make sure the
44 * card is compatible with the driver. Keep in mind that the PCMCIA
45 * spec specifies the CIS as the lower 8 bits of each word read from
46 * the CIS, so to read the bytes of the CIS, read every other byte
47 * (0,2,4,...). Passing that test, you need to enable the I/O address
48 * space on the PCMCIA card via the PCMCIA COR register. This is the
49 * first byte following the CIS. In my case (which may not have any
50 * relation to what's on the PRISM2 cards), COR was at offset 0x800
51 * within the PCI memory space. Write 0x41 to the COR register to
52 * enable I/O mode and to select level triggered interrupts. To
53 * confirm you actually succeeded, read the COR register back and make
54 * sure it actually got set to 0x41, in case you have an unexpected
55 * card inserted.
56 *
57 * Following that, you can treat the second PCI I/O address space (the
58 * one that's not 0x80 in length) as the PCMCIA I/O space.
59 *
60 * Note that in the Eumitcom's source for their drivers, they register
61 * the interrupt as edge triggered when registering it with the
62 * Windows kernel. I don't recall how to register edge triggered on
63 * Linux (if it can be done at all). But in some experimentation, I
64 * don't see much operational difference between using either
65 * interrupt mode. Don't mess with the interrupt mode in the COR
66 * register though, as the PLX9052 wants level triggers with the way
67 * the serial EEPROM configures it on the WL11000.
68 *
69 * There's some other little quirks related to timing that I bumped
70 * into, but I don't recall right now. Also, there's two variants of
71 * the WL11000 I've seen, revision A1 and T2. These seem to differ
72 * slightly in the timings configured in the wait-state generator in
73 * the PLX9052. There have also been some comments from Eumitcom that
74 * cards shouldn't be hot swapped, apparently due to risk of cooking
75 * the PLX9052. I'm unsure why they believe this, as I can't see
76 * anything in the design that would really cause a problem, except
77 * for crashing drivers not written to expect it. And having developed
78 * drivers for the WL11000, I'd say it's quite tricky to write code
79 * that will successfully deal with a hot unplug. Very odd things
80 * happen on the I/O side of things. But anyway, be warned. Despite
81 * that, I've hot-swapped a number of times during debugging and
82 * driver development for various reasons (stuck WAIT# line after the
83 * radio card's firmware locks up).
84 */
85
86#define DRIVER_NAME "orinoco_plx"
87#define PFX DRIVER_NAME ": "
88
89#include <linux/module.h>
90#include <linux/kernel.h>
91#include <linux/init.h>
92#include <linux/delay.h>
93#include <linux/pci.h>
94#include <pcmcia/cisreg.h>
95
96#include "orinoco.h"
97#include "orinoco_pci.h"
98
99#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */
100#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
101#define COR_RESET (0x80) /* reset bit in the COR register */
102#define PLX_RESET_TIME (500) /* milliseconds */
103
104#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */
105#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */
106
107/*
108 * Do a soft reset of the card using the Configuration Option Register
109 */
110static int orinoco_plx_cor_reset(struct orinoco_private *priv)
111{
112 hermes_t *hw = &priv->hw;
113 struct orinoco_pci_card *card = priv->card;
114 unsigned long timeout;
115 u16 reg;
116
117 iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET);
118 mdelay(1);
119
120 iowrite8(COR_VALUE, card->attr_io + COR_OFFSET);
121 mdelay(1);
122
123 /* Just in case, wait more until the card is no longer busy */
124 timeout = jiffies + (PLX_RESET_TIME * HZ / 1000);
125 reg = hermes_read_regn(hw, CMD);
126 while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
127 mdelay(1);
128 reg = hermes_read_regn(hw, CMD);
129 }
130
131 /* Still busy? */
132 if (reg & HERMES_CMD_BUSY) {
133 printk(KERN_ERR PFX "Busy timeout\n");
134 return -ETIMEDOUT;
135 }
136
137 return 0;
138}
139
140static int orinoco_plx_hw_init(struct orinoco_pci_card *card)
141{
142 int i;
143 u32 csr_reg;
144 static const u8 cis_magic[] = {
145 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67
146 };
147
148 printk(KERN_DEBUG PFX "CIS: ");
149 for (i = 0; i < 16; i++) {
150 printk("%02X:", ioread8(card->attr_io + (i << 1)));
151 }
152 printk("\n");
153
154 /* Verify whether a supported PC card is present */
155 /* FIXME: we probably need to be smarted about this */
156 for (i = 0; i < sizeof(cis_magic); i++) {
157 if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) {
158 printk(KERN_ERR PFX "The CIS value of Prism2 PC "
159 "card is unexpected\n");
160 return -ENODEV;
161 }
162 }
163
164 /* bjoern: We need to tell the card to enable interrupts, in
165 case the serial eprom didn't do this already. See the
166 PLX9052 data book, p8-1 and 8-24 for reference. */
167 csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
168 if (!(csr_reg & PLX_INTCSR_INTEN)) {
169 csr_reg |= PLX_INTCSR_INTEN;
170 iowrite32(csr_reg, card->bridge_io + PLX_INTCSR);
171 csr_reg = ioread32(card->bridge_io + PLX_INTCSR);
172 if (!(csr_reg & PLX_INTCSR_INTEN)) {
173 printk(KERN_ERR PFX "Cannot enable interrupts\n");
174 return -EIO;
175 }
176 }
177
178 return 0;
179}
180
181static int orinoco_plx_init_one(struct pci_dev *pdev,
182 const struct pci_device_id *ent)
183{
184 int err;
185 struct orinoco_private *priv;
186 struct orinoco_pci_card *card;
187 struct net_device *dev;
188 void __iomem *hermes_io, *attr_io, *bridge_io;
189
190 err = pci_enable_device(pdev);
191 if (err) {
192 printk(KERN_ERR PFX "Cannot enable PCI device\n");
193 return err;
194 }
195
196 err = pci_request_regions(pdev, DRIVER_NAME);
197 if (err) {
198 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
199 goto fail_resources;
200 }
201
202 bridge_io = pci_iomap(pdev, 1, 0);
203 if (!bridge_io) {
204 printk(KERN_ERR PFX "Cannot map bridge registers\n");
205 err = -EIO;
206 goto fail_map_bridge;
207 }
208
209 attr_io = pci_iomap(pdev, 2, 0);
210 if (!attr_io) {
211 printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n");
212 err = -EIO;
213 goto fail_map_attr;
214 }
215
216 hermes_io = pci_iomap(pdev, 3, 0);
217 if (!hermes_io) {
218 printk(KERN_ERR PFX "Cannot map chipset registers\n");
219 err = -EIO;
220 goto fail_map_hermes;
221 }
222
223 /* Allocate network device */
224 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
225 orinoco_plx_cor_reset, NULL);
226 if (!dev) {
227 printk(KERN_ERR PFX "Cannot allocate network device\n");
228 err = -ENOMEM;
229 goto fail_alloc;
230 }
231
232 priv = netdev_priv(dev);
233 card = priv->card;
234 card->bridge_io = bridge_io;
235 card->attr_io = attr_io;
236 SET_NETDEV_DEV(dev, &pdev->dev);
237
238 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
239
240 err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
241 dev->name, dev);
242 if (err) {
243 printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
244 err = -EBUSY;
245 goto fail_irq;
246 }
247
248 err = orinoco_plx_hw_init(card);
249 if (err) {
250 printk(KERN_ERR PFX "Hardware initialization failed\n");
251 goto fail;
252 }
253
254 err = orinoco_plx_cor_reset(priv);
255 if (err) {
256 printk(KERN_ERR PFX "Initial reset failed\n");
257 goto fail;
258 }
259
260 err = register_netdev(dev);
261 if (err) {
262 printk(KERN_ERR PFX "Cannot register network device\n");
263 goto fail;
264 }
265
266 pci_set_drvdata(pdev, dev);
267 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
268 pci_name(pdev));
269
270 return 0;
271
272 fail:
273 free_irq(pdev->irq, dev);
274
275 fail_irq:
276 pci_set_drvdata(pdev, NULL);
277 free_orinocodev(dev);
278
279 fail_alloc:
280 pci_iounmap(pdev, hermes_io);
281
282 fail_map_hermes:
283 pci_iounmap(pdev, attr_io);
284
285 fail_map_attr:
286 pci_iounmap(pdev, bridge_io);
287
288 fail_map_bridge:
289 pci_release_regions(pdev);
290
291 fail_resources:
292 pci_disable_device(pdev);
293
294 return err;
295}
296
297static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev)
298{
299 struct net_device *dev = pci_get_drvdata(pdev);
300 struct orinoco_private *priv = netdev_priv(dev);
301 struct orinoco_pci_card *card = priv->card;
302
303 unregister_netdev(dev);
304 free_irq(pdev->irq, dev);
305 pci_set_drvdata(pdev, NULL);
306 free_orinocodev(dev);
307 pci_iounmap(pdev, priv->hw.iobase);
308 pci_iounmap(pdev, card->attr_io);
309 pci_iounmap(pdev, card->bridge_io);
310 pci_release_regions(pdev);
311 pci_disable_device(pdev);
312}
313
314static struct pci_device_id orinoco_plx_id_table[] = {
315 {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */
316 {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */
317 {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */
318 {0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* SMC EZConnect SMC2602W,
319 Eumitcom PCI WL11000,
320 Addtron AWA-100 */
321 {0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* Global Sun Tech GL24110P */
322 {0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,}, /* Reported working, but unknown */
323 {0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,}, /* Linksys WDT11 */
324 {0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */
325 {0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 tested by
326 Brendan W. McAdams <rit AT jacked-in.org> */
327 {0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,}, /* 3Com AirConnect PCI tested by
328 Damien Persohn <damien AT persohn.net> */
329 {0,},
330};
331
332MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table);
333
334static struct pci_driver orinoco_plx_driver = {
335 .name = DRIVER_NAME,
336 .id_table = orinoco_plx_id_table,
337 .probe = orinoco_plx_init_one,
338 .remove = __devexit_p(orinoco_plx_remove_one),
339 .suspend = orinoco_pci_suspend,
340 .resume = orinoco_pci_resume,
341};
342
343static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
344 " (Pavel Roskin <proski@gnu.org>,"
345 " David Gibson <hermes@gibson.dropbear.id.au>,"
346 " Daniel Barlow <dan@telent.net>)";
347MODULE_AUTHOR("Daniel Barlow <dan@telent.net>");
348MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge");
349MODULE_LICENSE("Dual MPL/GPL");
350
351static int __init orinoco_plx_init(void)
352{
353 printk(KERN_DEBUG "%s\n", version);
354 return pci_register_driver(&orinoco_plx_driver);
355}
356
357static void __exit orinoco_plx_exit(void)
358{
359 pci_unregister_driver(&orinoco_plx_driver);
360}
361
362module_init(orinoco_plx_init);
363module_exit(orinoco_plx_exit);
364
365/*
366 * Local variables:
367 * c-indent-level: 8
368 * c-basic-offset: 8
369 * tab-width: 8
370 * End:
371 */
diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c
new file mode 100644
index 000000000000..ede24ec309c0
--- /dev/null
+++ b/drivers/net/wireless/orinoco/orinoco_tmd.c
@@ -0,0 +1,248 @@
1/* orinoco_tmd.c
2 *
3 * Driver for Prism II devices which would usually be driven by orinoco_cs,
4 * but are connected to the PCI bus by a TMD7160.
5 *
6 * Copyright (C) 2003 Joerg Dorchain <joerg AT dorchain.net>
7 * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow
8 *
9 * The contents of this file are subject to the Mozilla Public License
10 * Version 1.1 (the "License"); you may not use this file except in
11 * compliance with the License. You may obtain a copy of the License
12 * at http://www.mozilla.org/MPL/
13 *
14 * Software distributed under the License is distributed on an "AS IS"
15 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
16 * the License for the specific language governing rights and
17 * limitations under the License.
18 *
19 * Alternatively, the contents of this file may be used under the
20 * terms of the GNU General Public License version 2 (the "GPL"), in
21 * which case the provisions of the GPL are applicable instead of the
22 * above. If you wish to allow the use of your version of this file
23 * only under the terms of the GPL and not to allow others to use your
24 * version of this file under the MPL, indicate your decision by
25 * deleting the provisions above and replace them with the notice and
26 * other provisions required by the GPL. If you do not delete the
27 * provisions above, a recipient may use your version of this file
28 * under either the MPL or the GPL.
29 *
30 * The actual driving is done by orinoco.c, this is just resource
31 * allocation stuff.
32 *
33 * This driver is modeled after the orinoco_plx driver. The main
34 * difference is that the TMD chip has only IO port ranges and doesn't
35 * provide access to the PCMCIA attribute space.
36 *
37 * Pheecom sells cards with the TMD chip as "ASIC version"
38 */
39
40#define DRIVER_NAME "orinoco_tmd"
41#define PFX DRIVER_NAME ": "
42
43#include <linux/module.h>
44#include <linux/kernel.h>
45#include <linux/init.h>
46#include <linux/delay.h>
47#include <linux/pci.h>
48#include <pcmcia/cisreg.h>
49
50#include "orinoco.h"
51#include "orinoco_pci.h"
52
53#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */
54#define COR_RESET (0x80) /* reset bit in the COR register */
55#define TMD_RESET_TIME (500) /* milliseconds */
56
57/*
58 * Do a soft reset of the card using the Configuration Option Register
59 */
60static int orinoco_tmd_cor_reset(struct orinoco_private *priv)
61{
62 hermes_t *hw = &priv->hw;
63 struct orinoco_pci_card *card = priv->card;
64 unsigned long timeout;
65 u16 reg;
66
67 iowrite8(COR_VALUE | COR_RESET, card->bridge_io);
68 mdelay(1);
69
70 iowrite8(COR_VALUE, card->bridge_io);
71 mdelay(1);
72
73 /* Just in case, wait more until the card is no longer busy */
74 timeout = jiffies + (TMD_RESET_TIME * HZ / 1000);
75 reg = hermes_read_regn(hw, CMD);
76 while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) {
77 mdelay(1);
78 reg = hermes_read_regn(hw, CMD);
79 }
80
81 /* Still busy? */
82 if (reg & HERMES_CMD_BUSY) {
83 printk(KERN_ERR PFX "Busy timeout\n");
84 return -ETIMEDOUT;
85 }
86
87 return 0;
88}
89
90
91static int orinoco_tmd_init_one(struct pci_dev *pdev,
92 const struct pci_device_id *ent)
93{
94 int err;
95 struct orinoco_private *priv;
96 struct orinoco_pci_card *card;
97 struct net_device *dev;
98 void __iomem *hermes_io, *bridge_io;
99
100 err = pci_enable_device(pdev);
101 if (err) {
102 printk(KERN_ERR PFX "Cannot enable PCI device\n");
103 return err;
104 }
105
106 err = pci_request_regions(pdev, DRIVER_NAME);
107 if (err) {
108 printk(KERN_ERR PFX "Cannot obtain PCI resources\n");
109 goto fail_resources;
110 }
111
112 bridge_io = pci_iomap(pdev, 1, 0);
113 if (!bridge_io) {
114 printk(KERN_ERR PFX "Cannot map bridge registers\n");
115 err = -EIO;
116 goto fail_map_bridge;
117 }
118
119 hermes_io = pci_iomap(pdev, 2, 0);
120 if (!hermes_io) {
121 printk(KERN_ERR PFX "Cannot map chipset registers\n");
122 err = -EIO;
123 goto fail_map_hermes;
124 }
125
126 /* Allocate network device */
127 dev = alloc_orinocodev(sizeof(*card), &pdev->dev,
128 orinoco_tmd_cor_reset, NULL);
129 if (!dev) {
130 printk(KERN_ERR PFX "Cannot allocate network device\n");
131 err = -ENOMEM;
132 goto fail_alloc;
133 }
134
135 priv = netdev_priv(dev);
136 card = priv->card;
137 card->bridge_io = bridge_io;
138 SET_NETDEV_DEV(dev, &pdev->dev);
139
140 hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING);
141
142 err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED,
143 dev->name, dev);
144 if (err) {
145 printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq);
146 err = -EBUSY;
147 goto fail_irq;
148 }
149
150 err = orinoco_tmd_cor_reset(priv);
151 if (err) {
152 printk(KERN_ERR PFX "Initial reset failed\n");
153 goto fail;
154 }
155
156 err = register_netdev(dev);
157 if (err) {
158 printk(KERN_ERR PFX "Cannot register network device\n");
159 goto fail;
160 }
161
162 pci_set_drvdata(pdev, dev);
163 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s\n", dev->name,
164 pci_name(pdev));
165
166 return 0;
167
168 fail:
169 free_irq(pdev->irq, dev);
170
171 fail_irq:
172 pci_set_drvdata(pdev, NULL);
173 free_orinocodev(dev);
174
175 fail_alloc:
176 pci_iounmap(pdev, hermes_io);
177
178 fail_map_hermes:
179 pci_iounmap(pdev, bridge_io);
180
181 fail_map_bridge:
182 pci_release_regions(pdev);
183
184 fail_resources:
185 pci_disable_device(pdev);
186
187 return err;
188}
189
190static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev)
191{
192 struct net_device *dev = pci_get_drvdata(pdev);
193 struct orinoco_private *priv = netdev_priv(dev);
194 struct orinoco_pci_card *card = priv->card;
195
196 unregister_netdev(dev);
197 free_irq(pdev->irq, dev);
198 pci_set_drvdata(pdev, NULL);
199 free_orinocodev(dev);
200 pci_iounmap(pdev, priv->hw.iobase);
201 pci_iounmap(pdev, card->bridge_io);
202 pci_release_regions(pdev);
203 pci_disable_device(pdev);
204}
205
206static struct pci_device_id orinoco_tmd_id_table[] = {
207 {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */
208 {0,},
209};
210
211MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table);
212
213static struct pci_driver orinoco_tmd_driver = {
214 .name = DRIVER_NAME,
215 .id_table = orinoco_tmd_id_table,
216 .probe = orinoco_tmd_init_one,
217 .remove = __devexit_p(orinoco_tmd_remove_one),
218 .suspend = orinoco_pci_suspend,
219 .resume = orinoco_pci_resume,
220};
221
222static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
223 " (Joerg Dorchain <joerg@dorchain.net>)";
224MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
225MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge");
226MODULE_LICENSE("Dual MPL/GPL");
227
228static int __init orinoco_tmd_init(void)
229{
230 printk(KERN_DEBUG "%s\n", version);
231 return pci_register_driver(&orinoco_tmd_driver);
232}
233
234static void __exit orinoco_tmd_exit(void)
235{
236 pci_unregister_driver(&orinoco_tmd_driver);
237}
238
239module_init(orinoco_tmd_init);
240module_exit(orinoco_tmd_exit);
241
242/*
243 * Local variables:
244 * c-indent-level: 8
245 * c-basic-offset: 8
246 * tab-width: 8
247 * End:
248 */
diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c
new file mode 100644
index 000000000000..852789ad34b3
--- /dev/null
+++ b/drivers/net/wireless/orinoco/spectrum_cs.c
@@ -0,0 +1,507 @@
1/*
2 * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as
3 * Symbol Wireless Networker LA4137, CompactFlash cards by Socket
4 * Communications and Intel PRO/Wireless 2011B.
5 *
6 * The driver implements Symbol firmware download. The rest is handled
7 * in hermes.c and orinoco.c.
8 *
9 * Utilities for downloading the Symbol firmware are available at
10 * http://sourceforge.net/projects/orinoco/
11 *
12 * Copyright (C) 2002-2005 Pavel Roskin <proski@gnu.org>
13 * Portions based on orinoco_cs.c:
14 * Copyright (C) David Gibson, Linuxcare Australia
15 * Portions based on Spectrum24tDnld.c from original spectrum24 driver:
16 * Copyright (C) Symbol Technologies.
17 *
18 * See copyright notice in file orinoco.c.
19 */
20
21#define DRIVER_NAME "spectrum_cs"
22#define PFX DRIVER_NAME ": "
23
24#include <linux/module.h>
25#include <linux/kernel.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <pcmcia/cs_types.h>
29#include <pcmcia/cs.h>
30#include <pcmcia/cistpl.h>
31#include <pcmcia/cisreg.h>
32#include <pcmcia/ds.h>
33
34#include "orinoco.h"
35
36/********************************************************************/
37/* Module stuff */
38/********************************************************************/
39
40MODULE_AUTHOR("Pavel Roskin <proski@gnu.org>");
41MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader");
42MODULE_LICENSE("Dual MPL/GPL");
43
44/* Module parameters */
45
46/* Some D-Link cards have buggy CIS. They do work at 5v properly, but
47 * don't have any CIS entry for it. This workaround it... */
48static int ignore_cis_vcc; /* = 0 */
49module_param(ignore_cis_vcc, int, 0);
50MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket");
51
52/********************************************************************/
53/* Data structures */
54/********************************************************************/
55
56/* PCMCIA specific device information (goes in the card field of
57 * struct orinoco_private */
58struct orinoco_pccard {
59 struct pcmcia_device *p_dev;
60 dev_node_t node;
61};
62
63/********************************************************************/
64/* Function prototypes */
65/********************************************************************/
66
67static int spectrum_cs_config(struct pcmcia_device *link);
68static void spectrum_cs_release(struct pcmcia_device *link);
69
70/* Constants for the CISREG_CCSR register */
71#define HCR_RUN 0x07 /* run firmware after reset */
72#define HCR_IDLE 0x0E /* don't run firmware after reset */
73#define HCR_MEM16 0x10 /* memory width bit, should be preserved */
74
75
76#define CS_CHECK(fn, ret) \
77 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
78
79/*
80 * Reset the card using configuration registers COR and CCSR.
81 * If IDLE is 1, stop the firmware, so that it can be safely rewritten.
82 */
83static int
84spectrum_reset(struct pcmcia_device *link, int idle)
85{
86 int last_ret, last_fn;
87 conf_reg_t reg;
88 u_int save_cor;
89
90 /* Doing it if hardware is gone is guaranteed crash */
91 if (!pcmcia_dev_present(link))
92 return -ENODEV;
93
94 /* Save original COR value */
95 reg.Function = 0;
96 reg.Action = CS_READ;
97 reg.Offset = CISREG_COR;
98 CS_CHECK(AccessConfigurationRegister,
99 pcmcia_access_configuration_register(link, &reg));
100 save_cor = reg.Value;
101
102 /* Soft-Reset card */
103 reg.Action = CS_WRITE;
104 reg.Offset = CISREG_COR;
105 reg.Value = (save_cor | COR_SOFT_RESET);
106 CS_CHECK(AccessConfigurationRegister,
107 pcmcia_access_configuration_register(link, &reg));
108 udelay(1000);
109
110 /* Read CCSR */
111 reg.Action = CS_READ;
112 reg.Offset = CISREG_CCSR;
113 CS_CHECK(AccessConfigurationRegister,
114 pcmcia_access_configuration_register(link, &reg));
115
116 /*
117 * Start or stop the firmware. Memory width bit should be
118 * preserved from the value we've just read.
119 */
120 reg.Action = CS_WRITE;
121 reg.Offset = CISREG_CCSR;
122 reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16);
123 CS_CHECK(AccessConfigurationRegister,
124 pcmcia_access_configuration_register(link, &reg));
125 udelay(1000);
126
127 /* Restore original COR configuration index */
128 reg.Action = CS_WRITE;
129 reg.Offset = CISREG_COR;
130 reg.Value = (save_cor & ~COR_SOFT_RESET);
131 CS_CHECK(AccessConfigurationRegister,
132 pcmcia_access_configuration_register(link, &reg));
133 udelay(1000);
134 return 0;
135
136 cs_failed:
137 cs_error(link, last_fn, last_ret);
138 return -ENODEV;
139}
140
141/********************************************************************/
142/* Device methods */
143/********************************************************************/
144
145static int
146spectrum_cs_hard_reset(struct orinoco_private *priv)
147{
148 struct orinoco_pccard *card = priv->card;
149 struct pcmcia_device *link = card->p_dev;
150
151 /* Soft reset using COR and HCR */
152 spectrum_reset(link, 0);
153
154 return 0;
155}
156
157static int
158spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle)
159{
160 struct orinoco_pccard *card = priv->card;
161 struct pcmcia_device *link = card->p_dev;
162
163 return spectrum_reset(link, idle);
164}
165
166/********************************************************************/
167/* PCMCIA stuff */
168/********************************************************************/
169
170/*
171 * This creates an "instance" of the driver, allocating local data
172 * structures for one device. The device is registered with Card
173 * Services.
174 *
175 * The dev_link structure is initialized, but we don't actually
176 * configure the card at this point -- we wait until we receive a card
177 * insertion event. */
178static int
179spectrum_cs_probe(struct pcmcia_device *link)
180{
181 struct net_device *dev;
182 struct orinoco_private *priv;
183 struct orinoco_pccard *card;
184
185 dev = alloc_orinocodev(sizeof(*card), &handle_to_dev(link),
186 spectrum_cs_hard_reset,
187 spectrum_cs_stop_firmware);
188 if (! dev)
189 return -ENOMEM;
190 priv = netdev_priv(dev);
191 card = priv->card;
192
193 /* Link both structures together */
194 card->p_dev = link;
195 link->priv = dev;
196
197 /* Interrupt setup */
198 link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT;
199 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
200 link->irq.Handler = orinoco_interrupt;
201 link->irq.Instance = dev;
202
203 /* General socket configuration defaults can go here. In this
204 * client, we assume very little, and rely on the CIS for
205 * almost everything. In most clients, many details (i.e.,
206 * number, sizes, and attributes of IO windows) are fixed by
207 * the nature of the device, and can be hard-wired here. */
208 link->conf.Attributes = 0;
209 link->conf.IntType = INT_MEMORY_AND_IO;
210
211 return spectrum_cs_config(link);
212} /* spectrum_cs_attach */
213
214/*
215 * This deletes a driver "instance". The device is de-registered with
216 * Card Services. If it has been released, all local data structures
217 * are freed. Otherwise, the structures will be freed when the device
218 * is released.
219 */
220static void spectrum_cs_detach(struct pcmcia_device *link)
221{
222 struct net_device *dev = link->priv;
223
224 if (link->dev_node)
225 unregister_netdev(dev);
226
227 spectrum_cs_release(link);
228
229 free_orinocodev(dev);
230} /* spectrum_cs_detach */
231
232/*
233 * spectrum_cs_config() is scheduled to run after a CARD_INSERTION
234 * event is received, to configure the PCMCIA socket, and to make the
235 * device available to the system.
236 */
237
238static int spectrum_cs_config_check(struct pcmcia_device *p_dev,
239 cistpl_cftable_entry_t *cfg,
240 cistpl_cftable_entry_t *dflt,
241 unsigned int vcc,
242 void *priv_data)
243{
244 if (cfg->index == 0)
245 goto next_entry;
246
247 /* Use power settings for Vcc and Vpp if present */
248 /* Note that the CIS values need to be rescaled */
249 if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) {
250 if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) {
251 DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, cfg->vcc.param[CISTPL_POWER_VNOM] / 10000);
252 if (!ignore_cis_vcc)
253 goto next_entry;
254 }
255 } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) {
256 if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) {
257 DEBUG(2, "spectrum_cs_config: Vcc mismatch (vcc = %d, CIS = %d)\n", vcc, dflt->vcc.param[CISTPL_POWER_VNOM] / 10000);
258 if (!ignore_cis_vcc)
259 goto next_entry;
260 }
261 }
262
263 if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM))
264 p_dev->conf.Vpp =
265 cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000;
266 else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM))
267 p_dev->conf.Vpp =
268 dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000;
269
270 /* Do we need to allocate an interrupt? */
271 p_dev->conf.Attributes |= CONF_ENABLE_IRQ;
272
273 /* IO window settings */
274 p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0;
275 if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
276 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
277 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
278 if (!(io->flags & CISTPL_IO_8BIT))
279 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
280 if (!(io->flags & CISTPL_IO_16BIT))
281 p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
282 p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
283 p_dev->io.BasePort1 = io->win[0].base;
284 p_dev->io.NumPorts1 = io->win[0].len;
285 if (io->nwin > 1) {
286 p_dev->io.Attributes2 = p_dev->io.Attributes1;
287 p_dev->io.BasePort2 = io->win[1].base;
288 p_dev->io.NumPorts2 = io->win[1].len;
289 }
290
291 /* This reserves IO space but doesn't actually enable it */
292 if (pcmcia_request_io(p_dev, &p_dev->io) != 0)
293 goto next_entry;
294 }
295 return 0;
296
297next_entry:
298 pcmcia_disable_device(p_dev);
299 return -ENODEV;
300};
301
302static int
303spectrum_cs_config(struct pcmcia_device *link)
304{
305 struct net_device *dev = link->priv;
306 struct orinoco_private *priv = netdev_priv(dev);
307 struct orinoco_pccard *card = priv->card;
308 hermes_t *hw = &priv->hw;
309 int last_fn, last_ret;
310 void __iomem *mem;
311
312 /*
313 * In this loop, we scan the CIS for configuration table
314 * entries, each of which describes a valid card
315 * configuration, including voltage, IO window, memory window,
316 * and interrupt settings.
317 *
318 * We make no assumptions about the card to be configured: we
319 * use just the information available in the CIS. In an ideal
320 * world, this would work for any PCMCIA card, but it requires
321 * a complete and accurate CIS. In practice, a driver usually
322 * "knows" most of these things without consulting the CIS,
323 * and most client drivers will only use the CIS to fill in
324 * implementation-defined details.
325 */
326 last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL);
327 if (last_ret) {
328 if (!ignore_cis_vcc)
329 printk(KERN_ERR PFX "GetNextTuple(): No matching "
330 "CIS configuration. Maybe you need the "
331 "ignore_cis_vcc=1 parameter.\n");
332 cs_error(link, RequestIO, last_ret);
333 goto failed;
334 }
335
336 /*
337 * Allocate an interrupt line. Note that this does not assign
338 * a handler to the interrupt, unless the 'Handler' member of
339 * the irq structure is initialized.
340 */
341 CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
342
343 /* We initialize the hermes structure before completing PCMCIA
344 * configuration just in case the interrupt handler gets
345 * called. */
346 mem = ioport_map(link->io.BasePort1, link->io.NumPorts1);
347 if (!mem)
348 goto cs_failed;
349
350 hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING);
351
352 /*
353 * This actually configures the PCMCIA socket -- setting up
354 * the I/O windows and the interrupt mapping, and putting the
355 * card and host interface into "Memory and IO" mode.
356 */
357 CS_CHECK(RequestConfiguration,
358 pcmcia_request_configuration(link, &link->conf));
359
360 /* Ok, we have the configuration, prepare to register the netdev */
361 dev->base_addr = link->io.BasePort1;
362 dev->irq = link->irq.AssignedIRQ;
363 card->node.major = card->node.minor = 0;
364
365 /* Reset card */
366 if (spectrum_cs_hard_reset(priv) != 0) {
367 goto failed;
368 }
369
370 SET_NETDEV_DEV(dev, &handle_to_dev(link));
371 /* Tell the stack we exist */
372 if (register_netdev(dev) != 0) {
373 printk(KERN_ERR PFX "register_netdev() failed\n");
374 goto failed;
375 }
376
377 /* At this point, the dev_node_t structure(s) needs to be
378 * initialized and arranged in a linked list at link->dev_node. */
379 strcpy(card->node.dev_name, dev->name);
380 link->dev_node = &card->node; /* link->dev_node being non-NULL is also
381 used to indicate that the
382 net_device has been registered */
383
384 /* Finally, report what we've done */
385 printk(KERN_DEBUG "%s: " DRIVER_NAME " at %s, irq %d, io "
386 "0x%04x-0x%04x\n", dev->name, dev->dev.parent->bus_id,
387 link->irq.AssignedIRQ, link->io.BasePort1,
388 link->io.BasePort1 + link->io.NumPorts1 - 1);
389
390 return 0;
391
392 cs_failed:
393 cs_error(link, last_fn, last_ret);
394
395 failed:
396 spectrum_cs_release(link);
397 return -ENODEV;
398} /* spectrum_cs_config */
399
400/*
401 * After a card is removed, spectrum_cs_release() will unregister the
402 * device, and release the PCMCIA configuration. If the device is
403 * still open, this will be postponed until it is closed.
404 */
405static void
406spectrum_cs_release(struct pcmcia_device *link)
407{
408 struct net_device *dev = link->priv;
409 struct orinoco_private *priv = netdev_priv(dev);
410 unsigned long flags;
411
412 /* We're committed to taking the device away now, so mark the
413 * hardware as unavailable */
414 spin_lock_irqsave(&priv->lock, flags);
415 priv->hw_unavailable++;
416 spin_unlock_irqrestore(&priv->lock, flags);
417
418 pcmcia_disable_device(link);
419 if (priv->hw.iobase)
420 ioport_unmap(priv->hw.iobase);
421} /* spectrum_cs_release */
422
423
424static int
425spectrum_cs_suspend(struct pcmcia_device *link)
426{
427 struct net_device *dev = link->priv;
428 struct orinoco_private *priv = netdev_priv(dev);
429 unsigned long flags;
430 int err = 0;
431
432 /* Mark the device as stopped, to block IO until later */
433 spin_lock_irqsave(&priv->lock, flags);
434
435 err = __orinoco_down(dev);
436 if (err)
437 printk(KERN_WARNING "%s: Error %d downing interface\n",
438 dev->name, err);
439
440 netif_device_detach(dev);
441 priv->hw_unavailable++;
442
443 spin_unlock_irqrestore(&priv->lock, flags);
444
445 return err;
446}
447
448static int
449spectrum_cs_resume(struct pcmcia_device *link)
450{
451 struct net_device *dev = link->priv;
452 struct orinoco_private *priv = netdev_priv(dev);
453
454 netif_device_attach(dev);
455 priv->hw_unavailable--;
456 schedule_work(&priv->reset_work);
457
458 return 0;
459}
460
461
462/********************************************************************/
463/* Module initialization */
464/********************************************************************/
465
466/* Can't be declared "const" or the whole __initdata section will
467 * become const */
468static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION
469 " (Pavel Roskin <proski@gnu.org>,"
470 " David Gibson <hermes@gibson.dropbear.id.au>, et al)";
471
472static struct pcmcia_device_id spectrum_cs_ids[] = {
473 PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */
474 PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */
475 PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */
476 PCMCIA_DEVICE_NULL,
477};
478MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids);
479
480static struct pcmcia_driver orinoco_driver = {
481 .owner = THIS_MODULE,
482 .drv = {
483 .name = DRIVER_NAME,
484 },
485 .probe = spectrum_cs_probe,
486 .remove = spectrum_cs_detach,
487 .suspend = spectrum_cs_suspend,
488 .resume = spectrum_cs_resume,
489 .id_table = spectrum_cs_ids,
490};
491
492static int __init
493init_spectrum_cs(void)
494{
495 printk(KERN_DEBUG "%s\n", version);
496
497 return pcmcia_register_driver(&orinoco_driver);
498}
499
500static void __exit
501exit_spectrum_cs(void)
502{
503 pcmcia_unregister_driver(&orinoco_driver);
504}
505
506module_init(init_spectrum_cs);
507module_exit(exit_spectrum_cs);