Finished by hand
[people/xl0/gpxe.git] / src / drivers / net / prism2.c
1 /**************************************************************************
2 Etherboot -  BOOTP/TFTP Bootstrap Program
3 Prism2 NIC driver for Etherboot
4
5 Written by Michael Brown of Fen Systems Ltd
6 $Id$
7 ***************************************************************************/
8
9 /*
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2, or (at
13  * your option) any later version.
14  */
15
16 /* to get some global routines like printf */
17 #include "etherboot.h"
18 /* to get the interface to the body of the program */
19 #include "nic.h"
20 /* to get the PCI support functions, if this is a PCI NIC */
21 #include "pci.h"
22
23 /*
24  * Hard-coded SSID
25  * Leave blank in order to connect to any available SSID
26  */
27
28 static const char hardcoded_ssid[] = "";
29
30 /*
31  * Maximum number of info packets to wait for on a join attempt.
32  * Some APs (including the Linksys WAP11) will send a "you are disconnected" packet
33  * before sending the "you are connected" packet, if the card has previously been
34  * attached to the AP.
35  *
36  * 2 is probably a sensible value, but YMMV.
37  */
38
39 #define MAX_JOIN_INFO_COUNT 2
40
41 /*
42  * Type of Prism2 interface to support
43  * If not already defined, select PLX
44  */
45 #ifndef WLAN_HOSTIF
46 #define WLAN_HOSTIF WLAN_PLX
47 #endif
48
49 /*
50  * Include wlan_compat, p80211 and hfa384x header files from Linux Prism2 driver
51  * We need to hack some defines in order to avoid compiling kernel-specific routines
52  */
53
54 #define __LINUX_WLAN__
55 #undef __KERNEL__
56 #define __I386__
57 #include "wlan_compat.h"
58 #include "p80211hdr.h"
59 #include "hfa384x.h"
60 #define BAP_TIMEOUT ( 5000 )
61
62 /*
63  * A few hacks to make the coding environment more Linux-like.  This makes it somewhat
64  * quicker to convert code from the Linux Prism2 driver.
65  */
66 #include <errno.h>
67 #include "timer.h"
68 #define __le16_to_cpu(x) (x)
69 #define __le32_to_cpu(x) (x)
70 #define __cpu_to_le16(x) (x)
71 #define __cpu_to_le32(x) (x)
72
73 /*
74  * PLX9052 PCI register offsets
75  * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
76  */
77
78 #define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )
79 #define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )
80 #define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )
81 #define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )
82 #define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )
83
84 #define PRISM2_PLX_ATTR_MEM_BASE       ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )
85 #define PRISM2_PLX_IO_BASE             ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )
86
87 #define PRISM2_PCI_MEM_BASE            ( PCI_BASE_ADDRESS_0 )
88
89 /*
90  * PCMCIA CIS types
91  * Taken from cistpl.h in pcmcia-cs
92  */
93
94 #define CISTPL_VERS_1           ( 0x15 )
95 #define CISTPL_END              ( 0xff )
96
97 #define CIS_STEP                ( 2 )
98 #define CISTPL_HEADER_LEN       ( 2 * CIS_STEP )
99 #define CISTPL_LEN_OFF          ( 1 * CIS_STEP )
100 #define CISTPL_VERS_1_STR_OFF   ( 4 * CIS_STEP )
101
102 /*
103  * Prism2 constants
104  * Taken from prism2sta.c in linux-wlan-ng
105  */
106
107 #define COR_OFFSET      ( 0x3e0 )   /* COR attribute offset of Prism2 PC card */
108 #define COR_VALUE       ( 0x41 )    /* Enable PC card with irq in level trigger (but interrupts disabled) */
109
110 /* NIC specific static variables */
111
112 /* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined.
113  * This is a dummy version that contains only the fields we are interested in.
114  */
115
116 typedef struct hfa384x
117 {
118   UINT32 iobase;
119   UINT32 membase;
120   UINT16 lastcmd;
121   UINT16 status;         /* in host order */
122   UINT16 resp0;          /* in host order */
123   UINT16 resp1;          /* in host order */
124   UINT16 resp2;          /* in host order */
125   UINT8  bssid[WLAN_BSSID_LEN];
126 } hfa384x_t;
127
128 /* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */
129 static hfa384x_t hw_global = {
130   0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}
131 };
132
133 /*
134  * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
135  * Taken from p80211conv.h
136  */
137
138 typedef struct wlan_llc
139 {
140   UINT8   dsap                            __WLAN_ATTRIB_PACK__;
141   UINT8   ssap                            __WLAN_ATTRIB_PACK__;
142   UINT8   ctl                             __WLAN_ATTRIB_PACK__;
143 } __WLAN_ATTRIB_PACK__ wlan_llc_t;
144
145 static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
146
147 #define WLAN_IEEE_OUI_LEN 3
148 typedef struct wlan_snap
149 {
150   UINT8   oui[WLAN_IEEE_OUI_LEN]          __WLAN_ATTRIB_PACK__;
151   UINT16  type                            __WLAN_ATTRIB_PACK__;
152 } __WLAN_ATTRIB_PACK__ wlan_snap_t;
153
154 typedef struct wlan_80211hdr
155 {
156   wlan_llc_t llc;
157   wlan_snap_t snap;
158 } wlan_80211hdr_t;
159
160 /*
161  * Function prototypes
162  */
163
164 /*
165  * Hardware-level hfa384x functions
166  * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
167  * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions. 
168  */
169
170 /* Retrieve the value of one of the MAC registers. */
171 static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg )
172 {
173 #if (WLAN_HOSTIF == WLAN_PLX)
174   return inw ( hw->iobase + reg );
175 #elif (WLAN_HOSTIF == WLAN_PCI)
176   return readw ( hw->membase + reg );
177 #endif
178 }
179
180 /* Set the value of one of the MAC registers. */
181 static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg )
182 {
183 #if (WLAN_HOSTIF == WLAN_PLX)
184   outw ( val, hw->iobase + reg );
185 #elif (WLAN_HOSTIF == WLAN_PCI)
186   writew ( val, hw->membase + reg );
187 #endif
188   return;
189 }
190
191 /* 
192  * Noswap versions
193  * Etherboot is i386 only, so swap and noswap are the same...
194  */
195 static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg )
196 {
197   return hfa384x_getreg ( hw, reg );
198 }
199 static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg )
200 {
201   hfa384x_setreg ( hw, val, reg );
202 }
203
204 /*
205  * Low-level hfa384x functions
206  * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
207  */
208
209 /*
210  * hfa384x_docmd_wait
211  *
212  * Waits for availability of the Command register, then
213  * issues the given command.  Then polls the Evstat register
214  * waiting for command completion.
215  * Arguments:
216  *       hw              device structure
217  *       cmd             Command in host order
218  *       parm0           Parameter0 in host order
219  *       parm1           Parameter1 in host order
220  *       parm2           Parameter2 in host order
221  * Returns:
222  *       0               success
223  *       >0              command indicated error, Status and Resp0-2 are
224  *                       in hw structure.
225  */
226 static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2)
227 {
228   UINT16 reg = 0;
229   UINT16 counter = 0;
230   
231   /* wait for the busy bit to clear */  
232   counter = 0;
233   reg = hfa384x_getreg(hw, HFA384x_CMD);
234   while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
235     reg = hfa384x_getreg(hw, HFA384x_CMD);
236     counter++;
237     udelay(10);
238   }
239   if (HFA384x_CMD_ISBUSY(reg)) {
240     printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
241     return -ETIMEDOUT;
242   }
243
244   /* busy bit clear, write command */
245   hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
246   hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
247   hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
248   hw->lastcmd = cmd;
249   hfa384x_setreg(hw, cmd, HFA384x_CMD);
250   
251   /* Now wait for completion */
252   counter = 0;
253   reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
254   /* Initialization is the problem.  It takes about
255      100ms. "normal" commands are typically is about
256      200-400 us (I've never seen less than 200).  Longer
257      is better so that we're not hammering the bus. */
258   while ( !HFA384x_EVSTAT_ISCMD(reg) && (counter < 5000)) {
259     reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
260     counter++;
261     udelay(200);
262   }
263   if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
264     printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
265     return -ETIMEDOUT;
266   }
267
268   /* Read status and response */
269   hw->status = hfa384x_getreg(hw, HFA384x_STATUS);
270   hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
271   hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
272   hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
273   hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
274   return HFA384x_STATUS_RESULT_GET(hw->status);
275 }
276
277 /*
278  * Prepare BAP for access.  Assigns FID and RID, sets offset register
279  * and waits for BAP to become available.
280  *
281  * Arguments:
282  *      hw              device structure
283  *      id              FID or RID, destined for the select register (host order)
284  *      offset          An _even_ offset into the buffer for the given FID/RID.
285  * Returns: 
286  *      0               success
287  */
288 static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset)
289 {
290   int result = 0;
291   UINT16 reg;
292   UINT16 i;
293
294   /* Validate offset, buf, and len */
295   if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
296     result = -EINVAL;
297   } else {
298     /* Write fid/rid and offset */
299     hfa384x_setreg(hw, id, HFA384x_SELECT0);
300     udelay(10);
301     hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
302     /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
303     i = 0; 
304     do {
305       reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
306       if ( i > 0 ) udelay(2);
307       i++;
308     } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
309     if ( i >= BAP_TIMEOUT ) {
310       /* failure */
311       result = reg;
312     } else if ( HFA384x_OFFSET_ISERR(reg) ){
313       /* failure */
314       result = reg;
315     }
316   }
317   return result;
318 }
319
320 /*
321  * Copy data from BAP to memory.
322  *
323  * Arguments:
324  *      hw              device structure
325  *      id              FID or RID, destined for the select register (host order)
326  *      offset          An _even_ offset into the buffer for the given FID/RID.
327  *      buf             ptr to array of bytes
328  *      len             length of data to transfer in bytes
329  * Returns: 
330  *      0               success
331  */
332 static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
333                           void *buf, UINT len)
334 {
335   int result = 0;
336   UINT8 *d = (UINT8*)buf;
337   UINT16 i;
338   UINT16 reg = 0;
339   
340   /* Prepare BAP */
341   result = hfa384x_prepare_bap ( hw, id, offset );
342   if ( result == 0 ) {
343     /* Read even(len) buf contents from data reg */
344     for ( i = 0; i < (len & 0xfffe); i+=2 ) {
345       *(UINT16*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
346     }
347     /* If len odd, handle last byte */
348     if ( len % 2 ){
349       reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
350       d[len-1] = ((UINT8*)(&reg))[0];
351     }
352   }
353   if (result) {
354     printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
355   }
356   return result;
357 }
358
359 /*
360  * Copy data from memory to BAP.
361  *
362  * Arguments:
363  *      hw              device structure
364  *      id              FID or RID, destined for the select register (host order)
365  *      offset          An _even_ offset into the buffer for the given FID/RID.
366  *      buf             ptr to array of bytes
367  *      len             length of data to transfer in bytes
368  * Returns: 
369  *      0               success
370  */
371 static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
372                         void *buf, UINT len)
373 {
374   int result = 0;
375   UINT8 *d = (UINT8*)buf;
376   UINT16 i;
377   UINT16 savereg;
378
379   /* Prepare BAP */
380   result = hfa384x_prepare_bap ( hw, id, offset );
381   if ( result == 0 ) {
382     /* Write even(len) buf contents to data reg */
383     for ( i = 0; i < (len & 0xfffe); i+=2 ) {
384       hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), HFA384x_DATA0);
385     }
386     /* If len odd, handle last byte */
387     if ( len % 2 ){
388       savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
389       result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
390       if ( result == 0 ) {
391         ((UINT8*)(&savereg))[0] = d[len-1];
392         hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
393       }
394     }
395   }
396   if (result) {
397     printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
398   }
399   return result;
400 }
401
402 /*
403  * Request a given record to be copied to/from the record buffer.
404  *
405  * Arguments:
406  *      hw              device structure
407  *      write           [0|1] copy the record buffer to the given
408  *                      configuration record. (host order)
409  *      rid             RID of the record to read/write. (host order)
410  *
411  * Returns: 
412  *      0               success
413  */
414 static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid)
415 {
416   return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
417 }
418
419 /*
420  * Performs the sequence necessary to read a config/info item.
421  *
422  * Arguments:
423  *      hw              device structure
424  *      rid             config/info record id (host order)
425  *      buf             host side record buffer.  Upon return it will
426  *                      contain the body portion of the record (minus the 
427  *                      RID and len).
428  *      len             buffer length (in bytes, should match record length)
429  *
430  * Returns: 
431  *      0               success
432  */
433 static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
434 {
435   int result = 0;
436   hfa384x_rec_t rec;
437
438   /* Request read of RID */
439   result = hfa384x_cmd_access( hw, 0, rid);
440   if ( result ) {
441     printf("Call to hfa384x_cmd_access failed\n");
442     return -1;
443   }
444   /* Copy out record length */
445   result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
446   if ( result ) {
447     return -1;
448   }
449   /* Validate the record length */
450   if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) {  /* note body len calculation in bytes */
451     printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
452     return -1;
453   }
454   /* Copy out record data */
455   result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
456   return result;
457 }
458
459 /*
460  * Performs the sequence necessary to read a 16/32 bit config/info item
461  * and convert it to host order.
462  *
463  * Arguments:
464  *      hw              device structure
465  *      rid             config/info record id (in host order)
466  *      val             ptr to 16/32 bit buffer to receive value (in host order)
467  *
468  * Returns: 
469  *      0               success
470  */
471 #if 0 /* Not actually used anywhere */
472 static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
473 {
474   int result = 0;
475   result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
476   if ( result == 0 ) {
477     *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
478   }
479   return result;
480 }
481 #endif
482 #if 0 /* Not actually used anywhere */
483 static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
484 {
485   int result = 0;
486   result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
487   if ( result == 0 ) {
488     *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
489   }
490   return result;
491 }
492 #endif
493
494 /*
495  * Performs the sequence necessary to write a config/info item.
496  *
497  * Arguments:
498  *      hw              device structure
499  *      rid             config/info record id (in host order)
500  *      buf             host side record buffer
501  *      len             buffer length (in bytes)
502  *
503  * Returns: 
504  *      0               success
505  */
506 static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
507 {
508   int result = 0;
509   hfa384x_rec_t rec;
510
511   rec.rid = host2hfa384x_16(rid);
512   rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
513   /* write the record header */
514   result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
515   if ( result ) {
516     printf("Failure writing record header\n");
517     return -1;
518   }
519   /* write the record data (if there is any) */
520   if ( len > 0 ) {
521     result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
522     if ( result ) {
523       printf("Failure writing record data\n");
524       return -1;
525     }
526   }
527   /* Trigger setting of record */
528   result = hfa384x_cmd_access( hw, 1, rid);
529   return result;
530 }
531
532 /*
533  * Performs the sequence necessary to write a 16/32 bit config/info item.
534  *
535  * Arguments:
536  *      hw              device structure
537  *      rid             config/info record id (in host order)
538  *      val             16/32 bit value to store (in host order)
539  *
540  * Returns: 
541  *      0               success
542  */
543 static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val)
544 {
545   UINT16 value;
546   value = host2hfa384x_16(*val);
547   return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));
548 }
549 #if 0 /* Not actually used anywhere */
550 static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val)
551 {
552   UINT32 value;
553   value = host2hfa384x_32(*val);
554   return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32));
555 }
556 #endif
557
558 /*
559  * Wait for an event, with specified checking interval and timeout.
560  * Automatically acknolwedges events.
561  *
562  * Arguments:
563  *      hw              device structure
564  *      event_mask      EVSTAT register mask of events to wait for
565  *      event_ack       EVACK register set of events to be acknowledged if they happen (can be
566  *                      used to acknowledge "ignorable" events in addition to the "main" event)
567  *      wait            Time (in us) to wait between each poll of the register
568  *      timeout         Maximum number of polls before timing out
569  *      descr           Descriptive text string of what is being waited for
570  *                      (will be printed out if a timeout happens)
571  *
572  * Returns: 
573  *      value of EVSTAT register, or 0 on failure 
574  */
575 static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr)
576 {
577   UINT16 reg;
578   int count = 0;
579   
580   do {
581     reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
582     if ( count > 0 ) udelay(wait);
583     count++;
584   } while ( !(reg & event_mask) && count < timeout);
585   if ( count >= timeout ) {
586     printf("hfa384x: Timed out waiting for %s\n", descr);
587     return 0; /* Return failure */
588   }
589   /* Acknowledge all events that we were waiting on */
590   hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
591   return reg;
592 }
593
594 /**************************************************************************
595 POLL - Wait for a frame
596 ***************************************************************************/
597 static int prism2_poll(struct nic *nic, int retrieve)
598 {
599   UINT16 reg;
600   UINT16 rxfid;
601   UINT16 result;
602   hfa384x_rx_frame_t rxdesc;
603   hfa384x_t *hw = &hw_global;
604   
605   /* Check for received packet */
606   reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
607   if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
608     /* No packet received - return 0 */
609     return 0;
610   }
611
612   if ( ! retrieve ) return 1;
613
614   /* Acknowledge RX event */
615   hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
616   /* Get RX FID */  
617   rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
618   /* Get the descriptor (including headers) */
619   result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc));
620   if ( result ) {
621     return 0; /* fail */
622   }
623   /* Byte order convert once up front. */
624   rxdesc.status = hfa384x2host_16(rxdesc.status);
625   rxdesc.time = hfa384x2host_32(rxdesc.time);
626   rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
627
628   /* Fill in nic->packetlen */
629   nic->packetlen = rxdesc.data_len;
630   if ( nic->packetlen > 0 ) {
631     /* Fill in nic->packet */
632     /*
633      * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
634      * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
635      * header), so we use a quick hack to achieve this.
636      */
637     result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
638                                    nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
639     if ( result ) {
640       return 0; /* fail */
641     }
642   }
643   return 1; /* Packet successfully received */
644 }
645
646 /**************************************************************************
647 TRANSMIT - Transmit a frame
648 ***************************************************************************/
649 static void prism2_transmit(
650                             struct nic *nic,
651                             const char *d,                      /* Destination */
652                             unsigned int t,                     /* Type */
653                             unsigned int s,                     /* size */
654                             const char *p)                      /* Packet */
655 {
656   hfa384x_t *hw = &hw_global;
657   hfa384x_tx_frame_t txdesc;
658   wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
659   UINT16 fid;
660   UINT16 status;
661   int result;
662
663   // Request FID allocation
664   result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
665   if (result != 0) {
666     printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
667     return;
668   }
669   if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
670   fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
671
672   /* Build Tx frame structure */
673   memset(&txdesc, 0, sizeof(txdesc));
674   txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) | 
675                                        HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
676   txdesc.frame_control =  host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
677                                        WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
678                                        WLAN_SET_FC_TODS(1) );
679   memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
680   memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
681   memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
682   txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
683   /* Set up SNAP header */
684   /* Let OUI default to RFC1042 (0x000000) */
685   p80211hdr.snap.type = htons(t);
686   
687   /* Copy txdesc, p80211hdr and payload parts to FID */
688   result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
689   if ( result ) return; /* fail */
690   result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
691   if ( result ) return; /* fail */
692   result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (UINT8*)p, s );
693   if ( result ) return; /* fail */
694
695   /* Issue Tx command */
696   result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
697   if ( result != 0 ) {
698     printf("hfa384x: Transmit failed with result %#hx.\n", result);
699     return;
700   }
701   
702   /* Wait for transmit completion (or exception) */
703   result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
704                                   200, 500, "Tx to complete\n" );
705   if ( !result ) return; /* timeout failure */
706   if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
707     fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
708     printf ( "Tx exception occurred with fid %#hx\n", fid );
709     result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
710     if ( result ) return; /* fail */
711     printf("hfa384x: Tx error occurred (status %#hx):\n", status);
712     if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
713     if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
714     if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
715     if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
716     if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
717     return; /* fail */
718   }
719 }
720
721 /**************************************************************************
722 DISABLE - Turn off ethernet interface
723 ***************************************************************************/
724 static void prism2_disable ( struct nic *nic __unused ) {
725   /* put the card in its initial state */
726 }
727
728 /**************************************************************************
729 IRQ - Enable, Disable, or Force interrupts
730 ***************************************************************************/
731 static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
732 {
733   switch ( action ) {
734   case DISABLE :
735     break;
736   case ENABLE :
737     break;
738   case FORCE :
739     break;
740   }
741 }
742
743 /**************************************************************************
744 Operations table
745 ***************************************************************************/
746 static struct nic_operations prism2_operations = {
747         .connect        = dummy_connect,
748         .poll           = prism2_poll,
749         .transmit       = prism2_transmit,
750         .irq            = prism2_irq,
751         .disable        = prism2_disable,
752 };
753
754 /**************************************************************************
755 PROBE - Look for an adapter, this routine's visible to the outside
756 You should omit the last argument struct pci_device * for a non-PCI NIC
757 ***************************************************************************/
758 static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) {
759   int result;
760   UINT16 tmp16 = 0;
761   UINT16 infofid;
762   hfa384x_InfFrame_t inf;
763   char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
764   int info_count = 0;
765
766   nic->irqno  = 0;
767
768   /* Initialize card */
769   result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */
770   if ( result ) printf ( "Initialize command returned %#hx\n", result );
771   hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */
772   hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */
773
774   /* Retrieve MAC address (and fill out nic->node_addr) */
775   hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
776   printf ( "MAC address %!\n", nic->node_addr );
777
778   /* Prepare card for autojoin */
779   /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
780   tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */
781   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16);
782   if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result );
783   tmp16 = 0x000f; /* Set transmit rate(?) */
784   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16);
785   if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result );
786   tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */
787   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16);
788   if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result );
789   /* Set SSID */
790   memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN);
791   for ( tmp16=0; tmp16<sizeof(hardcoded_ssid); tmp16++ ) { ssid[2+tmp16] = hardcoded_ssid[tmp16]; }
792   ssid[0] = sizeof(hardcoded_ssid) - 1; /* Ignore terminating zero */
793   result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */
794   if ( result ) printf ( "Set SSID command returned %#hx\n", result );
795   tmp16 = 1; /* Set port type to ESS port */
796   result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16);
797   if ( result ) printf ( "Set port type command returned %#hx\n", result );
798   /* Enable card */
799   result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
800   if ( result ) printf ( "Enable command returned %#hx\n", result );
801
802   do {
803     /* Increment info_count, abort if too many attempts.
804      * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
805      */
806     info_count++;
807     if ( info_count > MAX_JOIN_INFO_COUNT ) {
808       printf ( "Too many failed attempts - aborting\n" );
809       return 0;
810     }
811
812     /* Wait for info frame to indicate link status */
813     if ( sizeof(hardcoded_ssid) == 1 ) {
814       /* Empty SSID => join to any SSID */
815       printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count );
816     } else {
817       printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count );
818     }
819     
820     if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0;
821     printf("done\n");
822     infofid = hfa384x_getreg(hw, HFA384x_INFOFID);
823     /* Retrieve the length */
824     result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(UINT16));
825     if ( result ) return 0; /* fail */
826     inf.framelen = hfa384x2host_16(inf.framelen);
827     /* Retrieve the rest */
828     result = hfa384x_copy_from_bap( hw, infofid, sizeof(UINT16),
829                                     &(inf.infotype), inf.framelen * sizeof(UINT16));
830     if ( result ) return 0; /* fail */
831     if ( inf.infotype != HFA384x_IT_LINKSTATUS ) {
832       /* Not a Link Status info frame: die */
833       printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf.infotype );
834       return 0;
835     }
836     inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus);
837     if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) {
838       /* Link not connected - retry */
839       printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus );
840     }
841   } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
842     
843   /* Retrieve BSSID and print Connected message */
844   result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
845   printf ( "Link connected (BSSID %! - MAC address %!)\n", hw->bssid, nic->node_addr );
846   
847   /* point to NIC specific routines */
848   nic->nic_op   = &prism2_operations;
849   return 1;
850 }
851