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 {
132 uint32_t iobase;
133 void *membase;
134 uint16_t lastcmd;
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 */
139 uint8_t bssid[WLAN_BSSID_LEN];
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 */
143 static hfa384x_t hw_global;
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 {
152 uint8_t dsap;
153 uint8_t ssap;
154 uint8_t ctl;
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 {
162 uint8_t oui[WLAN_IEEE_OUI_LEN];
163 uint16_t type;
164 } wlan_snap_t;
165
166 typedef struct wlan_80211hdr
167 {
168 wlan_llc_t llc;
169 wlan_snap_t snap;
170 } wlan_80211hdr_t;
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. */
hfa384x_getreg(hfa384x_t * hw,unsigned int reg)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. */
hfa384x_setreg(hfa384x_t * hw,uint16_t val,unsigned int reg)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 */
hfa384x_getreg_noswap(hfa384x_t * hw,unsigned int reg)207 static inline uint16_t hfa384x_getreg_noswap( hfa384x_t *hw, unsigned int reg )
208 {
209 return hfa384x_getreg ( hw, reg );
210 }
hfa384x_setreg_noswap(hfa384x_t * hw,uint16_t val,unsigned int reg)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 */
hfa384x_docmd_wait(hfa384x_t * hw,uint16_t cmd,uint16_t parm0,uint16_t parm1,uint16_t parm2)238 static int hfa384x_docmd_wait( hfa384x_t *hw, uint16_t cmd, uint16_t parm0, uint16_t parm1, uint16_t parm2)
239 {
240 uint16_t reg = 0;
241 uint16_t counter = 0;
242
243 /* wait for the busy bit to clear */
244 counter = 0;
245 reg = hfa384x_getreg(hw, HFA384x_CMD);
246 while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
247 reg = hfa384x_getreg(hw, HFA384x_CMD);
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 */
257 hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
258 hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
259 hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
260 hw->lastcmd = cmd;
261 hfa384x_setreg(hw, cmd, HFA384x_CMD);
262
263 /* Now wait for completion */
264 counter = 0;
265 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
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)) {
271 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
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);
285 hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
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 */
hfa384x_prepare_bap(hfa384x_t * hw,uint16_t id,uint16_t offset)300 static int hfa384x_prepare_bap(hfa384x_t *hw, uint16_t id, uint16_t offset)
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 */
311 hfa384x_setreg(hw, id, HFA384x_SELECT0);
312 udelay(10);
313 hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
314 /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
315 i = 0;
316 do {
317 reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
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 */
hfa384x_copy_from_bap(hfa384x_t * hw,uint16_t id,uint16_t offset,void * buf,unsigned int len)344 static int hfa384x_copy_from_bap(hfa384x_t *hw, uint16_t id, uint16_t offset,
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 ) {
357 *(uint16_t*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
358 }
359 /* If len odd, handle last byte */
360 if ( len % 2 ){
361 reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
362 d[len-1] = ((uint8_t*)(®))[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 */
hfa384x_copy_to_bap(hfa384x_t * hw,uint16_t id,uint16_t offset,void * buf,unsigned int len)383 static int hfa384x_copy_to_bap(hfa384x_t *hw, uint16_t id, uint16_t offset,
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 ) {
396 hfa384x_setreg_noswap(hw, *(uint16_t*)(&(d[i])), HFA384x_DATA0);
397 }
398 /* If len odd, handle last byte */
399 if ( len % 2 ){
400 savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
401 result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
402 if ( result == 0 ) {
403 ((uint8_t*)(&savereg))[0] = d[len-1];
404 hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
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 */
hfa384x_cmd_access(hfa384x_t * hw,uint16_t write,uint16_t rid)426 static inline int hfa384x_cmd_access(hfa384x_t *hw, uint16_t write, uint16_t rid)
427 {
428 return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
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 */
hfa384x_drvr_getconfig(hfa384x_t * hw,uint16_t rid,void * buf,uint16_t len)445 static int hfa384x_drvr_getconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
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 */
hfa384x_drvr_setconfig(hfa384x_t * hw,uint16_t rid,void * buf,uint16_t len)518 static int hfa384x_drvr_setconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
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 */
hfa384x_drvr_setconfig16(hfa384x_t * hw,uint16_t rid,uint16_t * val)555 static int hfa384x_drvr_setconfig16(hfa384x_t *hw, uint16_t rid, uint16_t *val)
556 {
557 uint16_t value;
558 value = host2hfa384x_16(*val);
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;
565 value = host2hfa384x_32(*val);
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 */
hfa384x_wait_for_event(hfa384x_t * hw,uint16_t event_mask,uint16_t event_ack,int wait,int timeout,const char * descr)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 {
593 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
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 ***************************************************************************/
prism2_poll(struct nic * nic,int retrieve)609 static int prism2_poll(struct nic *nic, int retrieve)
610 {
611 uint16_t reg;
612 uint16_t rxfid;
613 uint16_t result;
614 hfa384x_rx_frame_t rxdesc;
615 hfa384x_t *hw = &hw_global;
616
617 /* Check for received packet */
618 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
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 */
627 hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
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. */
636 rxdesc.status = hfa384x2host_16(rxdesc.status);
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 */
649 result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
650 nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
651 if ( result ) {
652 return 0; /* fail */
653 }
654 }
655 return 1; /* Packet successfully received */
656 }
657
658 /**************************************************************************
659 TRANSMIT - Transmit a frame
660 ***************************************************************************/
prism2_transmit(struct nic * nic,const char * d,unsigned int t,unsigned int s,const char * p)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;
669 hfa384x_tx_frame_t txdesc;
670 wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
671 uint16_t fid;
672 uint16_t status;
673 int result;
674
675 // Request FID allocation
676 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
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;
682 fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
683
684 /* Build Tx frame structure */
685 memset(&txdesc, 0, sizeof(txdesc));
686 txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
687 HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
688 txdesc.frame_control = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
689 WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
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 */
708 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
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) */
715 result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
716 200, 500, "Tx to complete\n" );
717 if ( !result ) return; /* timeout failure */
718 if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
719 fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
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 ***************************************************************************/
prism2_disable(struct nic * nic __unused)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 ***************************************************************************/
prism2_irq(struct nic * nic __unused,irq_action_t action __unused)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 ***************************************************************************/
758 static struct nic_operations prism2_operations = {
759 .connect = dummy_connect,
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 ***************************************************************************/
prism2_probe(struct nic * nic,hfa384x_t * hw)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;
774 char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
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) */
788 hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
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 */
793 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16);
794 if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result );
795 tmp16 = 0x000f; /* Set transmit rate(?) */
796 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16);
797 if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result );
798 tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */
799 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16);
800 if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result );
801 /* Set SSID */
802 memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN);
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 */
805 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */
806 if ( result ) printf ( "Set SSID command returned %#hx\n", result );
807 tmp16 = 1; /* Set port type to ESS port */
808 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16);
809 if ( result ) printf ( "Set port type command returned %#hx\n", result );
810 /* Enable card */
811 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
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 }
848 inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus);
849 if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) {
850 /* Link not connected - retry */
851 printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus );
852 }
853 } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
854
855 /* Retrieve BSSID and print Connected message */
856 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
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 */
862 nic->nic_op = &prism2_operations;
863 return 1;
864 }
865
866