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 <ipxe/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_t)(n)))
73 #define hfa384x2host_32(n) (__le32_to_cpu((uint32_t)(n)))
74 #define host2hfa384x_16(n) (__cpu_to_le16((uint16_t)(n)))
75 #define host2hfa384x_32(n) (__cpu_to_le32((uint32_t)(n)))
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_t status; /* in host order */
126 uint16_t resp0; /* in host order */
127 uint16_t resp1; /* in host order */
128 uint16_t resp2; /* in host order */
129 uint8_t bssid[WLAN_BSSID_LEN];
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;
136 * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
137 * Taken from p80211conv.h
140 typedef struct wlan_llc
147 static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
149 #define WLAN_IEEE_OUI_LEN 3
150 typedef struct wlan_snap
152 uint8_t oui[WLAN_IEEE_OUI_LEN];
156 typedef struct wlan_80211hdr
163 * Function prototypes
167 * Hardware-level hfa384x functions
168 * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
169 * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions.
172 /* Retrieve the value of one of the MAC registers. */
173 static inline uint16_t hfa384x_getreg( hfa384x_t *hw, unsigned int reg )
175 #if (WLAN_HOSTIF == WLAN_PLX)
176 return inw ( hw->iobase + reg );
177 #elif (WLAN_HOSTIF == WLAN_PCI)
178 return readw ( hw->membase + reg );
182 /* Set the value of one of the MAC registers. */
183 static inline void hfa384x_setreg( hfa384x_t *hw, uint16_t val, unsigned int reg )
185 #if (WLAN_HOSTIF == WLAN_PLX)
186 outw ( val, hw->iobase + reg );
187 #elif (WLAN_HOSTIF == WLAN_PCI)
188 writew ( val, hw->membase + reg );
195 * Etherboot is i386 only, so swap and noswap are the same...
197 static inline uint16_t hfa384x_getreg_noswap( hfa384x_t *hw, unsigned int reg )
199 return hfa384x_getreg ( hw, reg );
201 static inline void hfa384x_setreg_noswap( hfa384x_t *hw, uint16_t val, unsigned int reg )
203 hfa384x_setreg ( hw, val, reg );
207 * Low-level hfa384x functions
208 * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
214 * Waits for availability of the Command register, then
215 * issues the given command. Then polls the Evstat register
216 * waiting for command completion.
218 * hw device structure
219 * cmd Command in host order
220 * parm0 Parameter0 in host order
221 * parm1 Parameter1 in host order
222 * parm2 Parameter2 in host order
225 * >0 command indicated error, Status and Resp0-2 are
228 static int hfa384x_docmd_wait( hfa384x_t *hw, uint16_t cmd, uint16_t parm0, uint16_t parm1, uint16_t parm2)
231 uint16_t counter = 0;
233 /* wait for the busy bit to clear */
235 reg = hfa384x_getreg(hw, HFA384x_CMD);
236 while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
237 reg = hfa384x_getreg(hw, HFA384x_CMD);
241 if (HFA384x_CMD_ISBUSY(reg)) {
242 printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
246 /* busy bit clear, write command */
247 hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
248 hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
249 hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
251 hfa384x_setreg(hw, cmd, HFA384x_CMD);
253 /* Now wait for completion */
255 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
256 /* Initialization is the problem. It takes about
257 100ms. "normal" commands are typically is about
258 200-400 us (I've never seen less than 200). Longer
259 is better so that we're not hammering the bus. */
260 while ( !HFA384x_EVSTAT_ISCMD(reg) && (counter < 5000)) {
261 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
265 if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
266 printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
270 /* Read status and response */
271 hw->status = hfa384x_getreg(hw, HFA384x_STATUS);
272 hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
273 hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
274 hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
275 hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
276 return HFA384x_STATUS_RESULT_GET(hw->status);
280 * Prepare BAP for access. Assigns FID and RID, sets offset register
281 * and waits for BAP to become available.
284 * hw device structure
285 * id FID or RID, destined for the select register (host order)
286 * offset An _even_ offset into the buffer for the given FID/RID.
290 static int hfa384x_prepare_bap(hfa384x_t *hw, uint16_t id, uint16_t offset)
296 /* Validate offset, buf, and len */
297 if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
300 /* Write fid/rid and offset */
301 hfa384x_setreg(hw, id, HFA384x_SELECT0);
303 hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
304 /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
307 reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
308 if ( i > 0 ) udelay(2);
310 } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
311 if ( i >= BAP_TIMEOUT ) {
314 } else if ( HFA384x_OFFSET_ISERR(reg) ){
323 * Copy data from BAP to memory.
326 * hw device structure
327 * id FID or RID, destined for the select register (host order)
328 * offset An _even_ offset into the buffer for the given FID/RID.
329 * buf ptr to array of bytes
330 * len length of data to transfer in bytes
334 static int hfa384x_copy_from_bap(hfa384x_t *hw, uint16_t id, uint16_t offset,
335 void *buf, unsigned int len)
338 uint8_t *d = (uint8_t*)buf;
343 result = hfa384x_prepare_bap ( hw, id, offset );
345 /* Read even(len) buf contents from data reg */
346 for ( i = 0; i < (len & 0xfffe); i+=2 ) {
347 *(uint16_t*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
349 /* If len odd, handle last byte */
351 reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
352 d[len-1] = ((uint8_t*)(®))[0];
356 printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
362 * Copy data from memory to BAP.
365 * hw device structure
366 * id FID or RID, destined for the select register (host order)
367 * offset An _even_ offset into the buffer for the given FID/RID.
368 * buf ptr to array of bytes
369 * len length of data to transfer in bytes
373 static int hfa384x_copy_to_bap(hfa384x_t *hw, uint16_t id, uint16_t offset,
374 void *buf, unsigned int len)
377 uint8_t *d = (uint8_t*)buf;
382 result = hfa384x_prepare_bap ( hw, id, offset );
384 /* Write even(len) buf contents to data reg */
385 for ( i = 0; i < (len & 0xfffe); i+=2 ) {
386 hfa384x_setreg_noswap(hw, *(uint16_t*)(&(d[i])), HFA384x_DATA0);
388 /* If len odd, handle last byte */
390 savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
391 result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
393 ((uint8_t*)(&savereg))[0] = d[len-1];
394 hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
399 printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
405 * Request a given record to be copied to/from the record buffer.
408 * hw device structure
409 * write [0|1] copy the record buffer to the given
410 * configuration record. (host order)
411 * rid RID of the record to read/write. (host order)
416 static inline int hfa384x_cmd_access(hfa384x_t *hw, uint16_t write, uint16_t rid)
418 return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
422 * Performs the sequence necessary to read a config/info item.
425 * hw device structure
426 * rid config/info record id (host order)
427 * buf host side record buffer. Upon return it will
428 * contain the body portion of the record (minus the
430 * len buffer length (in bytes, should match record length)
435 static int hfa384x_drvr_getconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
440 /* Request read of RID */
441 result = hfa384x_cmd_access( hw, 0, rid);
443 printf("Call to hfa384x_cmd_access failed\n");
446 /* Copy out record length */
447 result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
451 /* Validate the record length */
452 if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */
453 printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
456 /* Copy out record data */
457 result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
462 * Performs the sequence necessary to read a 16/32 bit config/info item
463 * and convert it to host order.
466 * hw device structure
467 * rid config/info record id (in host order)
468 * val ptr to 16/32 bit buffer to receive value (in host order)
473 #if 0 /* Not actually used anywhere */
474 static int hfa384x_drvr_getconfig16(hfa384x_t *hw, uint16_t rid, void *val)
477 result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint16_t));
479 *((uint16_t*)val) = hfa384x2host_16(*((uint16_t*)val));
484 #if 0 /* Not actually used anywhere */
485 static int hfa384x_drvr_getconfig32(hfa384x_t *hw, uint16_t rid, void *val)
488 result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint32_t));
490 *((uint32_t*)val) = hfa384x2host_32(*((uint32_t*)val));
497 * Performs the sequence necessary to write a config/info item.
500 * hw device structure
501 * rid config/info record id (in host order)
502 * buf host side record buffer
503 * len buffer length (in bytes)
508 static int hfa384x_drvr_setconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
513 rec.rid = host2hfa384x_16(rid);
514 rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
515 /* write the record header */
516 result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
518 printf("Failure writing record header\n");
521 /* write the record data (if there is any) */
523 result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
525 printf("Failure writing record data\n");
529 /* Trigger setting of record */
530 result = hfa384x_cmd_access( hw, 1, rid);
535 * Performs the sequence necessary to write a 16/32 bit config/info item.
538 * hw device structure
539 * rid config/info record id (in host order)
540 * val 16/32 bit value to store (in host order)
545 static int hfa384x_drvr_setconfig16(hfa384x_t *hw, uint16_t rid, uint16_t *val)
548 value = host2hfa384x_16(*val);
549 return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint16_t));
551 #if 0 /* Not actually used anywhere */
552 static int hfa384x_drvr_setconfig32(hfa384x_t *hw, uint16_t rid, uint32_t *val)
555 value = host2hfa384x_32(*val);
556 return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint32_t));
561 * Wait for an event, with specified checking interval and timeout.
562 * Automatically acknolwedges events.
565 * hw device structure
566 * event_mask EVSTAT register mask of events to wait for
567 * event_ack EVACK register set of events to be acknowledged if they happen (can be
568 * used to acknowledge "ignorable" events in addition to the "main" event)
569 * wait Time (in us) to wait between each poll of the register
570 * timeout Maximum number of polls before timing out
571 * descr Descriptive text string of what is being waited for
572 * (will be printed out if a timeout happens)
575 * value of EVSTAT register, or 0 on failure
577 static int hfa384x_wait_for_event(hfa384x_t *hw, uint16_t event_mask, uint16_t event_ack, int wait, int timeout, const char *descr)
583 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
584 if ( count > 0 ) udelay(wait);
586 } while ( !(reg & event_mask) && count < timeout);
587 if ( count >= timeout ) {
588 printf("hfa384x: Timed out waiting for %s\n", descr);
589 return 0; /* Return failure */
591 /* Acknowledge all events that we were waiting on */
592 hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
596 /**************************************************************************
597 POLL - Wait for a frame
598 ***************************************************************************/
599 static int prism2_poll(struct nic *nic, int retrieve)
604 hfa384x_rx_frame_t rxdesc;
605 hfa384x_t *hw = &hw_global;
607 /* Check for received packet */
608 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
609 if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
610 /* No packet received - return 0 */
614 if ( ! retrieve ) return 1;
616 /* Acknowledge RX event */
617 hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
619 rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
620 /* Get the descriptor (including headers) */
621 result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc));
625 /* Byte order convert once up front. */
626 rxdesc.status = hfa384x2host_16(rxdesc.status);
627 rxdesc.time = hfa384x2host_32(rxdesc.time);
628 rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
630 /* Fill in nic->packetlen */
631 nic->packetlen = rxdesc.data_len;
632 if ( nic->packetlen > 0 ) {
633 /* Fill in nic->packet */
635 * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
636 * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
637 * header), so we use a quick hack to achieve this.
639 result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
640 nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
645 return 1; /* Packet successfully received */
648 /**************************************************************************
649 TRANSMIT - Transmit a frame
650 ***************************************************************************/
651 static void prism2_transmit(
653 const char *d, /* Destination */
654 unsigned int t, /* Type */
655 unsigned int s, /* size */
656 const char *p) /* Packet */
658 hfa384x_t *hw = &hw_global;
659 hfa384x_tx_frame_t txdesc;
660 wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
665 // Request FID allocation
666 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
668 printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
671 if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
672 fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
674 /* Build Tx frame structure */
675 memset(&txdesc, 0, sizeof(txdesc));
676 txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
677 HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
678 txdesc.frame_control = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
679 WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
680 WLAN_SET_FC_TODS(1) );
681 memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
682 memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
683 memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
684 txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
685 /* Set up SNAP header */
686 /* Let OUI default to RFC1042 (0x000000) */
687 p80211hdr.snap.type = htons(t);
689 /* Copy txdesc, p80211hdr and payload parts to FID */
690 result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
691 if ( result ) return; /* fail */
692 result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
693 if ( result ) return; /* fail */
694 result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (uint8_t*)p, s );
695 if ( result ) return; /* fail */
697 /* Issue Tx command */
698 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
700 printf("hfa384x: Transmit failed with result %#hx.\n", result);
704 /* Wait for transmit completion (or exception) */
705 result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
706 200, 500, "Tx to complete\n" );
707 if ( !result ) return; /* timeout failure */
708 if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
709 fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
710 printf ( "Tx exception occurred with fid %#hx\n", fid );
711 result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
712 if ( result ) return; /* fail */
713 printf("hfa384x: Tx error occurred (status %#hx):\n", status);
714 if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
715 if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
716 if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
717 if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
718 if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
723 /**************************************************************************
724 DISABLE - Turn off ethernet interface
725 ***************************************************************************/
726 static void prism2_disable ( struct nic *nic __unused ) {
727 /* put the card in its initial state */
730 /**************************************************************************
731 IRQ - Enable, Disable, or Force interrupts
732 ***************************************************************************/
733 static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
745 /**************************************************************************
747 ***************************************************************************/
748 static struct nic_operations prism2_operations = {
749 .connect = dummy_connect,
751 .transmit = prism2_transmit,
755 /**************************************************************************
756 PROBE - Look for an adapter, this routine's visible to the outside
757 You should omit the last argument struct pci_device * for a non-PCI NIC
758 ***************************************************************************/
759 static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) {
763 hfa384x_InfFrame_t inf;
764 char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
769 /* Initialize card */
770 result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */
771 if ( result ) printf ( "Initialize command returned %#hx\n", result );
772 hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */
773 hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */
775 DBG ( "MAC address %s\n", eth_ntoa ( nic->node_addr ) );
777 /* Retrieve MAC address (and fill out nic->node_addr) */
778 hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
780 /* Prepare card for autojoin */
781 /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
782 tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */
783 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16);
784 if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result );
785 tmp16 = 0x000f; /* Set transmit rate(?) */
786 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16);
787 if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result );
788 tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */
789 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16);
790 if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result );
792 memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN);
793 for ( tmp16=0; tmp16<sizeof(hardcoded_ssid); tmp16++ ) { ssid[2+tmp16] = hardcoded_ssid[tmp16]; }
794 ssid[0] = sizeof(hardcoded_ssid) - 1; /* Ignore terminating zero */
795 result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */
796 if ( result ) printf ( "Set SSID command returned %#hx\n", result );
797 tmp16 = 1; /* Set port type to ESS port */
798 result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16);
799 if ( result ) printf ( "Set port type command returned %#hx\n", result );
801 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
802 if ( result ) printf ( "Enable command returned %#hx\n", result );
805 /* Increment info_count, abort if too many attempts.
806 * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
809 if ( info_count > MAX_JOIN_INFO_COUNT ) {
810 printf ( "Too many failed attempts - aborting\n" );
814 /* Wait for info frame to indicate link status */
815 if ( sizeof(hardcoded_ssid) == 1 ) {
816 /* Empty SSID => join to any SSID */
817 printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count );
819 printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count );
822 if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0;
824 infofid = hfa384x_getreg(hw, HFA384x_INFOFID);
825 /* Retrieve the length */
826 result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(uint16_t));
827 if ( result ) return 0; /* fail */
828 inf.framelen = hfa384x2host_16(inf.framelen);
829 /* Retrieve the rest */
830 result = hfa384x_copy_from_bap( hw, infofid, sizeof(uint16_t),
831 &(inf.infotype), inf.framelen * sizeof(uint16_t));
832 if ( result ) return 0; /* fail */
833 if ( inf.infotype != HFA384x_IT_LINKSTATUS ) {
834 /* Not a Link Status info frame: die */
835 printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf.infotype );
838 inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus);
839 if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) {
840 /* Link not connected - retry */
841 printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus );
843 } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
845 /* Retrieve BSSID and print Connected message */
846 result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
848 DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) );
849 DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) );
851 /* point to NIC specific routines */
852 nic->nic_op = &prism2_operations;