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