|
|
1.1 root 1: /**************************************************************************
2: Etherboot - BOOTP/TFTP Bootstrap Program
3: Prism2 NIC driver for Etherboot
4:
5: Written by Michael Brown of Fen Systems Ltd
6: $Id$
7: ***************************************************************************/
8:
9: /*
10: * This program is free software; you can redistribute it and/or
11: * modify it under the terms of the GNU General Public License as
12: * published by the Free Software Foundation; either version 2, or (at
13: * your option) any later version.
14: */
15:
16: FILE_LICENCE ( GPL2_OR_LATER );
17:
18: #include <etherboot.h>
19: #include <nic.h>
20: #include <ipxe/pci.h>
21: #include <ipxe/ethernet.h>
22:
23: /*
24: * Hard-coded SSID
25: * Leave blank in order to connect to any available SSID
26: */
27:
28: static const char hardcoded_ssid[] = "";
29:
30: /*
31: * Maximum number of info packets to wait for on a join attempt.
32: * Some APs (including the Linksys WAP11) will send a "you are disconnected" packet
33: * before sending the "you are connected" packet, if the card has previously been
34: * attached to the AP.
35: *
36: * 2 is probably a sensible value, but YMMV.
37: */
38:
39: #define MAX_JOIN_INFO_COUNT 2
40:
41: /*
42: * Type of Prism2 interface to support
43: * If not already defined, select PLX
44: */
45: #ifndef WLAN_HOSTIF
46: #define WLAN_HOSTIF WLAN_PLX
47: #endif
48:
49: /*
50: * Include wlan_compat, p80211 and hfa384x header files from Linux Prism2 driver
51: * We need to hack some defines in order to avoid compiling kernel-specific routines
52: */
53:
54: #define __LINUX_WLAN__
55: #undef __KERNEL__
56: #define __I386__
57: #include "wlan_compat.h"
58: #include "p80211hdr.h"
59: #include "hfa384x.h"
60: #define BAP_TIMEOUT ( 5000 )
61:
62: /*
63: * A few hacks to make the coding environment more Linux-like. This makes it somewhat
64: * quicker to convert code from the Linux Prism2 driver.
65: */
66: #include <errno.h>
67: #define __le16_to_cpu(x) (x)
68: #define __le32_to_cpu(x) (x)
69: #define __cpu_to_le16(x) (x)
70: #define __cpu_to_le32(x) (x)
71:
72: #define hfa384x2host_16(n) (__le16_to_cpu((UINT16)(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)))
76:
77: /*
78: * PLX9052 PCI register offsets
79: * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
80: */
81:
82: #define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )
83: #define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )
84: #define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )
85: #define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )
86: #define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )
87:
88: #define PRISM2_PLX_ATTR_MEM_BASE ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )
89: #define PRISM2_PLX_IO_BASE ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )
90:
91: #define PRISM2_PCI_MEM_BASE ( PCI_BASE_ADDRESS_0 )
92:
93: /*
94: * PCMCIA CIS types
95: * Taken from cistpl.h in pcmcia-cs
96: */
97:
98: #define CISTPL_VERS_1 ( 0x15 )
99: #define CISTPL_END ( 0xff )
100:
101: #define CIS_STEP ( 2 )
102: #define CISTPL_HEADER_LEN ( 2 * CIS_STEP )
103: #define CISTPL_LEN_OFF ( 1 * CIS_STEP )
104: #define CISTPL_VERS_1_STR_OFF ( 4 * CIS_STEP )
105:
106: /*
107: * Prism2 constants
108: * Taken from prism2sta.c in linux-wlan-ng
109: */
110:
111: #define COR_OFFSET ( 0x3e0 ) /* COR attribute offset of Prism2 PC card */
112: #define COR_VALUE ( 0x41 ) /* Enable PC card with irq in level trigger (but interrupts disabled) */
113:
114: /* NIC specific static variables */
115:
116: /* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined.
117: * This is a dummy version that contains only the fields we are interested in.
118: */
119:
120: typedef struct hfa384x
121: {
122: UINT32 iobase;
123: void *membase;
124: UINT16 lastcmd;
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];
130: } hfa384x_t;
131:
132: /* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */
133: static hfa384x_t hw_global = {
134: 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}
135: };
136:
137: /*
138: * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
139: * Taken from p80211conv.h
140: */
141:
142: typedef struct wlan_llc
143: {
144: UINT8 dsap;
145: UINT8 ssap;
146: UINT8 ctl;
147: } wlan_llc_t;
148:
149: static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
150:
151: #define WLAN_IEEE_OUI_LEN 3
152: typedef struct wlan_snap
153: {
154: UINT8 oui[WLAN_IEEE_OUI_LEN];
155: UINT16 type;
156: } wlan_snap_t;
157:
158: typedef struct wlan_80211hdr
159: {
160: wlan_llc_t llc;
161: wlan_snap_t snap;
162: } wlan_80211hdr_t;
163:
164: /*
165: * Function prototypes
166: */
167:
168: /*
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.
172: */
173:
174: /* Retrieve the value of one of the MAC registers. */
175: static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg )
176: {
177: #if (WLAN_HOSTIF == WLAN_PLX)
178: return inw ( hw->iobase + reg );
179: #elif (WLAN_HOSTIF == WLAN_PCI)
180: return readw ( hw->membase + reg );
181: #endif
182: }
183:
184: /* Set the value of one of the MAC registers. */
185: static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg )
186: {
187: #if (WLAN_HOSTIF == WLAN_PLX)
188: outw ( val, hw->iobase + reg );
189: #elif (WLAN_HOSTIF == WLAN_PCI)
190: writew ( val, hw->membase + reg );
191: #endif
192: return;
193: }
194:
195: /*
196: * Noswap versions
197: * Etherboot is i386 only, so swap and noswap are the same...
198: */
199: static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg )
200: {
201: return hfa384x_getreg ( hw, reg );
202: }
203: static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg )
204: {
205: hfa384x_setreg ( hw, val, reg );
206: }
207:
208: /*
209: * Low-level hfa384x functions
210: * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
211: */
212:
213: /*
214: * hfa384x_docmd_wait
215: *
216: * Waits for availability of the Command register, then
217: * issues the given command. Then polls the Evstat register
218: * waiting for command completion.
219: * Arguments:
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
225: * Returns:
226: * 0 success
227: * >0 command indicated error, Status and Resp0-2 are
228: * in hw structure.
229: */
230: static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2)
231: {
232: UINT16 reg = 0;
233: UINT16 counter = 0;
234:
235: /* wait for the busy bit to clear */
236: counter = 0;
237: reg = hfa384x_getreg(hw, HFA384x_CMD);
238: while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
239: reg = hfa384x_getreg(hw, HFA384x_CMD);
240: counter++;
241: udelay(10);
242: }
243: if (HFA384x_CMD_ISBUSY(reg)) {
244: printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
245: return -ETIMEDOUT;
246: }
247:
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);
252: hw->lastcmd = cmd;
253: hfa384x_setreg(hw, cmd, HFA384x_CMD);
254:
255: /* Now wait for completion */
256: counter = 0;
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);
264: counter++;
265: udelay(200);
266: }
267: if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
268: printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
269: return -ETIMEDOUT;
270: }
271:
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);
279: }
280:
281: /*
282: * Prepare BAP for access. Assigns FID and RID, sets offset register
283: * and waits for BAP to become available.
284: *
285: * Arguments:
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.
289: * Returns:
290: * 0 success
291: */
292: static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset)
293: {
294: int result = 0;
295: UINT16 reg;
296: UINT16 i;
297:
298: /* Validate offset, buf, and len */
299: if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
300: result = -EINVAL;
301: } else {
302: /* Write fid/rid and offset */
303: hfa384x_setreg(hw, id, HFA384x_SELECT0);
304: udelay(10);
305: hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
306: /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
307: i = 0;
308: do {
309: reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
310: if ( i > 0 ) udelay(2);
311: i++;
312: } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
313: if ( i >= BAP_TIMEOUT ) {
314: /* failure */
315: result = reg;
316: } else if ( HFA384x_OFFSET_ISERR(reg) ){
317: /* failure */
318: result = reg;
319: }
320: }
321: return result;
322: }
323:
324: /*
325: * Copy data from BAP to memory.
326: *
327: * Arguments:
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
333: * Returns:
334: * 0 success
335: */
336: static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
337: void *buf, UINT len)
338: {
339: int result = 0;
340: UINT8 *d = (UINT8*)buf;
341: UINT16 i;
342: UINT16 reg = 0;
343:
344: /* Prepare BAP */
345: result = hfa384x_prepare_bap ( hw, id, offset );
346: if ( result == 0 ) {
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);
350: }
351: /* If len odd, handle last byte */
352: if ( len % 2 ){
353: reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
354: d[len-1] = ((UINT8*)(®))[0];
355: }
356: }
357: if (result) {
358: printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
359: }
360: return result;
361: }
362:
363: /*
364: * Copy data from memory to BAP.
365: *
366: * Arguments:
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
372: * Returns:
373: * 0 success
374: */
375: static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
376: void *buf, UINT len)
377: {
378: int result = 0;
379: UINT8 *d = (UINT8*)buf;
380: UINT16 i;
381: UINT16 savereg;
382:
383: /* Prepare BAP */
384: result = hfa384x_prepare_bap ( hw, id, offset );
385: if ( result == 0 ) {
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);
389: }
390: /* If len odd, handle last byte */
391: if ( len % 2 ){
392: savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
393: result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
394: if ( result == 0 ) {
395: ((UINT8*)(&savereg))[0] = d[len-1];
396: hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
397: }
398: }
399: }
400: if (result) {
401: printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
402: }
403: return result;
404: }
405:
406: /*
407: * Request a given record to be copied to/from the record buffer.
408: *
409: * Arguments:
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)
414: *
415: * Returns:
416: * 0 success
417: */
418: static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid)
419: {
420: return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
421: }
422:
423: /*
424: * Performs the sequence necessary to read a config/info item.
425: *
426: * Arguments:
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
431: * RID and len).
432: * len buffer length (in bytes, should match record length)
433: *
434: * Returns:
435: * 0 success
436: */
437: static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
438: {
439: int result = 0;
440: hfa384x_rec_t rec;
441:
442: /* Request read of RID */
443: result = hfa384x_cmd_access( hw, 0, rid);
444: if ( result ) {
445: printf("Call to hfa384x_cmd_access failed\n");
446: return -1;
447: }
448: /* Copy out record length */
449: result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
450: if ( result ) {
451: return -1;
452: }
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);
456: return -1;
457: }
458: /* Copy out record data */
459: result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
460: return result;
461: }
462:
463: /*
464: * Performs the sequence necessary to read a 16/32 bit config/info item
465: * and convert it to host order.
466: *
467: * Arguments:
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)
471: *
472: * Returns:
473: * 0 success
474: */
475: #if 0 /* Not actually used anywhere */
476: static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
477: {
478: int result = 0;
479: result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
480: if ( result == 0 ) {
481: *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
482: }
483: return result;
484: }
485: #endif
486: #if 0 /* Not actually used anywhere */
487: static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
488: {
489: int result = 0;
490: result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
491: if ( result == 0 ) {
492: *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
493: }
494: return result;
495: }
496: #endif
497:
498: /*
499: * Performs the sequence necessary to write a config/info item.
500: *
501: * Arguments:
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)
506: *
507: * Returns:
508: * 0 success
509: */
510: static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
511: {
512: int result = 0;
513: hfa384x_rec_t rec;
514:
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));
519: if ( result ) {
520: printf("Failure writing record header\n");
521: return -1;
522: }
523: /* write the record data (if there is any) */
524: if ( len > 0 ) {
525: result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
526: if ( result ) {
527: printf("Failure writing record data\n");
528: return -1;
529: }
530: }
531: /* Trigger setting of record */
532: result = hfa384x_cmd_access( hw, 1, rid);
533: return result;
534: }
535:
536: /*
537: * Performs the sequence necessary to write a 16/32 bit config/info item.
538: *
539: * Arguments:
540: * hw device structure
541: * rid config/info record id (in host order)
542: * val 16/32 bit value to store (in host order)
543: *
544: * Returns:
545: * 0 success
546: */
547: static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val)
548: {
549: UINT16 value;
550: value = host2hfa384x_16(*val);
551: return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));
552: }
553: #if 0 /* Not actually used anywhere */
554: static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val)
555: {
556: UINT32 value;
557: value = host2hfa384x_32(*val);
558: return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32));
559: }
560: #endif
561:
562: /*
563: * Wait for an event, with specified checking interval and timeout.
564: * Automatically acknolwedges events.
565: *
566: * Arguments:
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)
575: *
576: * Returns:
577: * value of EVSTAT register, or 0 on failure
578: */
579: static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr)
580: {
581: UINT16 reg;
582: int count = 0;
583:
584: do {
585: reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
586: if ( count > 0 ) udelay(wait);
587: count++;
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 */
592: }
593: /* Acknowledge all events that we were waiting on */
594: hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
595: return reg;
596: }
597:
598: /**************************************************************************
599: POLL - Wait for a frame
600: ***************************************************************************/
601: static int prism2_poll(struct nic *nic, int retrieve)
602: {
603: UINT16 reg;
604: UINT16 rxfid;
605: UINT16 result;
606: hfa384x_rx_frame_t rxdesc;
607: hfa384x_t *hw = &hw_global;
608:
609: /* Check for received packet */
610: reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
611: if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
612: /* No packet received - return 0 */
613: return 0;
614: }
615:
616: if ( ! retrieve ) return 1;
617:
618: /* Acknowledge RX event */
619: hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
620: /* Get RX FID */
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));
624: if ( result ) {
625: return 0; /* fail */
626: }
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);
631:
632: /* Fill in nic->packetlen */
633: nic->packetlen = rxdesc.data_len;
634: if ( nic->packetlen > 0 ) {
635: /* Fill in nic->packet */
636: /*
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.
640: */
641: result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
642: nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
643: if ( result ) {
644: return 0; /* fail */
645: }
646: }
647: return 1; /* Packet successfully received */
648: }
649:
650: /**************************************************************************
651: TRANSMIT - Transmit a frame
652: ***************************************************************************/
653: static void prism2_transmit(
654: struct nic *nic,
655: const char *d, /* Destination */
656: unsigned int t, /* Type */
657: unsigned int s, /* size */
658: const char *p) /* Packet */
659: {
660: hfa384x_t *hw = &hw_global;
661: hfa384x_tx_frame_t txdesc;
662: wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
663: UINT16 fid;
664: UINT16 status;
665: int result;
666:
667: // Request FID allocation
668: result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
669: if (result != 0) {
670: printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
671: return;
672: }
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);
675:
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);
690:
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 */
698:
699: /* Issue Tx command */
700: result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
701: if ( result != 0 ) {
702: printf("hfa384x: Transmit failed with result %#hx.\n", result);
703: return;
704: }
705:
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"); }
721: return; /* fail */
722: }
723: }
724:
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 */
730: }
731:
732: /**************************************************************************
733: IRQ - Enable, Disable, or Force interrupts
734: ***************************************************************************/
735: static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
736: {
737: switch ( action ) {
738: case DISABLE :
739: break;
740: case ENABLE :
741: break;
742: case FORCE :
743: break;
744: }
745: }
746:
747: /**************************************************************************
748: Operations table
749: ***************************************************************************/
750: static struct nic_operations prism2_operations = {
751: .connect = dummy_connect,
752: .poll = prism2_poll,
753: .transmit = prism2_transmit,
754: .irq = prism2_irq,
755: };
756:
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 ) {
762: int result;
763: UINT16 tmp16 = 0;
764: UINT16 infofid;
765: hfa384x_InfFrame_t inf;
766: char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
767: int info_count = 0;
768:
769: nic->irqno = 0;
770:
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 */
776:
777: DBG ( "MAC address %s\n", eth_ntoa ( nic->node_addr ) );
778:
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 );
781:
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 );
793: /* Set SSID */
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 );
802: /* Enable card */
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 );
805:
806: do {
807: /* Increment info_count, abort if too many attempts.
808: * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
809: */
810: info_count++;
811: if ( info_count > MAX_JOIN_INFO_COUNT ) {
812: printf ( "Too many failed attempts - aborting\n" );
813: return 0;
814: }
815:
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 );
820: } else {
821: printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count );
822: }
823:
824: if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0;
825: printf("done\n");
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 );
838: return 0;
839: }
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 );
844: }
845: } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
846:
847: /* Retrieve BSSID and print Connected message */
848: result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
849:
850: DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) );
851: DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) );
852:
853: /* point to NIC specific routines */
854: nic->nic_op = &prism2_operations;
855: return 1;
856: }
857:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.