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