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