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