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