VirtualBox

source: vbox/trunk/src/VBox/Devices/PC/Etherboot-src/drivers/net/prism2.c@ 1300

Last change on this file since 1300 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 30.7 KB
Line 
1/**************************************************************************
2Etherboot - BOOTP/TFTP Bootstrap Program
3Prism2 NIC driver for Etherboot
4
5Written by Michael Brown of Fen Systems Ltd
6$Id: prism2.c 1 1970-01-01 00:00:00Z vboxsync $
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/* to get some global routines like printf */
17#include "etherboot.h"
18/* to get the interface to the body of the program */
19#include "nic.h"
20/* to get the PCI support functions, if this is a PCI NIC */
21#include "pci.h"
22
23/*
24 * Hard-coded SSID
25 * Leave blank in order to connect to any available SSID
26 */
27
28static 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#include "timer.h"
68#define __le16_to_cpu(x) (x)
69#define __le32_to_cpu(x) (x)
70#define __cpu_to_le16(x) (x)
71#define __cpu_to_le32(x) (x)
72
73/*
74 * PLX9052 PCI register offsets
75 * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
76 */
77
78#define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )
79#define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )
80#define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )
81#define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )
82#define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )
83
84#define PRISM2_PLX_ATTR_MEM_BASE ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )
85#define PRISM2_PLX_IO_BASE ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )
86
87#define PRISM2_PCI_MEM_BASE ( PCI_BASE_ADDRESS_0 )
88
89/*
90 * PCMCIA CIS types
91 * Taken from cistpl.h in pcmcia-cs
92 */
93
94#define CISTPL_VERS_1 ( 0x15 )
95#define CISTPL_END ( 0xff )
96
97#define CIS_STEP ( 2 )
98#define CISTPL_HEADER_LEN ( 2 * CIS_STEP )
99#define CISTPL_LEN_OFF ( 1 * CIS_STEP )
100#define CISTPL_VERS_1_STR_OFF ( 4 * CIS_STEP )
101
102/*
103 * Prism2 constants
104 * Taken from prism2sta.c in linux-wlan-ng
105 */
106
107#define COR_OFFSET ( 0x3e0 ) /* COR attribute offset of Prism2 PC card */
108#define COR_VALUE ( 0x41 ) /* Enable PC card with irq in level trigger (but interrupts disabled) */
109
110/* NIC specific static variables */
111
112/* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined.
113 * This is a dummy version that contains only the fields we are interested in.
114 */
115
116typedef struct hfa384x
117{
118 UINT32 iobase;
119 UINT32 membase;
120 UINT16 lastcmd;
121 UINT16 status; /* in host order */
122 UINT16 resp0; /* in host order */
123 UINT16 resp1; /* in host order */
124 UINT16 resp2; /* in host order */
125 UINT8 bssid[WLAN_BSSID_LEN];
126} hfa384x_t;
127
128/* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */
129static hfa384x_t hw_global = {
130 0, 0, 0, 0, 0, 0, 0, {0,0,0,0,0,0}
131};
132
133/*
134 * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
135 * Taken from p80211conv.h
136 */
137
138typedef struct wlan_llc
139{
140 UINT8 dsap __WLAN_ATTRIB_PACK__;
141 UINT8 ssap __WLAN_ATTRIB_PACK__;
142 UINT8 ctl __WLAN_ATTRIB_PACK__;
143} __WLAN_ATTRIB_PACK__ wlan_llc_t;
144
145static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
146
147#define WLAN_IEEE_OUI_LEN 3
148typedef struct wlan_snap
149{
150 UINT8 oui[WLAN_IEEE_OUI_LEN] __WLAN_ATTRIB_PACK__;
151 UINT16 type __WLAN_ATTRIB_PACK__;
152} __WLAN_ATTRIB_PACK__ wlan_snap_t;
153
154typedef struct wlan_80211hdr
155{
156 wlan_llc_t llc;
157 wlan_snap_t snap;
158} wlan_80211hdr_t;
159
160/*
161 * Function prototypes
162 */
163
164#if (WLAN_HOSTIF == WLAN_PLX)
165static int prism2_find_plx ( hfa384x_t *hw, struct pci_device *p );
166#elif (WLAN_HOSTIF == WLAN_PCI)
167static int prism2_find_pci ( hfa384x_t *hw, struct pci_device *p );
168#endif
169
170/*
171 * Hardware-level hfa384x functions
172 * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
173 * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions.
174 */
175
176/* Retrieve the value of one of the MAC registers. */
177static inline UINT16 hfa384x_getreg( hfa384x_t *hw, UINT reg )
178{
179#if (WLAN_HOSTIF == WLAN_PLX)
180 return inw ( hw->iobase + reg );
181#elif (WLAN_HOSTIF == WLAN_PCI)
182 return readw ( hw->membase + reg );
183#endif
184}
185
186/* Set the value of one of the MAC registers. */
187static inline void hfa384x_setreg( hfa384x_t *hw, UINT16 val, UINT reg )
188{
189#if (WLAN_HOSTIF == WLAN_PLX)
190 outw ( val, hw->iobase + reg );
191#elif (WLAN_HOSTIF == WLAN_PCI)
192 writew ( val, hw->membase + reg );
193#endif
194 return;
195}
196
197/*
198 * Noswap versions
199 * Etherboot is i386 only, so swap and noswap are the same...
200 */
201static inline UINT16 hfa384x_getreg_noswap( hfa384x_t *hw, UINT reg )
202{
203 return hfa384x_getreg ( hw, reg );
204}
205static inline void hfa384x_setreg_noswap( hfa384x_t *hw, UINT16 val, UINT reg )
206{
207 hfa384x_setreg ( hw, val, reg );
208}
209
210/*
211 * Low-level hfa384x functions
212 * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
213 */
214
215/*
216 * hfa384x_docmd_wait
217 *
218 * Waits for availability of the Command register, then
219 * issues the given command. Then polls the Evstat register
220 * waiting for command completion.
221 * Arguments:
222 * hw device structure
223 * cmd Command in host order
224 * parm0 Parameter0 in host order
225 * parm1 Parameter1 in host order
226 * parm2 Parameter2 in host order
227 * Returns:
228 * 0 success
229 * >0 command indicated error, Status and Resp0-2 are
230 * in hw structure.
231 */
232static int hfa384x_docmd_wait( hfa384x_t *hw, UINT16 cmd, UINT16 parm0, UINT16 parm1, UINT16 parm2)
233{
234 UINT16 reg = 0;
235 UINT16 counter = 0;
236
237 /* wait for the busy bit to clear */
238 counter = 0;
239 reg = hfa384x_getreg(hw, HFA384x_CMD);
240 while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
241 reg = hfa384x_getreg(hw, HFA384x_CMD);
242 counter++;
243 udelay(10);
244 }
245 if (HFA384x_CMD_ISBUSY(reg)) {
246 printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
247 return -ETIMEDOUT;
248 }
249
250 /* busy bit clear, write command */
251 hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
252 hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
253 hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
254 hw->lastcmd = cmd;
255 hfa384x_setreg(hw, cmd, HFA384x_CMD);
256
257 /* Now wait for completion */
258 counter = 0;
259 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
260 /* Initialization is the problem. It takes about
261 100ms. "normal" commands are typically is about
262 200-400 us (I've never seen less than 200). Longer
263 is better so that we're not hammering the bus. */
264 while ( !HFA384x_EVSTAT_ISCMD(reg) && (counter < 5000)) {
265 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
266 counter++;
267 udelay(200);
268 }
269 if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
270 printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
271 return -ETIMEDOUT;
272 }
273
274 /* Read status and response */
275 hw->status = hfa384x_getreg(hw, HFA384x_STATUS);
276 hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
277 hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
278 hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
279 hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
280 return HFA384x_STATUS_RESULT_GET(hw->status);
281}
282
283/*
284 * Prepare BAP for access. Assigns FID and RID, sets offset register
285 * and waits for BAP to become available.
286 *
287 * Arguments:
288 * hw device structure
289 * id FID or RID, destined for the select register (host order)
290 * offset An _even_ offset into the buffer for the given FID/RID.
291 * Returns:
292 * 0 success
293 */
294static int hfa384x_prepare_bap(hfa384x_t *hw, UINT16 id, UINT16 offset)
295{
296 int result = 0;
297 UINT16 reg;
298 UINT16 i;
299
300 /* Validate offset, buf, and len */
301 if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
302 result = -EINVAL;
303 } else {
304 /* Write fid/rid and offset */
305 hfa384x_setreg(hw, id, HFA384x_SELECT0);
306 udelay(10);
307 hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
308 /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
309 i = 0;
310 do {
311 reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
312 if ( i > 0 ) udelay(2);
313 i++;
314 } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
315 if ( i >= BAP_TIMEOUT ) {
316 /* failure */
317 result = reg;
318 } else if ( HFA384x_OFFSET_ISERR(reg) ){
319 /* failure */
320 result = reg;
321 }
322 }
323 return result;
324}
325
326/*
327 * Copy data from BAP to memory.
328 *
329 * Arguments:
330 * hw device structure
331 * id FID or RID, destined for the select register (host order)
332 * offset An _even_ offset into the buffer for the given FID/RID.
333 * buf ptr to array of bytes
334 * len length of data to transfer in bytes
335 * Returns:
336 * 0 success
337 */
338static int hfa384x_copy_from_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
339 void *buf, UINT len)
340{
341 int result = 0;
342 UINT8 *d = (UINT8*)buf;
343 UINT16 i;
344 UINT16 reg = 0;
345
346 /* Prepare BAP */
347 result = hfa384x_prepare_bap ( hw, id, offset );
348 if ( result == 0 ) {
349 /* Read even(len) buf contents from data reg */
350 for ( i = 0; i < (len & 0xfffe); i+=2 ) {
351 *(UINT16*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
352 }
353 /* If len odd, handle last byte */
354 if ( len % 2 ){
355 reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
356 d[len-1] = ((UINT8*)(&reg))[0];
357 }
358 }
359 if (result) {
360 printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
361 }
362 return result;
363}
364
365/*
366 * Copy data from memory to BAP.
367 *
368 * Arguments:
369 * hw device structure
370 * id FID or RID, destined for the select register (host order)
371 * offset An _even_ offset into the buffer for the given FID/RID.
372 * buf ptr to array of bytes
373 * len length of data to transfer in bytes
374 * Returns:
375 * 0 success
376 */
377static int hfa384x_copy_to_bap(hfa384x_t *hw, UINT16 id, UINT16 offset,
378 void *buf, UINT len)
379{
380 int result = 0;
381 UINT8 *d = (UINT8*)buf;
382 UINT16 i;
383 UINT16 savereg;
384
385 /* Prepare BAP */
386 result = hfa384x_prepare_bap ( hw, id, offset );
387 if ( result == 0 ) {
388 /* Write even(len) buf contents to data reg */
389 for ( i = 0; i < (len & 0xfffe); i+=2 ) {
390 hfa384x_setreg_noswap(hw, *(UINT16*)(&(d[i])), HFA384x_DATA0);
391 }
392 /* If len odd, handle last byte */
393 if ( len % 2 ){
394 savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
395 result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
396 if ( result == 0 ) {
397 ((UINT8*)(&savereg))[0] = d[len-1];
398 hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
399 }
400 }
401 }
402 if (result) {
403 printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
404 }
405 return result;
406}
407
408/*
409 * Request a given record to be copied to/from the record buffer.
410 *
411 * Arguments:
412 * hw device structure
413 * write [0|1] copy the record buffer to the given
414 * configuration record. (host order)
415 * rid RID of the record to read/write. (host order)
416 *
417 * Returns:
418 * 0 success
419 */
420static inline int hfa384x_cmd_access(hfa384x_t *hw, UINT16 write, UINT16 rid)
421{
422 return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
423}
424
425/*
426 * Performs the sequence necessary to read a config/info item.
427 *
428 * Arguments:
429 * hw device structure
430 * rid config/info record id (host order)
431 * buf host side record buffer. Upon return it will
432 * contain the body portion of the record (minus the
433 * RID and len).
434 * len buffer length (in bytes, should match record length)
435 *
436 * Returns:
437 * 0 success
438 */
439static int hfa384x_drvr_getconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
440{
441 int result = 0;
442 hfa384x_rec_t rec;
443
444 /* Request read of RID */
445 result = hfa384x_cmd_access( hw, 0, rid);
446 if ( result ) {
447 printf("Call to hfa384x_cmd_access failed\n");
448 return -1;
449 }
450 /* Copy out record length */
451 result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
452 if ( result ) {
453 return -1;
454 }
455 /* Validate the record length */
456 if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) { /* note body len calculation in bytes */
457 printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
458 return -1;
459 }
460 /* Copy out record data */
461 result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
462 return result;
463}
464
465/*
466 * Performs the sequence necessary to read a 16/32 bit config/info item
467 * and convert it to host order.
468 *
469 * Arguments:
470 * hw device structure
471 * rid config/info record id (in host order)
472 * val ptr to 16/32 bit buffer to receive value (in host order)
473 *
474 * Returns:
475 * 0 success
476 */
477#if 0 /* Not actually used anywhere */
478static int hfa384x_drvr_getconfig16(hfa384x_t *hw, UINT16 rid, void *val)
479{
480 int result = 0;
481 result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT16));
482 if ( result == 0 ) {
483 *((UINT16*)val) = hfa384x2host_16(*((UINT16*)val));
484 }
485 return result;
486}
487#endif
488#if 0 /* Not actually used anywhere */
489static int hfa384x_drvr_getconfig32(hfa384x_t *hw, UINT16 rid, void *val)
490{
491 int result = 0;
492 result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(UINT32));
493 if ( result == 0 ) {
494 *((UINT32*)val) = hfa384x2host_32(*((UINT32*)val));
495 }
496 return result;
497}
498#endif
499
500/*
501 * Performs the sequence necessary to write a config/info item.
502 *
503 * Arguments:
504 * hw device structure
505 * rid config/info record id (in host order)
506 * buf host side record buffer
507 * len buffer length (in bytes)
508 *
509 * Returns:
510 * 0 success
511 */
512static int hfa384x_drvr_setconfig(hfa384x_t *hw, UINT16 rid, void *buf, UINT16 len)
513{
514 int result = 0;
515 hfa384x_rec_t rec;
516
517 rec.rid = host2hfa384x_16(rid);
518 rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
519 /* write the record header */
520 result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
521 if ( result ) {
522 printf("Failure writing record header\n");
523 return -1;
524 }
525 /* write the record data (if there is any) */
526 if ( len > 0 ) {
527 result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
528 if ( result ) {
529 printf("Failure writing record data\n");
530 return -1;
531 }
532 }
533 /* Trigger setting of record */
534 result = hfa384x_cmd_access( hw, 1, rid);
535 return result;
536}
537
538/*
539 * Performs the sequence necessary to write a 16/32 bit config/info item.
540 *
541 * Arguments:
542 * hw device structure
543 * rid config/info record id (in host order)
544 * val 16/32 bit value to store (in host order)
545 *
546 * Returns:
547 * 0 success
548 */
549static int hfa384x_drvr_setconfig16(hfa384x_t *hw, UINT16 rid, UINT16 *val)
550{
551 UINT16 value;
552 value = host2hfa384x_16(*val);
553 return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT16));
554}
555#if 0 /* Not actually used anywhere */
556static int hfa384x_drvr_setconfig32(hfa384x_t *hw, UINT16 rid, UINT32 *val)
557{
558 UINT32 value;
559 value = host2hfa384x_32(*val);
560 return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(UINT32));
561}
562#endif
563
564/*
565 * Wait for an event, with specified checking interval and timeout.
566 * Automatically acknolwedges events.
567 *
568 * Arguments:
569 * hw device structure
570 * event_mask EVSTAT register mask of events to wait for
571 * event_ack EVACK register set of events to be acknowledged if they happen (can be
572 * used to acknowledge "ignorable" events in addition to the "main" event)
573 * wait Time (in us) to wait between each poll of the register
574 * timeout Maximum number of polls before timing out
575 * descr Descriptive text string of what is being waited for
576 * (will be printed out if a timeout happens)
577 *
578 * Returns:
579 * value of EVSTAT register, or 0 on failure
580 */
581static int hfa384x_wait_for_event(hfa384x_t *hw, UINT16 event_mask, UINT16 event_ack, int wait, int timeout, const char *descr)
582{
583 UINT16 reg;
584 int count = 0;
585
586 do {
587 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
588 if ( count > 0 ) udelay(wait);
589 count++;
590 } while ( !(reg & event_mask) && count < timeout);
591 if ( count >= timeout ) {
592 printf("hfa384x: Timed out waiting for %s\n", descr);
593 return 0; /* Return failure */
594 }
595 /* Acknowledge all events that we were waiting on */
596 hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
597 return reg;
598}
599
600/**************************************************************************
601POLL - Wait for a frame
602***************************************************************************/
603static int prism2_poll(struct nic *nic, int retrieve)
604{
605 UINT16 reg;
606 UINT16 rxfid;
607 UINT16 result;
608 hfa384x_rx_frame_t rxdesc;
609 hfa384x_t *hw = &hw_global;
610
611 /* Check for received packet */
612 reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
613 if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
614 /* No packet received - return 0 */
615 return 0;
616 }
617
618 if ( ! retrieve ) return 1;
619
620 /* Acknowledge RX event */
621 hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
622 /* Get RX FID */
623 rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
624 /* Get the descriptor (including headers) */
625 result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc));
626 if ( result ) {
627 return 0; /* fail */
628 }
629 /* Byte order convert once up front. */
630 rxdesc.status = hfa384x2host_16(rxdesc.status);
631 rxdesc.time = hfa384x2host_32(rxdesc.time);
632 rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
633
634 /* Fill in nic->packetlen */
635 nic->packetlen = rxdesc.data_len;
636 if ( nic->packetlen > 0 ) {
637 /* Fill in nic->packet */
638 /*
639 * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
640 * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
641 * header), so we use a quick hack to achieve this.
642 */
643 result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
644 nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
645 if ( result ) {
646 return 0; /* fail */
647 }
648 }
649 return 1; /* Packet successfully received */
650}
651
652/**************************************************************************
653TRANSMIT - Transmit a frame
654***************************************************************************/
655static void prism2_transmit(
656 struct nic *nic,
657 const char *d, /* Destination */
658 unsigned int t, /* Type */
659 unsigned int s, /* size */
660 const char *p) /* Packet */
661{
662 hfa384x_t *hw = &hw_global;
663 hfa384x_tx_frame_t txdesc;
664 wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
665 UINT16 fid;
666 UINT16 status;
667 int result;
668
669 // Request FID allocation
670 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
671 if (result != 0) {
672 printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
673 return;
674 }
675 if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
676 fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
677
678 /* Build Tx frame structure */
679 memset(&txdesc, 0, sizeof(txdesc));
680 txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
681 HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
682 txdesc.frame_control = host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
683 WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
684 WLAN_SET_FC_TODS(1) );
685 memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
686 memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
687 memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
688 txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
689 /* Set up SNAP header */
690 /* Let OUI default to RFC1042 (0x000000) */
691 p80211hdr.snap.type = htons(t);
692
693 /* Copy txdesc, p80211hdr and payload parts to FID */
694 result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
695 if ( result ) return; /* fail */
696 result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
697 if ( result ) return; /* fail */
698 result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (UINT8*)p, s );
699 if ( result ) return; /* fail */
700
701 /* Issue Tx command */
702 result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
703 if ( result != 0 ) {
704 printf("hfa384x: Transmit failed with result %#hx.\n", result);
705 return;
706 }
707
708 /* Wait for transmit completion (or exception) */
709 result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
710 200, 500, "Tx to complete\n" );
711 if ( !result ) return; /* timeout failure */
712 if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
713 fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
714 printf ( "Tx exception occurred with fid %#hx\n", fid );
715 result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
716 if ( result ) return; /* fail */
717 printf("hfa384x: Tx error occurred (status %#hx):\n", status);
718 if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
719 if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
720 if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
721 if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
722 if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
723 return; /* fail */
724 }
725}
726
727/**************************************************************************
728DISABLE - Turn off ethernet interface
729***************************************************************************/
730static void prism2_disable(struct dev *dev __unused)
731{
732 /* put the card in its initial state */
733}
734
735/**************************************************************************
736IRQ - Enable, Disable, or Force interrupts
737***************************************************************************/
738static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
739{
740 switch ( action ) {
741 case DISABLE :
742 break;
743 case ENABLE :
744 break;
745 case FORCE :
746 break;
747 }
748}
749
750/**************************************************************************
751PROBE - Look for an adapter, this routine's visible to the outside
752You should omit the last argument struct pci_device * for a non-PCI NIC
753***************************************************************************/
754#if (WLAN_HOSTIF == WLAN_PLX)
755static int prism2_plx_probe(struct dev *dev, struct pci_device *p)
756#elif (WLAN_HOSTIF == WLAN_PCI)
757static int prism2_pci_probe(struct dev *dev, struct pci_device *p)
758#endif
759{
760 struct nic *nic = (struct nic *)dev;
761 hfa384x_t *hw = &hw_global;
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 /* Find and intialise PLX Prism2 card */
770#if (WLAN_HOSTIF == WLAN_PLX)
771 if ( ! prism2_find_plx ( hw, p ) ) return 0;
772 nic->ioaddr = hw->iobase;
773#elif (WLAN_HOSTIF == WLAN_PCI)
774 if ( ! prism2_find_pci ( hw, p ) ) return 0;
775 nic->ioaddr = hw->membase;
776#endif
777
778 nic->irqno = 0;
779
780 /* Initialize card */
781 result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */
782 if ( result ) printf ( "Initialize command returned %#hx\n", result );
783 hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */
784 hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */
785
786 /* Retrieve MAC address (and fill out nic->node_addr) */
787 hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
788 printf ( "MAC address %!\n", nic->node_addr );
789
790 /* Prepare card for autojoin */
791 /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
792 tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */
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));
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),
841 &(inf.infotype), inf.framelen * sizeof(UINT16));
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 printf ( "Link connected (BSSID %! - MAC address %!)\n", hw->bssid, nic->node_addr );
858
859 /* point to NIC specific routines */
860 dev->disable = prism2_disable;
861 nic->poll = prism2_poll;
862 nic->transmit = prism2_transmit;
863 nic->irq = prism2_irq;
864 return 1;
865}
866
867#if (WLAN_HOSTIF == WLAN_PLX)
868/*
869 * Find PLX card. Prints out information strings from PCMCIA CIS as visual
870 * confirmation of presence of card.
871 *
872 * Arguments:
873 * hw device structure to be filled in
874 * p PCI device structure
875 *
876 * Returns:
877 * 1 Success
878 */
879static int prism2_find_plx ( hfa384x_t *hw, struct pci_device *p )
880{
881 int found = 0;
882 uint32_t plx_lcr = 0; /* PLX9052 Local Configuration Register Base (I/O) */
883 uint32_t attr_mem = 0; /* Prism2 Attribute Memory Base */
884 uint32_t iobase = 0; /* Prism2 I/O Base */
885 unsigned char *cis_tpl = NULL;
886 unsigned char *cis_string;
887
888 /* Obtain all memory and IO base addresses */
889 pcibios_read_config_dword( p->bus, p->devfn, PLX_LOCAL_CONFIG_REGISTER_BASE, &plx_lcr);
890 plx_lcr &= PCI_BASE_ADDRESS_IO_MASK;
891 pcibios_read_config_dword( p->bus, p->devfn, PRISM2_PLX_ATTR_MEM_BASE, &attr_mem);
892 pcibios_read_config_dword( p->bus, p->devfn, PRISM2_PLX_IO_BASE, &iobase);
893 iobase &= PCI_BASE_ADDRESS_IO_MASK;
894
895 /* Fill out hw structure */
896 hw->membase = attr_mem;
897 hw->iobase = iobase;
898 printf ( "PLX9052 has local config registers at %#hx\n", plx_lcr );
899 printf ( "Prism2 has attribute memory at %#x and I/O base at %#hx\n", attr_mem, iobase );
900
901 /* Search for CIS strings */
902 printf ( "Searching for PCMCIA card...\n" );
903 cis_tpl = bus_to_virt(attr_mem);
904 while ( *cis_tpl != CISTPL_END ) {
905 if ( *cis_tpl == CISTPL_VERS_1 ) {
906 /* CISTPL_VERS_1 contains some nice text strings */
907 printf ( "...found " );
908 found = 1;
909 cis_string = cis_tpl + CISTPL_VERS_1_STR_OFF;
910 while ( ! ( ( *cis_string == 0 ) && ( *(cis_string+CIS_STEP) == 0 ) ) ) {
911 printf ( "%c", *cis_string == 0 ? ' ' : *cis_string );
912 cis_string += CIS_STEP;
913 }
914 printf ( "\n" );
915 }
916 /* printf ( "CIS tuple type %#hhx, length %#hhx\n", *cis_tpl, *(cis_tpl+CISTPL_LEN_OFF) ); */
917 cis_tpl += CISTPL_HEADER_LEN + CIS_STEP * ( *(cis_tpl+CISTPL_LEN_OFF) );
918 }
919 if ( found == 0 ) {
920 printf ( "...nothing found\n" );
921 }
922 ((unsigned char *)bus_to_virt(attr_mem))[COR_OFFSET] = COR_VALUE; /* Write COR to enable PC card */
923 return found;
924}
925#endif /* WLAN_PLX */
926
927#if (WLAN_HOSTIF == WLAN_PCI)
928/*
929 * Find PCI card.
930 *
931 * Arguments:
932 * hw device structure to be filled in
933 * p PCI device structure
934 *
935 * Returns:
936 * 1 Success
937 */
938static int prism2_find_pci ( hfa384x_t *hw, struct pci_device *p )
939{
940 uint32_t membase = 0; /* Prism2.5 Memory Base */
941 pcibios_read_config_dword( p->bus, p->devfn, PRISM2_PCI_MEM_BASE, &membase);
942 membase &= PCI_BASE_ADDRESS_MEM_MASK;
943 hw->membase = (uint32_t) phys_to_virt(membase);
944 printf ( "Prism2.5 has registers at %#x\n", hw->membase );
945 return 1;
946}
947#endif /* WLAN_PCI */
948
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette