~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/drivers/net/prism2.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**************************************************************************
 
2
Etherboot -  BOOTP/TFTP Bootstrap Program
 
3
Prism2 NIC driver for Etherboot
 
4
 
 
5
Written by Michael Brown of Fen Systems Ltd
 
6
$Id$
 
7
***************************************************************************/
 
8
 
 
9
/*
 
10
 * This program is free software; you can redistribute it and/or
 
11
 * modify it under the terms of the GNU General Public License as
 
12
 * published by the Free Software Foundation; either version 2 of the
 
13
 * License, or (at your option) any later version.
 
14
 *
 
15
 * This program is distributed in the hope that it will be useful, but
 
16
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
18
 * General Public License for more details.
 
19
 *
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
23
 * 02110-1301, USA.
 
24
 */
 
25
 
 
26
FILE_LICENCE ( GPL2_OR_LATER );
 
27
 
 
28
#include <etherboot.h>
 
29
#include <nic.h>
 
30
#include <ipxe/pci.h>
 
31
#include <ipxe/ethernet.h>
 
32
 
 
33
/*
 
34
 * Hard-coded SSID
 
35
 * Leave blank in order to connect to any available SSID
 
36
 */
 
37
 
 
38
static const char hardcoded_ssid[] = "";
 
39
 
 
40
/*
 
41
 * Maximum number of info packets to wait for on a join attempt.
 
42
 * Some APs (including the Linksys WAP11) will send a "you are disconnected" packet
 
43
 * before sending the "you are connected" packet, if the card has previously been
 
44
 * attached to the AP.
 
45
 *
 
46
 * 2 is probably a sensible value, but YMMV.
 
47
 */
 
48
 
 
49
#define MAX_JOIN_INFO_COUNT 2
 
50
 
 
51
/*
 
52
 * Type of Prism2 interface to support
 
53
 * If not already defined, select PLX
 
54
 */
 
55
#ifndef WLAN_HOSTIF
 
56
#define WLAN_HOSTIF WLAN_PLX
 
57
#endif
 
58
 
 
59
/*
 
60
 * Include wlan_compat, p80211 and hfa384x header files from Linux Prism2 driver
 
61
 * We need to hack some defines in order to avoid compiling kernel-specific routines
 
62
 */
 
63
 
 
64
#define __LINUX_WLAN__
 
65
#undef __KERNEL__
 
66
#define __I386__
 
67
#include "wlan_compat.h"
 
68
#include "p80211hdr.h"
 
69
#include "hfa384x.h"
 
70
#define BAP_TIMEOUT ( 5000 )
 
71
 
 
72
/*
 
73
 * A few hacks to make the coding environment more Linux-like.  This makes it somewhat
 
74
 * quicker to convert code from the Linux Prism2 driver.
 
75
 */
 
76
#include <errno.h>
 
77
#define __le16_to_cpu(x) (x)
 
78
#define __le32_to_cpu(x) (x)
 
79
#define __cpu_to_le16(x) (x)
 
80
#define __cpu_to_le32(x) (x)
 
81
 
 
82
#define hfa384x2host_16(n)      (__le16_to_cpu((uint16_t)(n)))
 
83
#define hfa384x2host_32(n)      (__le32_to_cpu((uint32_t)(n)))
 
84
#define host2hfa384x_16(n)      (__cpu_to_le16((uint16_t)(n)))
 
85
#define host2hfa384x_32(n)      (__cpu_to_le32((uint32_t)(n)))
 
86
 
 
87
/*
 
88
 * PLX9052 PCI register offsets
 
89
 * Taken from PLX9052 datasheet available from http://www.plxtech.com/download/9052/databook/9052db-20.pdf
 
90
 */
 
91
 
 
92
#define PLX_LOCAL_CONFIG_REGISTER_BASE ( PCI_BASE_ADDRESS_1 )
 
93
#define PLX_LOCAL_ADDRESS_SPACE_0_BASE ( PCI_BASE_ADDRESS_2 )
 
94
#define PLX_LOCAL_ADDRESS_SPACE_1_BASE ( PCI_BASE_ADDRESS_3 )
 
95
#define PLX_LOCAL_ADDRESS_SPACE_2_BASE ( PCI_BASE_ADDRESS_4 )
 
96
#define PLX_LOCAL_ADDRESS_SPACE_3_BASE ( PCI_BASE_ADDRESS_5 )
 
97
 
 
98
#define PRISM2_PLX_ATTR_MEM_BASE       ( PLX_LOCAL_ADDRESS_SPACE_0_BASE )
 
99
#define PRISM2_PLX_IO_BASE             ( PLX_LOCAL_ADDRESS_SPACE_1_BASE )
 
100
 
 
101
#define PRISM2_PCI_MEM_BASE            ( PCI_BASE_ADDRESS_0 )
 
102
 
 
103
/*
 
104
 * PCMCIA CIS types
 
105
 * Taken from cistpl.h in pcmcia-cs
 
106
 */
 
107
 
 
108
#define CISTPL_VERS_1           ( 0x15 )
 
109
#define CISTPL_END              ( 0xff )
 
110
 
 
111
#define CIS_STEP                ( 2 )
 
112
#define CISTPL_HEADER_LEN       ( 2 * CIS_STEP )
 
113
#define CISTPL_LEN_OFF          ( 1 * CIS_STEP )
 
114
#define CISTPL_VERS_1_STR_OFF   ( 4 * CIS_STEP )
 
115
 
 
116
/*
 
117
 * Prism2 constants
 
118
 * Taken from prism2sta.c in linux-wlan-ng
 
119
 */
 
120
 
 
121
#define COR_OFFSET      ( 0x3e0 )   /* COR attribute offset of Prism2 PC card */
 
122
#define COR_VALUE       ( 0x41 )    /* Enable PC card with irq in level trigger (but interrupts disabled) */
 
123
 
 
124
/* NIC specific static variables */
 
125
 
 
126
/* The hfa384x_t structure is used extensively in the Linux driver but is ifdef'd out in our include since __KERNEL__ is not defined.
 
127
 * This is a dummy version that contains only the fields we are interested in.
 
128
 */
 
129
 
 
130
typedef struct hfa384x
 
131
{
 
132
  uint32_t iobase;
 
133
  void *membase;
 
134
  uint16_t lastcmd;
 
135
  uint16_t status;         /* in host order */
 
136
  uint16_t resp0;          /* in host order */
 
137
  uint16_t resp1;          /* in host order */
 
138
  uint16_t resp2;          /* in host order */
 
139
  uint8_t  bssid[WLAN_BSSID_LEN];
 
140
} hfa384x_t;
 
141
 
 
142
/* The global instance of the hardware (i.e. where we store iobase and membase, in the absence of anywhere better to put them */
 
143
static hfa384x_t hw_global;
 
144
 
 
145
/*
 
146
 * 802.11 headers in addition to those in hfa384x_tx_frame_t (LLC and SNAP)
 
147
 * Taken from p80211conv.h
 
148
 */
 
149
 
 
150
typedef struct wlan_llc
 
151
{
 
152
  uint8_t   dsap;
 
153
  uint8_t   ssap;
 
154
  uint8_t   ctl;
 
155
}  wlan_llc_t;
 
156
 
 
157
static const wlan_llc_t wlan_llc_snap = { 0xaa, 0xaa, 0x03 }; /* LLC header indicating SNAP (?) */
 
158
 
 
159
#define WLAN_IEEE_OUI_LEN 3
 
160
typedef struct wlan_snap
 
161
{
 
162
  uint8_t   oui[WLAN_IEEE_OUI_LEN];
 
163
  uint16_t  type;
 
164
} wlan_snap_t;
 
165
 
 
166
typedef struct wlan_80211hdr
 
167
{
 
168
  wlan_llc_t llc;
 
169
  wlan_snap_t snap;
 
170
} wlan_80211hdr_t;
 
171
 
 
172
/*
 
173
 * Function prototypes
 
174
 */
 
175
 
 
176
/*
 
177
 * Hardware-level hfa384x functions
 
178
 * These are based on the ones in hfa384x.h (which are ifdef'd out since __KERNEL__ is not defined).
 
179
 * Basically, these functions are the result of hand-evaluating all the ifdefs and defines in the hfa384x.h versions.
 
180
 */
 
181
 
 
182
/* Retrieve the value of one of the MAC registers. */
 
183
static inline uint16_t hfa384x_getreg( hfa384x_t *hw, unsigned int reg )
 
184
{
 
185
#if (WLAN_HOSTIF == WLAN_PLX)
 
186
  return inw ( hw->iobase + reg );
 
187
#elif (WLAN_HOSTIF == WLAN_PCI)
 
188
  return readw ( hw->membase + reg );
 
189
#endif
 
190
}
 
191
 
 
192
/* Set the value of one of the MAC registers. */
 
193
static inline void hfa384x_setreg( hfa384x_t *hw, uint16_t val, unsigned int reg )
 
194
{
 
195
#if (WLAN_HOSTIF == WLAN_PLX)
 
196
  outw ( val, hw->iobase + reg );
 
197
#elif (WLAN_HOSTIF == WLAN_PCI)
 
198
  writew ( val, hw->membase + reg );
 
199
#endif
 
200
  return;
 
201
}
 
202
 
 
203
/*
 
204
 * Noswap versions
 
205
 * Etherboot is i386 only, so swap and noswap are the same...
 
206
 */
 
207
static inline uint16_t hfa384x_getreg_noswap( hfa384x_t *hw, unsigned int reg )
 
208
{
 
209
  return hfa384x_getreg ( hw, reg );
 
210
}
 
211
static inline void hfa384x_setreg_noswap( hfa384x_t *hw, uint16_t val, unsigned int reg )
 
212
{
 
213
  hfa384x_setreg ( hw, val, reg );
 
214
}
 
215
 
 
216
/*
 
217
 * Low-level hfa384x functions
 
218
 * These are based on the ones in hfa384x.c, modified to work in the Etherboot environment.
 
219
 */
 
220
 
 
221
/*
 
222
 * hfa384x_docmd_wait
 
223
 *
 
224
 * Waits for availability of the Command register, then
 
225
 * issues the given command.  Then polls the Evstat register
 
226
 * waiting for command completion.
 
227
 * Arguments:
 
228
 *       hw              device structure
 
229
 *       cmd             Command in host order
 
230
 *       parm0           Parameter0 in host order
 
231
 *       parm1           Parameter1 in host order
 
232
 *       parm2           Parameter2 in host order
 
233
 * Returns:
 
234
 *       0               success
 
235
 *       >0              command indicated error, Status and Resp0-2 are
 
236
 *                       in hw structure.
 
237
 */
 
238
static int hfa384x_docmd_wait( hfa384x_t *hw, uint16_t cmd, uint16_t parm0, uint16_t parm1, uint16_t parm2)
 
239
{
 
240
  uint16_t reg = 0;
 
241
  uint16_t counter = 0;
 
242
 
 
243
  /* wait for the busy bit to clear */
 
244
  counter = 0;
 
245
  reg = hfa384x_getreg(hw, HFA384x_CMD);
 
246
  while ( HFA384x_CMD_ISBUSY(reg) && (counter < 10) ) {
 
247
    reg = hfa384x_getreg(hw, HFA384x_CMD);
 
248
    counter++;
 
249
    udelay(10);
 
250
  }
 
251
  if (HFA384x_CMD_ISBUSY(reg)) {
 
252
    printf("hfa384x_cmd timeout(1), reg=0x%0hx.\n", reg);
 
253
    return -ETIMEDOUT;
 
254
  }
 
255
 
 
256
  /* busy bit clear, write command */
 
257
  hfa384x_setreg(hw, parm0, HFA384x_PARAM0);
 
258
  hfa384x_setreg(hw, parm1, HFA384x_PARAM1);
 
259
  hfa384x_setreg(hw, parm2, HFA384x_PARAM2);
 
260
  hw->lastcmd = cmd;
 
261
  hfa384x_setreg(hw, cmd, HFA384x_CMD);
 
262
 
 
263
  /* Now wait for completion */
 
264
  counter = 0;
 
265
  reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
 
266
  /* Initialization is the problem.  It takes about
 
267
     100ms. "normal" commands are typically is about
 
268
     200-400 us (I've never seen less than 200).  Longer
 
269
     is better so that we're not hammering the bus. */
 
270
  while ( !HFA384x_EVSTAT_ISCMD(reg) && (counter < 5000)) {
 
271
    reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
 
272
    counter++;
 
273
    udelay(200);
 
274
  }
 
275
  if ( ! HFA384x_EVSTAT_ISCMD(reg) ) {
 
276
    printf("hfa384x_cmd timeout(2), reg=0x%0hx.\n", reg);
 
277
    return -ETIMEDOUT;
 
278
  }
 
279
 
 
280
  /* Read status and response */
 
281
  hw->status = hfa384x_getreg(hw, HFA384x_STATUS);
 
282
  hw->resp0 = hfa384x_getreg(hw, HFA384x_RESP0);
 
283
  hw->resp1 = hfa384x_getreg(hw, HFA384x_RESP1);
 
284
  hw->resp2 = hfa384x_getreg(hw, HFA384x_RESP2);
 
285
  hfa384x_setreg(hw, HFA384x_EVACK_CMD, HFA384x_EVACK);
 
286
  return HFA384x_STATUS_RESULT_GET(hw->status);
 
287
}
 
288
 
 
289
/*
 
290
 * Prepare BAP for access.  Assigns FID and RID, sets offset register
 
291
 * and waits for BAP to become available.
 
292
 *
 
293
 * Arguments:
 
294
 *      hw              device structure
 
295
 *      id              FID or RID, destined for the select register (host order)
 
296
 *      offset          An _even_ offset into the buffer for the given FID/RID.
 
297
 * Returns:
 
298
 *      0               success
 
299
 */
 
300
static int hfa384x_prepare_bap(hfa384x_t *hw, uint16_t id, uint16_t offset)
 
301
{
 
302
  int result = 0;
 
303
  uint16_t reg;
 
304
  uint16_t i;
 
305
 
 
306
  /* Validate offset, buf, and len */
 
307
  if ( (offset > HFA384x_BAP_OFFSET_MAX) || (offset % 2) ) {
 
308
    result = -EINVAL;
 
309
  } else {
 
310
    /* Write fid/rid and offset */
 
311
    hfa384x_setreg(hw, id, HFA384x_SELECT0);
 
312
    udelay(10);
 
313
    hfa384x_setreg(hw, offset, HFA384x_OFFSET0);
 
314
    /* Wait for offset[busy] to clear (see BAP_TIMEOUT) */
 
315
    i = 0;
 
316
    do {
 
317
      reg = hfa384x_getreg(hw, HFA384x_OFFSET0);
 
318
      if ( i > 0 ) udelay(2);
 
319
      i++;
 
320
    } while ( i < BAP_TIMEOUT && HFA384x_OFFSET_ISBUSY(reg));
 
321
    if ( i >= BAP_TIMEOUT ) {
 
322
      /* failure */
 
323
      result = reg;
 
324
    } else if ( HFA384x_OFFSET_ISERR(reg) ){
 
325
      /* failure */
 
326
      result = reg;
 
327
    }
 
328
  }
 
329
  return result;
 
330
}
 
331
 
 
332
/*
 
333
 * Copy data from BAP to memory.
 
334
 *
 
335
 * Arguments:
 
336
 *      hw              device structure
 
337
 *      id              FID or RID, destined for the select register (host order)
 
338
 *      offset          An _even_ offset into the buffer for the given FID/RID.
 
339
 *      buf             ptr to array of bytes
 
340
 *      len             length of data to transfer in bytes
 
341
 * Returns:
 
342
 *      0               success
 
343
 */
 
344
static int hfa384x_copy_from_bap(hfa384x_t *hw, uint16_t id, uint16_t offset,
 
345
                          void *buf, unsigned int len)
 
346
{
 
347
  int result = 0;
 
348
  uint8_t       *d = (uint8_t*)buf;
 
349
  uint16_t i;
 
350
  uint16_t reg = 0;
 
351
 
 
352
  /* Prepare BAP */
 
353
  result = hfa384x_prepare_bap ( hw, id, offset );
 
354
  if ( result == 0 ) {
 
355
    /* Read even(len) buf contents from data reg */
 
356
    for ( i = 0; i < (len & 0xfffe); i+=2 ) {
 
357
      *(uint16_t*)(&(d[i])) = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
 
358
    }
 
359
    /* If len odd, handle last byte */
 
360
    if ( len % 2 ){
 
361
      reg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
 
362
      d[len-1] = ((uint8_t*)(&reg))[0];
 
363
    }
 
364
  }
 
365
  if (result) {
 
366
    printf ( "copy_from_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
 
367
  }
 
368
  return result;
 
369
}
 
370
 
 
371
/*
 
372
 * Copy data from memory to BAP.
 
373
 *
 
374
 * Arguments:
 
375
 *      hw              device structure
 
376
 *      id              FID or RID, destined for the select register (host order)
 
377
 *      offset          An _even_ offset into the buffer for the given FID/RID.
 
378
 *      buf             ptr to array of bytes
 
379
 *      len             length of data to transfer in bytes
 
380
 * Returns:
 
381
 *      0               success
 
382
 */
 
383
static int hfa384x_copy_to_bap(hfa384x_t *hw, uint16_t id, uint16_t offset,
 
384
                        void *buf, unsigned int len)
 
385
{
 
386
  int result = 0;
 
387
  uint8_t       *d = (uint8_t*)buf;
 
388
  uint16_t i;
 
389
  uint16_t savereg;
 
390
 
 
391
  /* Prepare BAP */
 
392
  result = hfa384x_prepare_bap ( hw, id, offset );
 
393
  if ( result == 0 ) {
 
394
    /* Write even(len) buf contents to data reg */
 
395
    for ( i = 0; i < (len & 0xfffe); i+=2 ) {
 
396
      hfa384x_setreg_noswap(hw, *(uint16_t*)(&(d[i])), HFA384x_DATA0);
 
397
    }
 
398
    /* If len odd, handle last byte */
 
399
    if ( len % 2 ){
 
400
      savereg = hfa384x_getreg_noswap(hw, HFA384x_DATA0);
 
401
      result = hfa384x_prepare_bap ( hw, id, offset + (len & 0xfffe) );
 
402
      if ( result == 0 ) {
 
403
        ((uint8_t*)(&savereg))[0] = d[len-1];
 
404
        hfa384x_setreg_noswap(hw, savereg, HFA384x_DATA0);
 
405
      }
 
406
    }
 
407
  }
 
408
  if (result) {
 
409
    printf ( "copy_to_bap(%#hx, %#hx, %d) failed, result=%#hx\n", id, offset, len, result);
 
410
  }
 
411
  return result;
 
412
}
 
413
 
 
414
/*
 
415
 * Request a given record to be copied to/from the record buffer.
 
416
 *
 
417
 * Arguments:
 
418
 *      hw              device structure
 
419
 *      write           [0|1] copy the record buffer to the given
 
420
 *                      configuration record. (host order)
 
421
 *      rid             RID of the record to read/write. (host order)
 
422
 *
 
423
 * Returns:
 
424
 *      0               success
 
425
 */
 
426
static inline int hfa384x_cmd_access(hfa384x_t *hw, uint16_t write, uint16_t rid)
 
427
{
 
428
  return hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ACCESS) | HFA384x_CMD_WRITE_SET(write), rid, 0, 0);
 
429
}
 
430
 
 
431
/*
 
432
 * Performs the sequence necessary to read a config/info item.
 
433
 *
 
434
 * Arguments:
 
435
 *      hw              device structure
 
436
 *      rid             config/info record id (host order)
 
437
 *      buf             host side record buffer.  Upon return it will
 
438
 *                      contain the body portion of the record (minus the
 
439
 *                      RID and len).
 
440
 *      len             buffer length (in bytes, should match record length)
 
441
 *
 
442
 * Returns:
 
443
 *      0               success
 
444
 */
 
445
static int hfa384x_drvr_getconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
 
446
{
 
447
  int result = 0;
 
448
  hfa384x_rec_t rec;
 
449
 
 
450
  /* Request read of RID */
 
451
  result = hfa384x_cmd_access( hw, 0, rid);
 
452
  if ( result ) {
 
453
    printf("Call to hfa384x_cmd_access failed\n");
 
454
    return -1;
 
455
  }
 
456
  /* Copy out record length */
 
457
  result = hfa384x_copy_from_bap( hw, rid, 0, &rec, sizeof(rec));
 
458
  if ( result ) {
 
459
    return -1;
 
460
  }
 
461
  /* Validate the record length */
 
462
  if ( ((hfa384x2host_16(rec.reclen)-1)*2) != len ) {  /* note body len calculation in bytes */
 
463
    printf ( "RID len mismatch, rid=%#hx hlen=%d fwlen=%d\n", rid, len, (hfa384x2host_16(rec.reclen)-1)*2);
 
464
    return -1;
 
465
  }
 
466
  /* Copy out record data */
 
467
  result = hfa384x_copy_from_bap( hw, rid, sizeof(rec), buf, len);
 
468
  return result;
 
469
}
 
470
 
 
471
/*
 
472
 * Performs the sequence necessary to read a 16/32 bit config/info item
 
473
 * and convert it to host order.
 
474
 *
 
475
 * Arguments:
 
476
 *      hw              device structure
 
477
 *      rid             config/info record id (in host order)
 
478
 *      val             ptr to 16/32 bit buffer to receive value (in host order)
 
479
 *
 
480
 * Returns:
 
481
 *      0               success
 
482
 */
 
483
#if 0 /* Not actually used anywhere */
 
484
static int hfa384x_drvr_getconfig16(hfa384x_t *hw, uint16_t rid, void *val)
 
485
{
 
486
  int result = 0;
 
487
  result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint16_t));
 
488
  if ( result == 0 ) {
 
489
    *((uint16_t*)val) = hfa384x2host_16(*((uint16_t*)val));
 
490
  }
 
491
  return result;
 
492
}
 
493
#endif
 
494
#if 0 /* Not actually used anywhere */
 
495
static int hfa384x_drvr_getconfig32(hfa384x_t *hw, uint16_t rid, void *val)
 
496
{
 
497
  int result = 0;
 
498
  result = hfa384x_drvr_getconfig(hw, rid, val, sizeof(uint32_t));
 
499
  if ( result == 0 ) {
 
500
    *((uint32_t*)val) = hfa384x2host_32(*((uint32_t*)val));
 
501
  }
 
502
  return result;
 
503
}
 
504
#endif
 
505
 
 
506
/*
 
507
 * Performs the sequence necessary to write a config/info item.
 
508
 *
 
509
 * Arguments:
 
510
 *      hw              device structure
 
511
 *      rid             config/info record id (in host order)
 
512
 *      buf             host side record buffer
 
513
 *      len             buffer length (in bytes)
 
514
 *
 
515
 * Returns:
 
516
 *      0               success
 
517
 */
 
518
static int hfa384x_drvr_setconfig(hfa384x_t *hw, uint16_t rid, void *buf, uint16_t len)
 
519
{
 
520
  int result = 0;
 
521
  hfa384x_rec_t rec;
 
522
 
 
523
  rec.rid = host2hfa384x_16(rid);
 
524
  rec.reclen = host2hfa384x_16((len/2) + 1); /* note conversion to words, +1 for rid field */
 
525
  /* write the record header */
 
526
  result = hfa384x_copy_to_bap( hw, rid, 0, &rec, sizeof(rec));
 
527
  if ( result ) {
 
528
    printf("Failure writing record header\n");
 
529
    return -1;
 
530
  }
 
531
  /* write the record data (if there is any) */
 
532
  if ( len > 0 ) {
 
533
    result = hfa384x_copy_to_bap( hw, rid, sizeof(rec), buf, len);
 
534
    if ( result ) {
 
535
      printf("Failure writing record data\n");
 
536
      return -1;
 
537
    }
 
538
  }
 
539
  /* Trigger setting of record */
 
540
  result = hfa384x_cmd_access( hw, 1, rid);
 
541
  return result;
 
542
}
 
543
 
 
544
/*
 
545
 * Performs the sequence necessary to write a 16/32 bit config/info item.
 
546
 *
 
547
 * Arguments:
 
548
 *      hw              device structure
 
549
 *      rid             config/info record id (in host order)
 
550
 *      val             16/32 bit value to store (in host order)
 
551
 *
 
552
 * Returns:
 
553
 *      0               success
 
554
 */
 
555
static int hfa384x_drvr_setconfig16(hfa384x_t *hw, uint16_t rid, uint16_t *val)
 
556
{
 
557
  uint16_t value;
 
558
  value = host2hfa384x_16(*val);
 
559
  return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint16_t));
 
560
}
 
561
#if 0 /* Not actually used anywhere */
 
562
static int hfa384x_drvr_setconfig32(hfa384x_t *hw, uint16_t rid, uint32_t *val)
 
563
{
 
564
  uint32_t value;
 
565
  value = host2hfa384x_32(*val);
 
566
  return hfa384x_drvr_setconfig(hw, rid, &value, sizeof(uint32_t));
 
567
}
 
568
#endif
 
569
 
 
570
/*
 
571
 * Wait for an event, with specified checking interval and timeout.
 
572
 * Automatically acknolwedges events.
 
573
 *
 
574
 * Arguments:
 
575
 *      hw              device structure
 
576
 *      event_mask      EVSTAT register mask of events to wait for
 
577
 *      event_ack       EVACK register set of events to be acknowledged if they happen (can be
 
578
 *                      used to acknowledge "ignorable" events in addition to the "main" event)
 
579
 *      wait            Time (in us) to wait between each poll of the register
 
580
 *      timeout         Maximum number of polls before timing out
 
581
 *      descr           Descriptive text string of what is being waited for
 
582
 *                      (will be printed out if a timeout happens)
 
583
 *
 
584
 * Returns:
 
585
 *      value of EVSTAT register, or 0 on failure
 
586
 */
 
587
static int hfa384x_wait_for_event(hfa384x_t *hw, uint16_t event_mask, uint16_t event_ack, int wait, int timeout, const char *descr)
 
588
{
 
589
  uint16_t reg;
 
590
  int count = 0;
 
591
 
 
592
  do {
 
593
    reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
 
594
    if ( count > 0 ) udelay(wait);
 
595
    count++;
 
596
  } while ( !(reg & event_mask) && count < timeout);
 
597
  if ( count >= timeout ) {
 
598
    printf("hfa384x: Timed out waiting for %s\n", descr);
 
599
    return 0; /* Return failure */
 
600
  }
 
601
  /* Acknowledge all events that we were waiting on */
 
602
  hfa384x_setreg(hw, reg & ( event_mask | event_ack ), HFA384x_EVACK);
 
603
  return reg;
 
604
}
 
605
 
 
606
/**************************************************************************
 
607
POLL - Wait for a frame
 
608
***************************************************************************/
 
609
static int prism2_poll(struct nic *nic, int retrieve)
 
610
{
 
611
  uint16_t reg;
 
612
  uint16_t rxfid;
 
613
  uint16_t result;
 
614
  hfa384x_rx_frame_t rxdesc;
 
615
  hfa384x_t *hw = &hw_global;
 
616
 
 
617
  /* Check for received packet */
 
618
  reg = hfa384x_getreg(hw, HFA384x_EVSTAT);
 
619
  if ( ! HFA384x_EVSTAT_ISRX(reg) ) {
 
620
    /* No packet received - return 0 */
 
621
    return 0;
 
622
  }
 
623
 
 
624
  if ( ! retrieve ) return 1;
 
625
 
 
626
  /* Acknowledge RX event */
 
627
  hfa384x_setreg(hw, HFA384x_EVACK_RX_SET(1), HFA384x_EVACK);
 
628
  /* Get RX FID */
 
629
  rxfid = hfa384x_getreg(hw, HFA384x_RXFID);
 
630
  /* Get the descriptor (including headers) */
 
631
  result = hfa384x_copy_from_bap(hw, rxfid, 0, &rxdesc, sizeof(rxdesc));
 
632
  if ( result ) {
 
633
    return 0; /* fail */
 
634
  }
 
635
  /* Byte order convert once up front. */
 
636
  rxdesc.status = hfa384x2host_16(rxdesc.status);
 
637
  rxdesc.time = hfa384x2host_32(rxdesc.time);
 
638
  rxdesc.data_len = hfa384x2host_16(rxdesc.data_len);
 
639
 
 
640
  /* Fill in nic->packetlen */
 
641
  nic->packetlen = rxdesc.data_len;
 
642
  if ( nic->packetlen > 0 ) {
 
643
    /* Fill in nic->packet */
 
644
    /*
 
645
     * NOTE: Packets as received have an 8-byte header (LLC+SNAP(?)) terminating with the packet type.
 
646
     * Etherboot expects a 14-byte header terminating with the packet type (it ignores the rest of the
 
647
     * header), so we use a quick hack to achieve this.
 
648
     */
 
649
    result = hfa384x_copy_from_bap(hw, rxfid, HFA384x_RX_DATA_OFF,
 
650
                                   nic->packet + ETH_HLEN - sizeof(wlan_80211hdr_t), nic->packetlen);
 
651
    if ( result ) {
 
652
      return 0; /* fail */
 
653
    }
 
654
  }
 
655
  return 1; /* Packet successfully received */
 
656
}
 
657
 
 
658
/**************************************************************************
 
659
TRANSMIT - Transmit a frame
 
660
***************************************************************************/
 
661
static void prism2_transmit(
 
662
                            struct nic *nic,
 
663
                            const char *d,                      /* Destination */
 
664
                            unsigned int t,                     /* Type */
 
665
                            unsigned int s,                     /* size */
 
666
                            const char *p)                      /* Packet */
 
667
{
 
668
  hfa384x_t *hw = &hw_global;
 
669
  hfa384x_tx_frame_t txdesc;
 
670
  wlan_80211hdr_t p80211hdr = { wlan_llc_snap, {{0,0,0},0} };
 
671
  uint16_t fid;
 
672
  uint16_t status;
 
673
  int result;
 
674
 
 
675
  // Request FID allocation
 
676
  result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ALLOC), HFA384x_DRVR_TXBUF_MAX, 0, 0);
 
677
  if (result != 0) {
 
678
    printf("hfa384x: Tx FID allocate command failed: Aborting transmit..\n");
 
679
    return;
 
680
  }
 
681
  if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_ALLOC, HFA384x_EVACK_INFO, 10, 50, "Tx FID to be allocated\n" ) ) return;
 
682
  fid = hfa384x_getreg(hw, HFA384x_ALLOCFID);
 
683
 
 
684
  /* Build Tx frame structure */
 
685
  memset(&txdesc, 0, sizeof(txdesc));
 
686
  txdesc.tx_control = host2hfa384x_16( HFA384x_TX_MACPORT_SET(0) | HFA384x_TX_STRUCTYPE_SET(1) |
 
687
                                       HFA384x_TX_TXEX_SET(1) | HFA384x_TX_TXOK_SET(1) );
 
688
  txdesc.frame_control =  host2ieee16( WLAN_SET_FC_FTYPE(WLAN_FTYPE_DATA) |
 
689
                                       WLAN_SET_FC_FSTYPE(WLAN_FSTYPE_DATAONLY) |
 
690
                                       WLAN_SET_FC_TODS(1) );
 
691
  memcpy(txdesc.address1, hw->bssid, WLAN_ADDR_LEN);
 
692
  memcpy(txdesc.address2, nic->node_addr, WLAN_ADDR_LEN);
 
693
  memcpy(txdesc.address3, d, WLAN_ADDR_LEN);
 
694
  txdesc.data_len = host2hfa384x_16( sizeof(txdesc) + sizeof(p80211hdr) + s );
 
695
  /* Set up SNAP header */
 
696
  /* Let OUI default to RFC1042 (0x000000) */
 
697
  p80211hdr.snap.type = htons(t);
 
698
 
 
699
  /* Copy txdesc, p80211hdr and payload parts to FID */
 
700
  result = hfa384x_copy_to_bap(hw, fid, 0, &txdesc, sizeof(txdesc));
 
701
  if ( result ) return; /* fail */
 
702
  result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc), &p80211hdr, sizeof(p80211hdr) );
 
703
  if ( result ) return; /* fail */
 
704
  result = hfa384x_copy_to_bap( hw, fid, sizeof(txdesc) + sizeof(p80211hdr), (uint8_t*)p, s );
 
705
  if ( result ) return; /* fail */
 
706
 
 
707
  /* Issue Tx command */
 
708
  result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_TX), fid, 0, 0);
 
709
  if ( result != 0 ) {
 
710
    printf("hfa384x: Transmit failed with result %#hx.\n", result);
 
711
    return;
 
712
  }
 
713
 
 
714
  /* Wait for transmit completion (or exception) */
 
715
  result = hfa384x_wait_for_event(hw, HFA384x_EVSTAT_TXEXC | HFA384x_EVSTAT_TX, HFA384x_EVACK_INFO,
 
716
                                  200, 500, "Tx to complete\n" );
 
717
  if ( !result ) return; /* timeout failure */
 
718
  if ( HFA384x_EVSTAT_ISTXEXC(result) ) {
 
719
    fid = hfa384x_getreg(hw, HFA384x_TXCOMPLFID);
 
720
    printf ( "Tx exception occurred with fid %#hx\n", fid );
 
721
    result = hfa384x_copy_from_bap(hw, fid, 0, &status, sizeof(status));
 
722
    if ( result ) return; /* fail */
 
723
    printf("hfa384x: Tx error occurred (status %#hx):\n", status);
 
724
    if ( HFA384x_TXSTATUS_ISACKERR(status) ) { printf(" ...acknowledgement error\n"); }
 
725
    if ( HFA384x_TXSTATUS_ISFORMERR(status) ) { printf(" ...format error\n"); }
 
726
    if ( HFA384x_TXSTATUS_ISDISCON(status) ) { printf(" ...disconnected error\n"); }
 
727
    if ( HFA384x_TXSTATUS_ISAGEDERR(status) ) { printf(" ...AGED error\n"); }
 
728
    if ( HFA384x_TXSTATUS_ISRETRYERR(status) ) { printf(" ...retry error\n"); }
 
729
    return; /* fail */
 
730
  }
 
731
}
 
732
 
 
733
/**************************************************************************
 
734
DISABLE - Turn off ethernet interface
 
735
***************************************************************************/
 
736
static void prism2_disable ( struct nic *nic __unused ) {
 
737
  /* put the card in its initial state */
 
738
}
 
739
 
 
740
/**************************************************************************
 
741
IRQ - Enable, Disable, or Force interrupts
 
742
***************************************************************************/
 
743
static void prism2_irq(struct nic *nic __unused, irq_action_t action __unused)
 
744
{
 
745
  switch ( action ) {
 
746
  case DISABLE :
 
747
    break;
 
748
  case ENABLE :
 
749
    break;
 
750
  case FORCE :
 
751
    break;
 
752
  }
 
753
}
 
754
 
 
755
/**************************************************************************
 
756
Operations table
 
757
***************************************************************************/
 
758
static struct nic_operations prism2_operations = {
 
759
        .connect        = dummy_connect,
 
760
        .poll           = prism2_poll,
 
761
        .transmit       = prism2_transmit,
 
762
        .irq            = prism2_irq,
 
763
};
 
764
 
 
765
/**************************************************************************
 
766
PROBE - Look for an adapter, this routine's visible to the outside
 
767
You should omit the last argument struct pci_device * for a non-PCI NIC
 
768
***************************************************************************/
 
769
static int prism2_probe ( struct nic *nic, hfa384x_t *hw ) {
 
770
  int result;
 
771
  uint16_t tmp16 = 0;
 
772
  uint16_t infofid;
 
773
  hfa384x_InfFrame_t inf;
 
774
  char ssid[HFA384x_RID_CNFDESIREDSSID_LEN];
 
775
  int info_count = 0;
 
776
 
 
777
  nic->irqno  = 0;
 
778
 
 
779
  /* Initialize card */
 
780
  result = hfa384x_docmd_wait(hw, HFA384x_CMDCODE_INIT, 0,0,0); /* Send initialize command */
 
781
  if ( result ) printf ( "Initialize command returned %#hx\n", result );
 
782
  hfa384x_setreg(hw, 0, HFA384x_INTEN); /* Disable interrupts */
 
783
  hfa384x_setreg(hw, 0xffff, HFA384x_EVACK); /* Acknowledge any spurious events */
 
784
 
 
785
  DBG ( "MAC address %s\n", eth_ntoa ( nic->node_addr ) );
 
786
 
 
787
  /* Retrieve MAC address (and fill out nic->node_addr) */
 
788
  hfa384x_drvr_getconfig ( hw, HFA384x_RID_CNFOWNMACADDR, nic->node_addr, HFA384x_RID_CNFOWNMACADDR_LEN );
 
789
 
 
790
  /* Prepare card for autojoin */
 
791
  /* This procedure is reverse-engineered from a register-level trace of the Linux driver's join process */
 
792
  tmp16 = WLAN_DATA_MAXLEN; /* Set maximum data length */
 
793
  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFMAXDATALEN, &tmp16);
 
794
  if ( result ) printf ( "Set Max Data Length command returned %#hx\n", result );
 
795
  tmp16 = 0x000f; /* Set transmit rate(?) */
 
796
  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_TXRATECNTL, &tmp16);
 
797
  if ( result ) printf ( "Set Transmit Rate command returned %#hx\n", result );
 
798
  tmp16 = HFA384x_CNFAUTHENTICATION_OPENSYSTEM; /* Set authentication type to OpenSystem */
 
799
  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFAUTHENTICATION, &tmp16);
 
800
  if ( result ) printf ( "Set Authentication Type command returned %#hx\n", result );
 
801
  /* Set SSID */
 
802
  memset(ssid, 0, HFA384x_RID_CNFDESIREDSSID_LEN);
 
803
  for ( tmp16=0; tmp16<sizeof(hardcoded_ssid); tmp16++ ) { ssid[2+tmp16] = hardcoded_ssid[tmp16]; }
 
804
  ssid[0] = sizeof(hardcoded_ssid) - 1; /* Ignore terminating zero */
 
805
  result = hfa384x_drvr_setconfig(hw, HFA384x_RID_CNFDESIREDSSID, ssid, HFA384x_RID_CNFDESIREDSSID_LEN); /* Set the SSID */
 
806
  if ( result ) printf ( "Set SSID command returned %#hx\n", result );
 
807
  tmp16 = 1; /* Set port type to ESS port */
 
808
  result = hfa384x_drvr_setconfig16(hw, HFA384x_RID_CNFPORTTYPE, &tmp16);
 
809
  if ( result ) printf ( "Set port type command returned %#hx\n", result );
 
810
  /* Enable card */
 
811
  result = hfa384x_docmd_wait(hw, HFA384x_CMD_CMDCODE_SET(HFA384x_CMDCODE_ENABLE) | HFA384x_CMD_MACPORT_SET(0), 0,0,0);
 
812
  if ( result ) printf ( "Enable command returned %#hx\n", result );
 
813
 
 
814
  do {
 
815
    /* Increment info_count, abort if too many attempts.
 
816
     * See comment next to definition of MAX_JOIN_INFO_COUNT for explanation.
 
817
     */
 
818
    info_count++;
 
819
    if ( info_count > MAX_JOIN_INFO_COUNT ) {
 
820
      printf ( "Too many failed attempts - aborting\n" );
 
821
      return 0;
 
822
    }
 
823
 
 
824
    /* Wait for info frame to indicate link status */
 
825
    if ( sizeof(hardcoded_ssid) == 1 ) {
 
826
      /* Empty SSID => join to any SSID */
 
827
      printf ( "Attempting to autojoin to any available access point (attempt %d)...", info_count );
 
828
    } else {
 
829
      printf ( "Attempting to autojoin to SSID %s (attempt %d)...", &ssid[2], info_count );
 
830
    }
 
831
 
 
832
    if ( !hfa384x_wait_for_event(hw, HFA384x_EVSTAT_INFO, 0, 1000, 2000, "Info event" ) ) return 0;
 
833
    printf("done\n");
 
834
    infofid = hfa384x_getreg(hw, HFA384x_INFOFID);
 
835
    /* Retrieve the length */
 
836
    result = hfa384x_copy_from_bap( hw, infofid, 0, &inf.framelen, sizeof(uint16_t));
 
837
    if ( result ) return 0; /* fail */
 
838
    inf.framelen = hfa384x2host_16(inf.framelen);
 
839
    /* Retrieve the rest */
 
840
    result = hfa384x_copy_from_bap( hw, infofid, sizeof(uint16_t),
 
841
                                    &(inf.infotype), inf.framelen * sizeof(uint16_t));
 
842
    if ( result ) return 0; /* fail */
 
843
    if ( inf.infotype != HFA384x_IT_LINKSTATUS ) {
 
844
      /* Not a Link Status info frame: die */
 
845
      printf ( "Unexpected info frame type %#hx (not LinkStatus type)\n", inf.infotype );
 
846
      return 0;
 
847
    }
 
848
    inf.info.linkstatus.linkstatus = hfa384x2host_16(inf.info.linkstatus.linkstatus);
 
849
    if ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED ) {
 
850
      /* Link not connected - retry */
 
851
      printf ( "Link not connected (status %#hx)\n", inf.info.linkstatus.linkstatus );
 
852
    }
 
853
  } while ( inf.info.linkstatus.linkstatus != HFA384x_LINK_CONNECTED );
 
854
 
 
855
  /* Retrieve BSSID and print Connected message */
 
856
  result = hfa384x_drvr_getconfig(hw, HFA384x_RID_CURRENTBSSID, hw->bssid, WLAN_BSSID_LEN);
 
857
 
 
858
  DBG ( "Link connected (BSSID %s - ", eth_ntoa ( hw->bssid ) );
 
859
  DBG ( " MAC address %s)\n", eth_ntoa (nic->node_addr ) );
 
860
 
 
861
  /* point to NIC specific routines */
 
862
  nic->nic_op   = &prism2_operations;
 
863
  return 1;
 
864
}
 
865