1 /**************************************************************************
2 Etherboot - BOOTP/TFTP Bootstrap Program
3 Prism2 NIC driver for Etherboot
5 Written by Michael Brown of Fen Systems Ltd
7 ***************************************************************************/
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.
16 FILE_LICENCE ( GPL2_OR_LATER
);
18 #include <etherboot.h>
21 #include <gpxe/ethernet.h>
25 * Leave blank in order to connect to any available SSID
28 static const char hardcoded_ssid
[] = "";
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
36 * 2 is probably a sensible value, but YMMV.
39 #define MAX_JOIN_INFO_COUNT 2
42 * Type of Prism2 interface to support
43 * If not already defined, select PLX
46 #define WLAN_HOSTIF WLAN_PLX
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
54 #define __LINUX_WLAN__
57 #include "wlan_compat.h"
58 #include "p80211hdr.h"
60 #define BAP_TIMEOUT ( 5000 )
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.
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)
72 #define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(n)))
73 #define hfa384x2host_32(n) (__le32_to_cpu((UINT32)(n)))
74 #define host2hfa384x_16(n) (__cpu_to_le16((UINT16)(n)))
75 #define host2hfa384x_32(n) (__cpu_to_le32((UINT32)(n)))
78 * PLX9052 PCI register offsets
79 * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
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 )
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 )
91 #define PRISM2_PCI_MEM_BASE ( PCI_BASE_ADDRESS_0 )
95 * Taken from cistpl.h in pcmcia-cs
98 #define CISTPL_VERS_1 ( 0x15 )
99 #define CISTPL_END ( 0xff )
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 )
108 * Taken from prism2sta.c in linux-wlan-ng
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) */
114 /* NIC specific static variables */
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.
120 typedef struct hfa384x
125 UINT16 status
; /* in host order */
126 UINT16 resp0
; /* in host order */
127 UINT16 resp1
; /* in host order */
128 UINT16 resp2
; /* in host order */
129 UINT8 bssid
[WLAN_BSSID_LEN
];
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 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}
138 * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
139 * Taken from p80211conv.h
142 typedef struct wlan_llc
149 static const wlan_llc_t wlan_llc_snap
= { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
151 #define WLAN_IEEE_OUI_LEN 3
152 typedef struct wlan_snap
154 UINT8 oui
[WLAN_IEEE_OUI_LEN
];
158 typedef struct wlan_80211hdr
165 * Function prototypes
169 * Hardware-level hfa384x functions
170 * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
171 * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions.
174 /* Retrieve the value of one of the MAC registers. */
175 static inline UINT16
hfa384x_getreg( hfa384x_t
*hw
, UINT reg
)
177 #if (WLAN_HOSTIF == WLAN_PLX)
178 return inw ( hw
->iobase
+ reg
);
179 #elif (WLAN_HOSTIF == WLAN_PCI)
180 return readw ( hw
->membase
+ reg
);
184 /* Set the value of one of the MAC registers. */
185 static inline void hfa384x_setreg( hfa384x_t
*hw
, UINT16 val
, UINT reg
)
187 #if (WLAN_HOSTIF == WLAN_PLX)
188 outw ( val
, hw
->iobase
+ reg
);
189 #elif (WLAN_HOSTIF == WLAN_PCI)
190 writew ( val
, hw
->membase
+ reg
);
197 * Etherboot is i386 only, so swap and noswap are the same...
199 static inline UINT16
hfa384x_getreg_noswap( hfa384x_t
*hw
, UINT reg
)
201 return hfa384x_getreg ( hw
, reg
);
203 static inline void hfa384x_setreg_noswap( hfa384x_t
*hw
, UINT16 val
, UINT reg
)
205 hfa384x_setreg ( hw
, val
, reg
);
209 * Low-level hfa384x functions
210 * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
216 * Waits for availability of the Command register, then
217 * issues the given command. Then polls the Evstat register
218 * waiting for command completion.
220 * hw device structure
221 * cmd Command in host order
222 * parm0 Parameter0 in host order
223 * parm1 Parameter1 in host order
224 * parm2 Parameter2 in host order
227 * >0 command indicated error, Status and Resp0-2 are
230 static int hfa384x_docmd_wait( hfa384x_t
*hw
, UINT16 cmd
, UINT16 parm0
, UINT16 parm1
, UINT16 parm2
)
235 /* wait for the busy bit to clear */
237 reg
= hfa384x_getreg(hw
, HFA384x_CMD
);
238 while ( HFA384x_CMD_ISBUSY(reg
) && (counter
< 10) ) {
239 reg
= hfa384x_getreg(hw
, HFA384x_CMD
);
243 if (HFA384x_CMD_ISBUSY(reg
)) {
244 printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg
);
248 /* busy bit clear, write command */
249 hfa384x_setreg(hw
, parm0
, HFA384x_PARAM0
);
250 hfa384x_setreg(hw
, parm1
, HFA384x_PARAM1
);
251 hfa384x_setreg(hw
, parm2
, HFA384x_PARAM2
);
253 hfa384x_setreg(hw
, cmd
, HFA384x_CMD
);
255 /* Now wait for completion */
257 reg
= hfa384x_getreg(hw
, HFA384x_EVSTAT
);
258 /* Initialization is the problem. It takes about
259 100ms. "normal" commands are typically is about
260 200-400 us (I've never seen less than 200). Longer
261 is better so that we're not hammering the bus. */
262 while ( !HFA384x_EVSTAT_ISCMD(reg
) && (counter
< 5000)) {
263 reg
= hfa384x_getreg(hw
, HFA384x_EVSTAT
);
267 if ( ! HFA384x_EVSTAT_ISCMD(reg
) ) {
268 printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg
);
272 /* Read status and response */
273 hw
->status
= hfa384x_getreg(hw
, HFA384x_STATUS
);
274 hw
->resp0
= hfa384x_getreg(hw
, HFA384x_RESP0
);
275 hw
->resp1
= hfa384x_getreg(hw
, HFA384x_RESP1
);
276 hw
->resp2
= hfa384x_getreg(hw
, HFA384x_RESP2
);
277 hfa384x_setreg(hw
, HFA384x_EVACK_CMD
, HFA384x_EVACK
);
278 return HFA384x_STATUS_RESULT_GET(hw
->status
);
282 * Prepare BAP for access. Assigns FID and RID, sets offset register
283 * and waits for BAP to become available.
286 * hw device structure
287 * id FID or RID, destined for the select register (host order)
288 * offset An _even_ offset into the buffer for the given FID/RID.
292 static int hfa384x_prepare_bap(hfa384x_t
*hw
, UINT16 id
, UINT16 offset
)
298 /* Validate offset, buf, and len */
299 if ( (offset
> HFA384x_BAP_OFFSET_MAX
) || (offset
% 2) ) {
302 /* Write fid/rid and offset */
303 hfa384x_setreg(hw
, id
, HFA384x_SELECT0
);
305 hfa384x_setreg(hw
, offset
, HFA384x_OFFSET0
);
306 /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
309 reg
= hfa384x_getreg(hw
, HFA384x_OFFSET0
);
310 if ( i
> 0 ) udelay(2);
312 } while ( i
< BAP_TIMEOUT
&& HFA384x_OFFSET_ISBUSY(reg
));
313 if ( i
>= BAP_TIMEOUT
) {
316 } else if ( HFA384x_OFFSET_ISERR(reg
) ){
325 * Copy data from BAP to memory.
328 * hw device structure
329 * id FID or RID, destined for the select register (host order)
330 * offset An _even_ offset into the buffer for the given FID/RID.
331 * buf ptr to array of bytes
332 * len length of data to transfer in bytes
336 static int hfa384x_copy_from_bap(hfa384x_t
*hw
, UINT16 id
, UINT16 offset
,
340 UINT8
*d
= (UINT8
*)buf
;
345 result
= hfa384x_prepare_bap ( hw
, id
, offset
);
347 /* Read even(len) buf contents from data reg */
348 for ( i
= 0; i
< (len
& 0xfffe); i
+=2 ) {
349 *(UINT16
*)(&(d
[i
])) = hfa384x_getreg_noswap(hw
, HFA384x_DATA0
);
351 /* If len odd, handle last byte */
353 reg
= hfa384x_getreg_noswap(hw
, HFA384x_DATA0
);
354 d
[len
-1] = ((UINT8
*)(®
))[0];
358 printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id
, offset
, len
, result
);
364 * Copy data from memory to BAP.
367 * hw device structure
368 * id FID or RID, destined for the select register (host order)
369 * offset An _even_ offset into the buffer for the given FID/RID.
370 * buf ptr to array of bytes
371 * len length of data to transfer in bytes
375 static int hfa384x_copy_to_bap(hfa384x_t
*hw
, UINT16 id
, UINT16 offset
,
379 UINT8
*d
= (UINT8
*)buf
;
384 result
= hfa384x_prepare_bap ( hw
, id
, offset
);
386 /* Write even(len) buf contents to data reg */
387 for ( i
= 0; i
< (len
& 0xfffe); i
+=2 ) {
388 hfa384x_setreg_noswap(hw
, *(UINT16
*)(&(d
[i
])), HFA384x_DATA0
);
390 /* If len odd, handle last byte */
392 savereg
= hfa384x_getreg_noswap(hw
, HFA384x_DATA0
);
393 result
= hfa384x_prepare_bap ( hw
, id
, offset
+ (len
& 0xfffe) );
395 ((UINT8
*)(&savereg
))[0] = d
[len
-1];
396 hfa384x_setreg_noswap(hw
, savereg
, HFA384x_DATA0
);
401 printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id
, offset
, len
, result
);
407 * Request a given record to be copied to/from the record buffer.
410 * hw device structure
411 * write [0|1] copy the record buffer to the given
412 * configuration record. (host order)
413 * rid RID of the record to read/write. (host order)
418 static inline int hfa384x_cmd_access(hfa384x_t
*hw
, UINT16 write
, UINT16 rid
)
420 return hfa384x_docmd_wait(hw
, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS
) | HFA384x_CMD_WRITE_SET(write
), rid
, 0, 0);
424 * Performs the sequence necessary to read a config/info item.
427 * hw device structure
428 * rid config/info record id (host order)
429 * buf host side record buffer. Upon return it will
430 * contain the body portion of the record (minus the
432 * len buffer length (in bytes, should match record length)
437 static int hfa384x_drvr_getconfig(hfa384x_t
*hw
, UINT16 rid
, void *buf
, UINT16 len
)
442 /* Request read of RID */
443 result
= hfa384x_cmd_access( hw
, 0, rid
);
445 printf("Call to hfa384x_cmd_access failed\n");
448 /* Copy out record length */
449 result
= hfa384x_copy_from_bap( hw
, rid
, 0, &rec
, sizeof(rec
));
453 /* Validate the record length */
454 if ( ((hfa384x2host_16(rec
.reclen
)-1)*2) != len
) { /* note body len calculation in bytes */
455 printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid
, len
, (hfa384x2host_16(rec
.reclen
)-1)*2);
458 /* Copy out record data */
459 result
= hfa384x_copy_from_bap( hw
, rid
, sizeof(rec
), buf
, len
);
464 * Performs the sequence necessary to read a 16/32 bit config/info item
465 * and convert it to host order.
468 * hw device structure
469 * rid config/info record id (in host order)
470 * val ptr to 16/32 bit buffer to receive value (in host order)
475 #if 0 /* Not actually used anywhere */
476 static int hfa384x_drvr_getconfig16(hfa384x_t
*hw
, UINT16 rid
, void *val
)
479 result
= hfa384x_drvr_getconfig(hw
, rid
, val
, sizeof(UINT16
));
481 *((UINT16
*)val
) = hfa384x2host_16(*((UINT16
*)val
));
486 #if 0 /* Not actually used anywhere */
487 static int hfa384x_drvr_getconfig32(hfa384x_t
*hw
, UINT16 rid
, void *val
)
490 result
= hfa384x_drvr_getconfig(hw
, rid
, val
, sizeof(UINT32
));
492 *((UINT32
*)val
) = hfa384x2host_32(*((UINT32
*)val
));
499 * Performs the sequence necessary to write a config/info item.
502 * hw device structure
503 * rid config/info record id (in host order)
504 * buf host side record buffer
505 * len buffer length (in bytes)
510 static int hfa384x_drvr_setconfig(hfa384x_t
*hw
, UINT16 rid
, void *buf
, UINT16 len
)
515 rec
.rid
= host2hfa384x_16(rid
);
516 rec
.reclen
= host2hfa384x_16((len
/2) + 1); /* note conversion to words, +1 for rid field */
517 /* write the record header */
518 result
= hfa384x_copy_to_bap( hw
, rid
, 0, &rec
, sizeof(rec
));
520 printf("Failure writing record header\n");
523 /* write the record data (if there is any) */
525 result
= hfa384x_copy_to_bap( hw
, rid
, sizeof(rec
), buf
, len
);
527 printf("Failure writing record data\n");
531 /* Trigger setting of record */
532 result
= hfa384x_cmd_access( hw
, 1, rid
);
537 * Performs the sequence necessary to write a 16/32 bit config/info item.
540 * hw device structure
541 * rid config/info record id (in host order)
542 * val 16/32 bit value to store (in host order)
547 static int hfa384x_drvr_setconfig16(hfa384x_t
*hw
, UINT16 rid
, UINT16
*val
)
550 value
= host2hfa384x_16(*val
);
551 return hfa384x_drvr_setconfig(hw
, rid
, &value
, sizeof(UINT16
));
553 #if 0 /* Not actually used anywhere */
554 static int hfa384x_drvr_setconfig32(hfa384x_t
*hw
, UINT16 rid
, UINT32
*val
)
557 value
= host2hfa384x_32(*val
);
558 return hfa384x_drvr_setconfig(hw
, rid
, &value
, sizeof(UINT32
));
563 * Wait for an event, with specified checking interval and timeout.
564 * Automatically acknolwedges events.
567 * hw device structure
568 * event_mask EVSTAT register mask of events to wait for
569 * event_ack EVACK register set of events to be acknowledged if they happen (can be
570 * used to acknowledge "ignorable" events in addition to the "main" event)
571 * wait Time (in us) to wait between each poll of the register
572 * timeout Maximum number of polls before timing out
573 * descr Descriptive text string of what is being waited for
574 * (will be printed out if a timeout happens)
577 * value of EVSTAT register, or 0 on failure
579 static int hfa384x_wait_for_event(hfa384x_t
*hw
, UINT16 event_mask
, UINT16 event_ack
, int wait
, int timeout
, const char *descr
)
585 reg
= hfa384x_getreg(hw
, HFA384x_EVSTAT
);
586 if ( count
> 0 ) udelay(wait
);
588 } while ( !(reg
& event_mask
) && count
< timeout
);
589 if ( count
>= timeout
) {
590 printf("hfa384x: Timed out waiting for %s\n", descr
);
591 return 0; /* Return failure */
593 /* Acknowledge all events that we were waiting on */
594 hfa384x_setreg(hw
, reg
& ( event_mask
| event_ack
), HFA384x_EVACK
);
598 /**************************************************************************
599 POLL - Wait for a frame
600 ***************************************************************************/
601 static int prism2_poll(struct nic
*nic
, int retrieve
)
606 hfa384x_rx_frame_t rxdesc
;
607 hfa384x_t
*hw
= &hw_global
;
609 /* Check for received packet */
610 reg
= hfa384x_getreg(hw
, HFA384x_EVSTAT
);
611 if ( ! HFA384x_EVSTAT_ISRX(reg
) ) {
612 /* No packet received - return 0 */
616 if ( ! retrieve
) return 1;
618 /* Acknowledge RX event */
619 hfa384x_setreg(hw
, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK
);
621 rxfid
= hfa384x_getreg(hw
, HFA384x_RXFID
);
622 /* Get the descriptor (including headers) */
623 result
= hfa384x_copy_from_bap(hw
, rxfid
, 0, &rxdesc
, sizeof(rxdesc
));
627 /* Byte order convert once up front. */
628 rxdesc
.status
= hfa384x2host_16(rxdesc
.status
);
629 rxdesc
.time
= hfa384x2host_32(rxdesc
.time
);
630 rxdesc
.data_len
= hfa384x2host_16(rxdesc
.data_len
);
632 /* Fill in nic->packetlen */
633 nic
->packetlen
= rxdesc
.data_len
;
634 if ( nic
->packetlen
> 0 ) {
635 /* Fill in nic->packet */
637 * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
638 * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
639 * header), so we use a quick hack to achieve this.
641 result
= hfa384x_copy_from_bap(hw
, rxfid
, HFA384x_RX_DATA_OFF
,
642 nic
->packet
+ ETH_HLEN
- sizeof(wlan_80211hdr_t
), nic
->packetlen
);
647 return 1; /* Packet successfully received */
650 /**************************************************************************
651 TRANSMIT - Transmit a frame
652 ***************************************************************************/
653 static void prism2_transmit(
655 const char *d
, /* Destination */
656 unsigned int t
, /* Type */
657 unsigned int s
, /* size */
658 const char *p
) /* Packet */
660 hfa384x_t
*hw
= &hw_global
;
661 hfa384x_tx_frame_t txdesc
;
662 wlan_80211hdr_t p80211hdr
= { wlan_llc_snap
, {{0,0,0},0} };
667 // Request FID allocation
668 result
= hfa384x_docmd_wait(hw
, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC
), HFA384x_DRVR_TXBUF_MAX
, 0, 0);
670 printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
673 if ( !hfa384x_wait_for_event(hw
, HFA384x_EVSTAT_ALLOC
, HFA384x_EVACK_INFO
, 10, 50, "Tx FID to be allocated\n" ) ) return;
674 fid
= hfa384x_getreg(hw
, HFA384x_ALLOCFID
);
676 /* Build Tx frame structure */
677 memset(&txdesc
, 0, sizeof(txdesc
));
678 txdesc
.tx_control
= host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
679 HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
680 txdesc
.frame_control
= host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA
) |
681 WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY
) |
682 WLAN_SET_FC_TODS(1) );
683 memcpy(txdesc
.address1
, hw
->bssid
, WLAN_ADDR_LEN
);
684 memcpy(txdesc
.address2
, nic
->node_addr
, WLAN_ADDR_LEN
);
685 memcpy(txdesc
.address3
, d
, WLAN_ADDR_LEN
);
686 txdesc
.data_len
= host2hfa384x_16( sizeof(txdesc
) + sizeof(p80211hdr
) + s
);
687 /* Set up SNAP header */
688 /* Let OUI default to RFC1042 (0x000000) */
689 p80211hdr
.snap
.type
= htons(t
);
691 /* Copy txdesc, p80211hdr and payload parts to FID */
692 result
= hfa384x_copy_to_bap(hw
, fid
, 0, &txdesc
, sizeof(txdesc
));
693 if ( result
) return; /* fail */
694 result
= hfa384x_copy_to_bap( hw
, fid
, sizeof(txdesc
), &p80211hdr
, sizeof(p80211hdr
) );
695 if ( result
) return; /* fail */
696 result
= hfa384x_copy_to_bap( hw
, fid
, sizeof(txdesc
) + sizeof(p80211hdr
), (UINT8
*)p
, s
);
697 if ( result
) return; /* fail */
699 /* Issue Tx command */
700 result
= hfa384x_docmd_wait(hw
, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX
), fid
, 0, 0);
702 printf("hfa384x: Transmit failed with result %#hx.\n", result
);
706 /* Wait for transmit completion (or exception) */
707 result
= hfa384x_wait_for_event(hw
, HFA384x_EVSTAT_TXEXC
| HFA384x_EVSTAT_TX
, HFA384x_EVACK_INFO
,
708 200, 500, "Tx to complete\n" );
709 if ( !result
) return; /* timeout failure */
710 if ( HFA384x_EVSTAT_ISTXEXC(result
) ) {
711 fid
= hfa384x_getreg(hw
, HFA384x_TXCOMPLFID
);
712 printf ( "Tx exception occurred with fid %#hx\n", fid
);
713 result
= hfa384x_copy_from_bap(hw
, fid
, 0, &status
, sizeof(status
));
714 if ( result
) return; /* fail */
715 printf("hfa384x: Tx error occurred (status %#hx):\n", status
);
716 if ( HFA384x_TXSTATUS_ISACKERR(status
) ) { printf(" ...acknowledgement error\n"); }
717 if ( HFA384x_TXSTATUS_ISFORMERR(status
) ) { printf(" ...format error\n"); }
718 if ( HFA384x_TXSTATUS_ISDISCON(status
) ) { printf(" ...disconnected error\n"); }
719 if ( HFA384x_TXSTATUS_ISAGEDERR(status
) ) { printf(" ...AGED error\n"); }
720 if ( HFA384x_TXSTATUS_ISRETRYERR(status
) ) { printf(" ...retry error\n"); }
725 /**************************************************************************
726 DISABLE - Turn off ethernet interface
727 ***************************************************************************/
728 static void prism2_disable ( struct nic
*nic __unused
) {
729 /* put the card in its initial state */
732 /**************************************************************************
733 IRQ - Enable, Disable, or Force interrupts
734 ***************************************************************************/
735 static void prism2_irq(struct nic
*nic __unused
, irq_action_t action __unused
)
747 /**************************************************************************
749 ***************************************************************************/
750 static struct nic_operations prism2_operations
= {
751 .connect
= dummy_connect
,
753 .transmit
= prism2_transmit
,
757 /**************************************************************************
758 PROBE - Look for an adapter, this routine's visible to the outside
759 You should omit the last argument struct pci_device * for a non-PCI NIC
760 ***************************************************************************/
761 static int prism2_probe ( struct nic
*nic
, hfa384x_t
*hw
) {
765 hfa384x_InfFrame_t inf
;
766 char ssid
[HFA384x_RID_CNFDESIREDSSID_LEN
];
771 /* Initialize card */
772 result
= hfa384x_docmd_wait(hw
, HFA384x_CMDCODE_INIT
, 0,0,0); /* Send initialize command */
773 if ( result
) printf ( "Initialize command returned %#hx\n", result
);
774 hfa384x_setreg(hw
, 0, HFA384x_INTEN
); /* Disable interrupts */
775 hfa384x_setreg(hw
, 0xffff, HFA384x_EVACK
); /* Acknowledge any spurious events */
777 DBG ( "MAC address %s\n", eth_ntoa ( nic
->node_addr
) );
779 /* Retrieve MAC address (and fill out nic->node_addr) */
780 hfa384x_drvr_getconfig ( hw
, HFA384x_RID_CNFOWNMACADDR
, nic
->node_addr
, HFA384x_RID_CNFOWNMACADDR_LEN
);
782 /* Prepare card for autojoin */
783 /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
784 tmp16
= WLAN_DATA_MAXLEN
; /* Set maximum data length */
785 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFMAXDATALEN
, &tmp16
);
786 if ( result
) printf ( "Set Max Data Length command returned %#hx\n", result
);
787 tmp16
= 0x000f; /* Set transmit rate(?) */
788 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_TXRATECNTL
, &tmp16
);
789 if ( result
) printf ( "Set Transmit Rate command returned %#hx\n", result
);
790 tmp16
= HFA384x_CNFAUTHENTICATION_OPENSYSTEM
; /* Set authentication type to OpenSystem */
791 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFAUTHENTICATION
, &tmp16
);
792 if ( result
) printf ( "Set Authentication Type command returned %#hx\n", result
);
794 memset(ssid
, 0, HFA384x_RID_CNFDESIREDSSID_LEN
);
795 for ( tmp16
=0; tmp16
<sizeof(hardcoded_ssid
); tmp16
++ ) { ssid
[2+tmp16
] = hardcoded_ssid
[tmp16
]; }
796 ssid
[0] = sizeof(hardcoded_ssid
) - 1; /* Ignore terminating zero */
797 result
= hfa384x_drvr_setconfig(hw
, HFA384x_RID_CNFDESIREDSSID
, ssid
, HFA384x_RID_CNFDESIREDSSID_LEN
); /* Set the SSID */
798 if ( result
) printf ( "Set SSID command returned %#hx\n", result
);
799 tmp16
= 1; /* Set port type to ESS port */
800 result
= hfa384x_drvr_setconfig16(hw
, HFA384x_RID_CNFPORTTYPE
, &tmp16
);
801 if ( result
) printf ( "Set port type command returned %#hx\n", result
);
803 result
= hfa384x_docmd_wait(hw
, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE
) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
804 if ( result
) printf ( "Enable command returned %#hx\n", result
);
807 /* Increment info_count, abort if too many attempts.
808 * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
811 if ( info_count
> MAX_JOIN_INFO_COUNT
) {
812 printf ( "Too many failed attempts - aborting\n" );
816 /* Wait for info frame to indicate link status */
817 if ( sizeof(hardcoded_ssid
) == 1 ) {
818 /* Empty SSID => join to any SSID */
819 printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count
);
821 printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid
[2], info_count
);
824 if ( !hfa384x_wait_for_event(hw
, HFA384x_EVSTAT_INFO
, 0, 1000, 2000, "Info event" ) ) return 0;
826 infofid
= hfa384x_getreg(hw
, HFA384x_INFOFID
);
827 /* Retrieve the length */
828 result
= hfa384x_copy_from_bap( hw
, infofid
, 0, &inf
.framelen
, sizeof(UINT16
));
829 if ( result
) return 0; /* fail */
830 inf
.framelen
= hfa384x2host_16(inf
.framelen
);
831 /* Retrieve the rest */
832 result
= hfa384x_copy_from_bap( hw
, infofid
, sizeof(UINT16
),
833 &(inf
.infotype
), inf
.framelen
* sizeof(UINT16
));
834 if ( result
) return 0; /* fail */
835 if ( inf
.infotype
!= HFA384x_IT_LINKSTATUS
) {
836 /* Not a Link Status info frame: die */
837 printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf
.infotype
);
840 inf
.info
.linkstatus
.linkstatus
= hfa384x2host_16(inf
.info
.linkstatus
.linkstatus
);
841 if ( inf
.info
.linkstatus
.linkstatus
!= HFA384x_LINK_CONNECTED
) {
842 /* Link not connected - retry */
843 printf ( "Link not connected (status %#hx)\n", inf
.info
.linkstatus
.linkstatus
);
845 } while ( inf
.info
.linkstatus
.linkstatus
!= HFA384x_LINK_CONNECTED
);
847 /* Retrieve BSSID and print Connected message */
848 result
= hfa384x_drvr_getconfig(hw
, HFA384x_RID_CURRENTBSSID
, hw
->bssid
, WLAN_BSSID_LEN
);
850 DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw
->bssid
) );
851 DBG ( " MAC address %s)\n", eth_ntoa (nic
->node_addr
) );
853 /* point to NIC specific routines */
854 nic
->nic_op
= &prism2_operations
;