You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

prism2.c 28KB

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