net: Makefile change for KSZ884X driver
[safe/jmp/linux-2.6] / drivers / net / wireless / orinoco / hermes.c
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
48 /* These are maximum timeouts. Most often, card wil react much faster */
49 #define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */
50 #define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */
51 #define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */
52 #define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */
53
54 /*
55  * Debugging helpers
56  */
57
58 #define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \
59                         printk(stuff); } while (0)
60
61 #undef HERMES_DEBUG
62 #ifdef HERMES_DEBUG
63 #include <stdarg.h>
64
65 #define DEBUG(lvl, stuff...) if ((lvl) <= HERMES_DEBUG) DMSG(stuff)
66
67 #else /* ! HERMES_DEBUG */
68
69 #define DEBUG(lvl, stuff...) do { } while (0)
70
71 #endif /* ! HERMES_DEBUG */
72
73
74 /*
75  * Internal functions
76  */
77
78 /* Issue a command to the chip. Waiting for it to complete is the caller's
79    problem.
80
81    Returns -EBUSY if the command register is busy, 0 on success.
82
83    Callable from any context.
84 */
85 static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0,
86                             u16 param1, u16 param2)
87 {
88         int k = CMD_BUSY_TIMEOUT;
89         u16 reg;
90
91         /* First wait for the command register to unbusy */
92         reg = hermes_read_regn(hw, CMD);
93         while ((reg & HERMES_CMD_BUSY) && k) {
94                 k--;
95                 udelay(1);
96                 reg = hermes_read_regn(hw, CMD);
97         }
98         if (reg & HERMES_CMD_BUSY)
99                 return -EBUSY;
100
101         hermes_write_regn(hw, PARAM2, param2);
102         hermes_write_regn(hw, PARAM1, param1);
103         hermes_write_regn(hw, PARAM0, param0);
104         hermes_write_regn(hw, CMD, cmd);
105
106         return 0;
107 }
108
109 /*
110  * Function definitions
111  */
112
113 /* For doing cmds that wipe the magic constant in SWSUPPORT0 */
114 int hermes_doicmd_wait(hermes_t *hw, u16 cmd,
115                        u16 parm0, u16 parm1, u16 parm2,
116                        struct hermes_response *resp)
117 {
118         int err = 0;
119         int k;
120         u16 status, reg;
121
122         err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2);
123         if (err)
124                 return err;
125
126         reg = hermes_read_regn(hw, EVSTAT);
127         k = CMD_INIT_TIMEOUT;
128         while ((!(reg & HERMES_EV_CMD)) && k) {
129                 k--;
130                 udelay(10);
131                 reg = hermes_read_regn(hw, EVSTAT);
132         }
133
134         hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC);
135
136         if (!hermes_present(hw)) {
137                 DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n",
138                        hw->iobase);
139                 err = -ENODEV;
140                 goto out;
141         }
142
143         if (!(reg & HERMES_EV_CMD)) {
144                 printk(KERN_ERR "hermes @ %p: "
145                        "Timeout waiting for card to reset (reg=0x%04x)!\n",
146                        hw->iobase, reg);
147                 err = -ETIMEDOUT;
148                 goto out;
149         }
150
151         status = hermes_read_regn(hw, STATUS);
152         if (resp) {
153                 resp->status = status;
154                 resp->resp0 = hermes_read_regn(hw, RESP0);
155                 resp->resp1 = hermes_read_regn(hw, RESP1);
156                 resp->resp2 = hermes_read_regn(hw, RESP2);
157         }
158
159         hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
160
161         if (status & HERMES_STATUS_RESULT)
162                 err = -EIO;
163 out:
164         return err;
165 }
166 EXPORT_SYMBOL(hermes_doicmd_wait);
167
168 void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing)
169 {
170         hw->iobase = address;
171         hw->reg_spacing = reg_spacing;
172         hw->inten = 0x0;
173 }
174 EXPORT_SYMBOL(hermes_struct_init);
175
176 int hermes_init(hermes_t *hw)
177 {
178         u16 reg;
179         int err = 0;
180         int k;
181
182         /* We don't want to be interrupted while resetting the chipset */
183         hw->inten = 0x0;
184         hermes_write_regn(hw, INTEN, 0);
185         hermes_write_regn(hw, EVACK, 0xffff);
186
187         /* Normally it's a "can't happen" for the command register to
188            be busy when we go to issue a command because we are
189            serializing all commands.  However we want to have some
190            chance of resetting the card even if it gets into a stupid
191            state, so we actually wait to see if the command register
192            will unbusy itself here. */
193         k = CMD_BUSY_TIMEOUT;
194         reg = hermes_read_regn(hw, CMD);
195         while (k && (reg & HERMES_CMD_BUSY)) {
196                 if (reg == 0xffff) /* Special case - the card has probably been
197                                       removed, so don't wait for the timeout */
198                         return -ENODEV;
199
200                 k--;
201                 udelay(1);
202                 reg = hermes_read_regn(hw, CMD);
203         }
204
205         /* No need to explicitly handle the timeout - if we've timed
206            out hermes_issue_cmd() will probably return -EBUSY below */
207
208         /* According to the documentation, EVSTAT may contain
209            obsolete event occurrence information.  We have to acknowledge
210            it by writing EVACK. */
211         reg = hermes_read_regn(hw, EVSTAT);
212         hermes_write_regn(hw, EVACK, reg);
213
214         /* We don't use hermes_docmd_wait here, because the reset wipes
215            the magic constant in SWSUPPORT0 away, and it gets confused */
216         err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL);
217
218         return err;
219 }
220 EXPORT_SYMBOL(hermes_init);
221
222 /* Issue a command to the chip, and (busy!) wait for it to
223  * complete.
224  *
225  * Returns:
226  *     < 0 on internal error
227  *       0 on success
228  *     > 0 on error returned by the firmware
229  *
230  * Callable from any context, but locking is your problem. */
231 int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0,
232                       struct hermes_response *resp)
233 {
234         int err;
235         int k;
236         u16 reg;
237         u16 status;
238
239         err = hermes_issue_cmd(hw, cmd, parm0, 0, 0);
240         if (err) {
241                 if (!hermes_present(hw)) {
242                         if (net_ratelimit())
243                                 printk(KERN_WARNING "hermes @ %p: "
244                                        "Card removed while issuing command "
245                                        "0x%04x.\n", hw->iobase, cmd);
246                         err = -ENODEV;
247                 } else
248                         if (net_ratelimit())
249                                 printk(KERN_ERR "hermes @ %p: "
250                                        "Error %d issuing command 0x%04x.\n",
251                                        hw->iobase, err, cmd);
252                 goto out;
253         }
254
255         reg = hermes_read_regn(hw, EVSTAT);
256         k = CMD_COMPL_TIMEOUT;
257         while ((!(reg & HERMES_EV_CMD)) && k) {
258                 k--;
259                 udelay(10);
260                 reg = hermes_read_regn(hw, EVSTAT);
261         }
262
263         if (!hermes_present(hw)) {
264                 printk(KERN_WARNING "hermes @ %p: Card removed "
265                        "while waiting for command 0x%04x completion.\n",
266                        hw->iobase, cmd);
267                 err = -ENODEV;
268                 goto out;
269         }
270
271         if (!(reg & HERMES_EV_CMD)) {
272                 printk(KERN_ERR "hermes @ %p: Timeout waiting for "
273                        "command 0x%04x completion.\n", hw->iobase, cmd);
274                 err = -ETIMEDOUT;
275                 goto out;
276         }
277
278         status = hermes_read_regn(hw, STATUS);
279         if (resp) {
280                 resp->status = status;
281                 resp->resp0 = hermes_read_regn(hw, RESP0);
282                 resp->resp1 = hermes_read_regn(hw, RESP1);
283                 resp->resp2 = hermes_read_regn(hw, RESP2);
284         }
285
286         hermes_write_regn(hw, EVACK, HERMES_EV_CMD);
287
288         if (status & HERMES_STATUS_RESULT)
289                 err = -EIO;
290
291  out:
292         return err;
293 }
294 EXPORT_SYMBOL(hermes_docmd_wait);
295
296 int hermes_allocate(hermes_t *hw, u16 size, u16 *fid)
297 {
298         int err = 0;
299         int k;
300         u16 reg;
301
302         if ((size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX))
303                 return -EINVAL;
304
305         err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL);
306         if (err)
307                 return err;
308
309         reg = hermes_read_regn(hw, EVSTAT);
310         k = ALLOC_COMPL_TIMEOUT;
311         while ((!(reg & HERMES_EV_ALLOC)) && k) {
312                 k--;
313                 udelay(10);
314                 reg = hermes_read_regn(hw, EVSTAT);
315         }
316
317         if (!hermes_present(hw)) {
318                 printk(KERN_WARNING "hermes @ %p: "
319                        "Card removed waiting for frame allocation.\n",
320                        hw->iobase);
321                 return -ENODEV;
322         }
323
324         if (!(reg & HERMES_EV_ALLOC)) {
325                 printk(KERN_ERR "hermes @ %p: "
326                        "Timeout waiting for frame allocation\n",
327                        hw->iobase);
328                 return -ETIMEDOUT;
329         }
330
331         *fid = hermes_read_regn(hw, ALLOCFID);
332         hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC);
333
334         return 0;
335 }
336 EXPORT_SYMBOL(hermes_allocate);
337
338 /* Set up a BAP to read a particular chunk of data from card's internal buffer.
339  *
340  * Returns:
341  *     < 0 on internal failure (errno)
342  *       0 on success
343  *     > 0 on error
344  * from firmware
345  *
346  * Callable from any context */
347 static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset)
348 {
349         int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0;
350         int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0;
351         int k;
352         u16 reg;
353
354         /* Paranoia.. */
355         if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2))
356                 return -EINVAL;
357
358         k = HERMES_BAP_BUSY_TIMEOUT;
359         reg = hermes_read_reg(hw, oreg);
360         while ((reg & HERMES_OFFSET_BUSY) && k) {
361                 k--;
362                 udelay(1);
363                 reg = hermes_read_reg(hw, oreg);
364         }
365
366         if (reg & HERMES_OFFSET_BUSY)
367                 return -ETIMEDOUT;
368
369         /* Now we actually set up the transfer */
370         hermes_write_reg(hw, sreg, id);
371         hermes_write_reg(hw, oreg, offset);
372
373         /* Wait for the BAP to be ready */
374         k = HERMES_BAP_BUSY_TIMEOUT;
375         reg = hermes_read_reg(hw, oreg);
376         while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) {
377                 k--;
378                 udelay(1);
379                 reg = hermes_read_reg(hw, oreg);
380         }
381
382         if (reg != offset) {
383                 printk(KERN_ERR "hermes @ %p: BAP%d offset %s: "
384                        "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap,
385                        (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error",
386                        reg, id, offset);
387
388                 if (reg & HERMES_OFFSET_BUSY)
389                         return -ETIMEDOUT;
390
391                 return -EIO;            /* error or wrong offset */
392         }
393
394         return 0;
395 }
396
397 /* Read a block of data from the chip's buffer, via the
398  * BAP. Synchronization/serialization is the caller's problem.  len
399  * must be even.
400  *
401  * Returns:
402  *     < 0 on internal failure (errno)
403  *       0 on success
404  *     > 0 on error from firmware
405  */
406 int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len,
407                      u16 id, u16 offset)
408 {
409         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
410         int err = 0;
411
412         if ((len < 0) || (len % 2))
413                 return -EINVAL;
414
415         err = hermes_bap_seek(hw, bap, id, offset);
416         if (err)
417                 goto out;
418
419         /* Actually do the transfer */
420         hermes_read_words(hw, dreg, buf, len/2);
421
422  out:
423         return err;
424 }
425 EXPORT_SYMBOL(hermes_bap_pread);
426
427 /* Write a block of data to the chip's buffer, via the
428  * BAP. Synchronization/serialization is the caller's problem.
429  *
430  * Returns:
431  *     < 0 on internal failure (errno)
432  *       0 on success
433  *     > 0 on error from firmware
434  */
435 int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len,
436                       u16 id, u16 offset)
437 {
438         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
439         int err = 0;
440
441         if (len < 0)
442                 return -EINVAL;
443
444         err = hermes_bap_seek(hw, bap, id, offset);
445         if (err)
446                 goto out;
447
448         /* Actually do the transfer */
449         hermes_write_bytes(hw, dreg, buf, len);
450
451  out:
452         return err;
453 }
454 EXPORT_SYMBOL(hermes_bap_pwrite);
455
456 /* Read a Length-Type-Value record from the card.
457  *
458  * If length is NULL, we ignore the length read from the card, and
459  * read the entire buffer regardless. This is useful because some of
460  * the configuration records appear to have incorrect lengths in
461  * practice.
462  *
463  * Callable from user or bh context.  */
464 int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize,
465                     u16 *length, void *buf)
466 {
467         int err = 0;
468         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
469         u16 rlength, rtype;
470         unsigned nwords;
471
472         if (bufsize % 2)
473                 return -EINVAL;
474
475         err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL);
476         if (err)
477                 return err;
478
479         err = hermes_bap_seek(hw, bap, rid, 0);
480         if (err)
481                 return err;
482
483         rlength = hermes_read_reg(hw, dreg);
484
485         if (!rlength)
486                 return -ENODATA;
487
488         rtype = hermes_read_reg(hw, dreg);
489
490         if (length)
491                 *length = rlength;
492
493         if (rtype != rid)
494                 printk(KERN_WARNING "hermes @ %p: %s(): "
495                        "rid (0x%04x) does not match type (0x%04x)\n",
496                        hw->iobase, __func__, rid, rtype);
497         if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize)
498                 printk(KERN_WARNING "hermes @ %p: "
499                        "Truncating LTV record from %d to %d bytes. "
500                        "(rid=0x%04x, len=0x%04x)\n", hw->iobase,
501                        HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength);
502
503         nwords = min((unsigned)rlength - 1, bufsize / 2);
504         hermes_read_words(hw, dreg, buf, nwords);
505
506         return 0;
507 }
508 EXPORT_SYMBOL(hermes_read_ltv);
509
510 int hermes_write_ltv(hermes_t *hw, int bap, u16 rid,
511                      u16 length, const void *value)
512 {
513         int dreg = bap ? HERMES_DATA1 : HERMES_DATA0;
514         int err = 0;
515         unsigned count;
516
517         if (length == 0)
518                 return -EINVAL;
519
520         err = hermes_bap_seek(hw, bap, rid, 0);
521         if (err)
522                 return err;
523
524         hermes_write_reg(hw, dreg, length);
525         hermes_write_reg(hw, dreg, rid);
526
527         count = length - 1;
528
529         hermes_write_bytes(hw, dreg, value, count << 1);
530
531         err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE,
532                                 rid, NULL);
533
534         return err;
535 }
536 EXPORT_SYMBOL(hermes_write_ltv);