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 <gpxe/pci.h> 21 #include <gpxe/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 858