wavelan.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. /*
  2. Lucent Wavelan IEEE 802.11 pcmcia.
  3. There is almost no documentation for the card.
  4. the driver is done using both the FreeBSD, Linux and
  5. original Plan 9 drivers as `documentation'.
  6. Has been used with the card plugged in during all up time.
  7. no cards removals/insertions yet.
  8. For known BUGS see the comments below. Besides,
  9. the driver keeps interrupts disabled for just too
  10. long. When it gets robust, locks should be revisited.
  11. BUGS: check endian, alignment and mem/io issues;
  12. multicast;
  13. receive watchdog interrupts.
  14. TODO: automatic power management;
  15. improve locking.
  16. */
  17. #include "u.h"
  18. #include "../port/lib.h"
  19. #include "mem.h"
  20. #include "dat.h"
  21. #include "fns.h"
  22. #include "io.h"
  23. #include "../port/error.h"
  24. #include "../port/netif.h"
  25. #include "etherif.h"
  26. #include "wavelan.h"
  27. /*
  28. * When we're using a PCI device and memory-mapped I/O,
  29. * the registers are spaced out as though each takes 32 bits,
  30. * even though they are only 16-bit registers. Thus,
  31. * ctlr->mmb[reg] is the right way to access register reg,
  32. * even though a priori you'd expect to use ctlr->mmb[reg/2].
  33. */
  34. void
  35. csr_outs(Ctlr *ctlr, int reg, ushort arg)
  36. {
  37. if(ctlr->mmb)
  38. ctlr->mmb[reg] = arg;
  39. else
  40. outs(ctlr->iob+reg, arg);
  41. }
  42. ushort
  43. csr_ins(Ctlr *ctlr, int reg)
  44. {
  45. if(ctlr->mmb)
  46. return ctlr->mmb[reg];
  47. else
  48. return ins(ctlr->iob+reg);
  49. }
  50. static void
  51. csr_ack(Ctlr *ctlr, int ev)
  52. {
  53. csr_outs(ctlr, WR_EvAck, ev);
  54. }
  55. static void
  56. csr_inss(Ctlr *ctlr, int reg, void *dat, int ndat)
  57. {
  58. ushort *rp, *wp;
  59. if(ctlr->mmb){
  60. rp = &ctlr->mmb[reg];
  61. wp = dat;
  62. while(ndat-- > 0)
  63. *wp++ = *rp;
  64. }else
  65. inss(ctlr->iob+reg, dat, ndat);
  66. }
  67. static void
  68. csr_outss(Ctlr *ctlr, int reg, void *dat, int ndat)
  69. {
  70. ushort *rp, *wp;
  71. if(ctlr->mmb){
  72. rp = dat;
  73. wp = &ctlr->mmb[reg];
  74. while(ndat-- > 0)
  75. *wp = *rp++;
  76. }else
  77. outss(ctlr->iob+reg, dat, ndat);
  78. }
  79. // w_... routines do not ilock the Ctlr and should
  80. // be called locked.
  81. void
  82. w_intdis(Ctlr* ctlr)
  83. {
  84. csr_outs(ctlr, WR_IntEna, 0);
  85. csr_ack(ctlr, 0xffff);
  86. }
  87. static void
  88. w_intena(Ctlr* ctlr)
  89. {
  90. csr_outs(ctlr, WR_IntEna, WEvs);
  91. }
  92. int
  93. w_cmd(Ctlr *ctlr, ushort cmd, ushort arg)
  94. {
  95. int i, rc;
  96. for(i=0; i<WTmOut; i++)
  97. if((csr_ins(ctlr, WR_Cmd)&WCmdBusy) == 0)
  98. break;
  99. if(i==WTmOut){
  100. print("#l%d: issuing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_Cmd));
  101. return -1;
  102. }
  103. csr_outs(ctlr, WR_Parm0, arg);
  104. csr_outs(ctlr, WR_Cmd, cmd);
  105. for(i=0; i<WTmOut; i++)
  106. if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
  107. break;
  108. if(i==WTmOut){
  109. /*
  110. * WCmdIni can take a really long time.
  111. */
  112. enum { IniTmOut = 2000 };
  113. for(i=0; i<IniTmOut; i++){
  114. if(csr_ins(ctlr, WR_EvSts)&WCmdEv)
  115. break;
  116. microdelay(100);
  117. }
  118. if(i < IniTmOut)
  119. if(0) print("#l%d: long cmd %.4ux %d\n", ctlr->ctlrno, cmd, i);
  120. if(i == IniTmOut){
  121. print("#l%d: execing cmd %.4ux: %.4ux\n", ctlr->ctlrno, cmd, csr_ins(ctlr, WR_EvSts));
  122. return -1;
  123. }
  124. }
  125. rc = csr_ins(ctlr, WR_Sts);
  126. csr_ack(ctlr, WCmdEv);
  127. if((rc&WCmdMsk) != (cmd&WCmdMsk)){
  128. print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
  129. return -1;
  130. }
  131. if(rc&WResSts){
  132. /*
  133. * Don't print; this happens on every WCmdAccWr for some reason.
  134. */
  135. if(0) print("#l%d: cmd %.4ux: status %.4ux\n", ctlr->ctlrno, cmd, rc);
  136. return -1;
  137. }
  138. return 0;
  139. }
  140. static int
  141. w_seek(Ctlr* ctlr, ushort id, ushort offset, int chan)
  142. {
  143. int i, rc;
  144. static ushort sel[] = { WR_Sel0, WR_Sel1 };
  145. static ushort off[] = { WR_Off0, WR_Off1 };
  146. if(chan != 0 && chan != 1)
  147. panic("wavelan: bad chan\n");
  148. csr_outs(ctlr, sel[chan], id);
  149. csr_outs(ctlr, off[chan], offset);
  150. for (i=0; i<WTmOut; i++){
  151. rc = csr_ins(ctlr, off[chan]);
  152. if((rc & (WBusyOff|WErrOff)) == 0)
  153. return 0;
  154. }
  155. return -1;
  156. }
  157. int
  158. w_inltv(Ctlr* ctlr, Wltv* ltv)
  159. {
  160. int len;
  161. ushort code;
  162. if(w_cmd(ctlr, WCmdAccRd, ltv->type)){
  163. DEBUG("wavelan: access read failed\n");
  164. return -1;
  165. }
  166. if(w_seek(ctlr,ltv->type,0,1)){
  167. DEBUG("wavelan: seek failed\n");
  168. return -1;
  169. }
  170. len = csr_ins(ctlr, WR_Data1);
  171. if(len > ltv->len)
  172. return -1;
  173. ltv->len = len;
  174. if((code=csr_ins(ctlr, WR_Data1)) != ltv->type){
  175. USED(code);
  176. DEBUG("wavelan: type %x != code %x\n",ltv->type,code);
  177. return -1;
  178. }
  179. if(ltv->len > 0)
  180. csr_inss(ctlr, WR_Data1, &ltv->val, ltv->len-1);
  181. return 0;
  182. }
  183. static void
  184. w_outltv(Ctlr* ctlr, Wltv* ltv)
  185. {
  186. if(w_seek(ctlr,ltv->type, 0, 1))
  187. return;
  188. csr_outss(ctlr, WR_Data1, ltv, ltv->len+1);
  189. w_cmd(ctlr, WCmdAccWr, ltv->type);
  190. }
  191. void
  192. ltv_outs(Ctlr* ctlr, int type, ushort val)
  193. {
  194. Wltv ltv;
  195. ltv.len = 2;
  196. ltv.type = type;
  197. ltv.val = val;
  198. w_outltv(ctlr, &ltv);
  199. }
  200. int
  201. ltv_ins(Ctlr* ctlr, int type)
  202. {
  203. Wltv ltv;
  204. ltv.len = 2;
  205. ltv.type = type;
  206. ltv.val = 0;
  207. if(w_inltv(ctlr, &ltv))
  208. return -1;
  209. return ltv.val;
  210. }
  211. static void
  212. ltv_outstr(Ctlr* ctlr, int type, char* val)
  213. {
  214. Wltv ltv;
  215. int len;
  216. len = strlen(val);
  217. if(len > sizeof(ltv.s))
  218. len = sizeof(ltv.s);
  219. memset(&ltv, 0, sizeof(ltv));
  220. ltv.len = (sizeof(ltv.type)+sizeof(ltv.slen)+sizeof(ltv.s))/2;
  221. ltv.type = type;
  222. // This should be ltv.slen = len; according to Axel Belinfante
  223. ltv.slen = len;
  224. strncpy(ltv.s, val, len);
  225. w_outltv(ctlr, &ltv);
  226. }
  227. static char Unkname[] = "who knows";
  228. static char Nilname[] = "card does not tell";
  229. static char*
  230. ltv_inname(Ctlr* ctlr, int type)
  231. {
  232. static Wltv ltv;
  233. int len;
  234. memset(&ltv,0,sizeof(ltv));
  235. ltv.len = WNameLen/2+2;
  236. ltv.type = type;
  237. if(w_inltv(ctlr, &ltv))
  238. return Unkname;
  239. len = ltv.slen;
  240. if(len == 0 || ltv.s[0] == 0)
  241. return Nilname;
  242. if(len >= sizeof ltv.s)
  243. len = sizeof ltv.s - 1;
  244. ltv.s[len] = '\0';
  245. return ltv.s;
  246. }
  247. static int
  248. w_read(Ctlr* ctlr, int type, int off, void* buf, ulong len)
  249. {
  250. if(w_seek(ctlr, type, off, 1)){
  251. DEBUG("wavelan: w_read: seek failed");
  252. return 0;
  253. }
  254. csr_inss(ctlr, WR_Data1, buf, len/2);
  255. return len;
  256. }
  257. static int
  258. w_write(Ctlr* ctlr, int type, int off, void* buf, ulong len)
  259. {
  260. int tries;
  261. for (tries=0; tries < WTmOut; tries++){
  262. if(w_seek(ctlr, type, off, 0)){
  263. DEBUG("wavelan: w_write: seek failed\n");
  264. return 0;
  265. }
  266. csr_outss(ctlr, WR_Data0, buf, len/2);
  267. csr_outs(ctlr, WR_Data0, 0xdead);
  268. csr_outs(ctlr, WR_Data0, 0xbeef);
  269. if(w_seek(ctlr, type, off + len, 0)){
  270. DEBUG("wavelan: write seek failed\n");
  271. return 0;
  272. }
  273. if(csr_ins(ctlr, WR_Data0) == 0xdead)
  274. if(csr_ins(ctlr, WR_Data0) == 0xbeef)
  275. return len;
  276. DEBUG("wavelan: Hermes bug byte.\n");
  277. return 0;
  278. }
  279. DEBUG("wavelan: tx timeout\n");
  280. return 0;
  281. }
  282. static int
  283. w_alloc(Ctlr* ctlr, int len)
  284. {
  285. int rc;
  286. int i,j;
  287. if(w_cmd(ctlr, WCmdMalloc, len)==0)
  288. for (i = 0; i<WTmOut; i++)
  289. if(csr_ins(ctlr, WR_EvSts) & WAllocEv){
  290. csr_ack(ctlr, WAllocEv);
  291. rc=csr_ins(ctlr, WR_Alloc);
  292. if(w_seek(ctlr, rc, 0, 0))
  293. return -1;
  294. len = len/2;
  295. for (j=0; j<len; j++)
  296. csr_outs(ctlr, WR_Data0, 0);
  297. return rc;
  298. }
  299. return -1;
  300. }
  301. static int
  302. w_enable(Ether* ether)
  303. {
  304. Wltv ltv;
  305. Ctlr* ctlr = (Ctlr*) ether->ctlr;
  306. if(!ctlr)
  307. return -1;
  308. w_intdis(ctlr);
  309. w_cmd(ctlr, WCmdDis, 0);
  310. w_intdis(ctlr);
  311. if(w_cmd(ctlr, WCmdIni, 0))
  312. return -1;
  313. w_intdis(ctlr);
  314. ltv_outs(ctlr, WTyp_Tick, 8);
  315. ltv_outs(ctlr, WTyp_MaxLen, ctlr->maxlen);
  316. ltv_outs(ctlr, WTyp_Ptype, ctlr->ptype);
  317. ltv_outs(ctlr, WTyp_CreateIBSS, ctlr->createibss);
  318. ltv_outs(ctlr, WTyp_RtsThres, ctlr->rtsthres);
  319. ltv_outs(ctlr, WTyp_TxRate, ctlr->txrate);
  320. ltv_outs(ctlr, WTyp_ApDens, ctlr->apdensity);
  321. ltv_outs(ctlr, WTyp_PMWait, ctlr->pmwait);
  322. ltv_outs(ctlr, WTyp_PM, ctlr->pmena);
  323. if(*ctlr->netname)
  324. ltv_outstr(ctlr, WTyp_NetName, ctlr->netname);
  325. if(*ctlr->wantname)
  326. ltv_outstr(ctlr, WTyp_WantName, ctlr->wantname);
  327. ltv_outs(ctlr, WTyp_Chan, ctlr->chan);
  328. if(*ctlr->nodename)
  329. ltv_outstr(ctlr, WTyp_NodeName, ctlr->nodename);
  330. ltv.len = 4;
  331. ltv.type = WTyp_Mac;
  332. memmove(ltv.addr, ether->ea, Eaddrlen);
  333. w_outltv(ctlr, &ltv);
  334. ltv_outs(ctlr, WTyp_Prom, (ether->prom?1:0));
  335. if(ctlr->hascrypt){
  336. ltv_outs(ctlr, WTyp_Crypt, ctlr->crypt);
  337. ltv_outs(ctlr, WTyp_TxKey, ctlr->txkey);
  338. w_outltv(ctlr, &ctlr->keys);
  339. ltv_outs(ctlr, WTyp_XClear, ctlr->xclear);
  340. }
  341. // BUG: set multicast addresses
  342. if(w_cmd(ctlr, WCmdEna, 0)){
  343. DEBUG("wavelan: Enable failed");
  344. return -1;
  345. }
  346. ctlr->txdid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
  347. ctlr->txmid = w_alloc(ctlr, 1518 + sizeof(WFrame) + 8);
  348. if(ctlr->txdid == -1 || ctlr->txmid == -1)
  349. DEBUG("wavelan: alloc failed");
  350. ctlr->txbusy = 0;
  351. w_intena(ctlr);
  352. return 0;
  353. }
  354. static void
  355. w_rxdone(Ether* ether)
  356. {
  357. Ctlr* ctlr = (Ctlr*) ether->ctlr;
  358. int len, sp;
  359. WFrame f;
  360. Block* bp=0;
  361. Etherpkt* ep;
  362. sp = csr_ins(ctlr, WR_RXId);
  363. len = w_read(ctlr, sp, 0, &f, sizeof(f));
  364. if(len == 0){
  365. DEBUG("wavelan: read frame error\n");
  366. goto rxerror;
  367. }
  368. if(f.sts&WF_Err){
  369. goto rxerror;
  370. }
  371. switch(f.sts){
  372. case WF_1042:
  373. case WF_Tunnel:
  374. case WF_WMP:
  375. len = f.dlen + WSnapHdrLen;
  376. bp = iallocb(ETHERHDRSIZE + len + 2);
  377. if(!bp)
  378. goto rxerror;
  379. ep = (Etherpkt*) bp->wp;
  380. memmove(ep->d, f.addr1, Eaddrlen);
  381. memmove(ep->s, f.addr2, Eaddrlen);
  382. memmove(ep->type,&f.type,2);
  383. bp->wp += ETHERHDRSIZE;
  384. if(w_read(ctlr, sp, WF_802_11_Off, bp->wp, len+2) == 0){
  385. DEBUG("wavelan: read 802.11 error\n");
  386. goto rxerror;
  387. }
  388. bp->wp = bp->rp+(ETHERHDRSIZE+f.dlen);
  389. break;
  390. default:
  391. len = ETHERHDRSIZE + f.dlen + 2;
  392. bp = iallocb(len);
  393. if(!bp)
  394. goto rxerror;
  395. if(w_read(ctlr, sp, WF_802_3_Off, bp->wp, len) == 0){
  396. DEBUG("wavelan: read 800.3 error\n");
  397. goto rxerror;
  398. }
  399. bp->wp += len;
  400. }
  401. ctlr->nrx++;
  402. etheriq(ether,bp,1);
  403. ctlr->signal = ((ctlr->signal*15)+((f.qinfo>>8) & 0xFF))/16;
  404. ctlr->noise = ((ctlr->noise*15)+(f.qinfo & 0xFF))/16;
  405. return;
  406. rxerror:
  407. freeb(bp);
  408. ctlr->nrxerr++;
  409. }
  410. static void
  411. w_txstart(Ether* ether)
  412. {
  413. Etherpkt *pkt;
  414. Ctlr *ctlr;
  415. Block *bp;
  416. int len, off;
  417. if((ctlr = ether->ctlr) == nil || (ctlr->state & (Attached|Power)) != (Attached|Power) || ctlr->txbusy)
  418. return;
  419. if((bp = qget(ether->oq)) == nil)
  420. return;
  421. pkt = (Etherpkt*)bp->rp;
  422. //
  423. // If the packet header type field is > 1500 it is an IP or
  424. // ARP datagram, otherwise it is an 802.3 packet. See RFC1042.
  425. //
  426. memset(&ctlr->txf, 0, sizeof(ctlr->txf));
  427. if(((pkt->type[0]<<8)|pkt->type[1]) > 1500){
  428. ctlr->txf.framectl = WF_Data;
  429. memmove(ctlr->txf.addr1, pkt->d, Eaddrlen);
  430. memmove(ctlr->txf.addr2, pkt->s, Eaddrlen);
  431. memmove(ctlr->txf.dstaddr, pkt->d, Eaddrlen);
  432. memmove(ctlr->txf.srcaddr, pkt->s, Eaddrlen);
  433. memmove(&ctlr->txf.type, pkt->type, 2);
  434. bp->rp += ETHERHDRSIZE;
  435. len = BLEN(bp);
  436. off = WF_802_11_Off;
  437. ctlr->txf.dlen = len+ETHERHDRSIZE-WSnapHdrLen;
  438. hnputs((uchar*)&ctlr->txf.dat[0], WSnap0);
  439. hnputs((uchar*)&ctlr->txf.dat[1], WSnap1);
  440. hnputs((uchar*)&ctlr->txf.len, len+ETHERHDRSIZE-WSnapHdrLen);
  441. }
  442. else{
  443. len = BLEN(bp);
  444. off = WF_802_3_Off;
  445. ctlr->txf.dlen = len;
  446. }
  447. w_write(ctlr, ctlr->txdid, 0, &ctlr->txf, sizeof(ctlr->txf));
  448. w_write(ctlr, ctlr->txdid, off, bp->rp, len+2);
  449. if(w_cmd(ctlr, WCmdReclaim|WCmdTx, ctlr->txdid)){
  450. DEBUG("wavelan: transmit failed\n");
  451. ctlr->ntxerr++;
  452. }
  453. else{
  454. ctlr->txbusy = 1;
  455. ctlr->txtmout = 2;
  456. }
  457. freeb(bp);
  458. }
  459. static void
  460. w_txdone(Ctlr* ctlr, int sts)
  461. {
  462. ctlr->txbusy = 0;
  463. ctlr->txtmout = 0;
  464. if(sts & WTxErrEv)
  465. ctlr->ntxerr++;
  466. else
  467. ctlr->ntx++;
  468. }
  469. static int
  470. w_stats(Ctlr* ctlr)
  471. {
  472. int i, rc, sp;
  473. Wltv ltv;
  474. ulong* p = (ulong*)&ctlr->WStats;
  475. ulong* pend = (ulong*)&ctlr->end;
  476. sp = csr_ins(ctlr, WR_InfoId);
  477. ltv.len = ltv.type = 0;
  478. w_read(ctlr, sp, 0, &ltv, 4);
  479. if(ltv.type == WTyp_Stats){
  480. ltv.len--;
  481. for (i = 0; i < ltv.len && p < pend; i++){
  482. rc = csr_ins(ctlr, WR_Data1);
  483. if(rc > 0xf000)
  484. rc = ~rc & 0xffff;
  485. p[i] += rc;
  486. }
  487. return 0;
  488. }
  489. return -1;
  490. }
  491. static void
  492. w_intr(Ether *ether)
  493. {
  494. int rc, txid;
  495. Ctlr* ctlr = (Ctlr*) ether->ctlr;
  496. if((ctlr->state & Power) == 0)
  497. return;
  498. if((ctlr->state & Attached) == 0){
  499. csr_ack(ctlr, 0xffff);
  500. csr_outs(ctlr, WR_IntEna, 0);
  501. return;
  502. }
  503. rc = csr_ins(ctlr, WR_EvSts);
  504. csr_ack(ctlr, ~WEvs); // Not interested in them
  505. if(rc & WRXEv){
  506. w_rxdone(ether);
  507. csr_ack(ctlr, WRXEv);
  508. }
  509. if(rc & WTXEv){
  510. w_txdone(ctlr, rc);
  511. csr_ack(ctlr, WTXEv);
  512. }
  513. if(rc & WAllocEv){
  514. ctlr->nalloc++;
  515. txid = csr_ins(ctlr, WR_Alloc);
  516. csr_ack(ctlr, WAllocEv);
  517. if(txid == ctlr->txdid){
  518. if((rc & WTXEv) == 0)
  519. w_txdone(ctlr, rc);
  520. }
  521. }
  522. if(rc & WInfoEv){
  523. ctlr->ninfo++;
  524. w_stats(ctlr);
  525. csr_ack(ctlr, WInfoEv);
  526. }
  527. if(rc & WTxErrEv){
  528. w_txdone(ctlr, rc);
  529. csr_ack(ctlr, WTxErrEv);
  530. }
  531. if(rc & WIDropEv){
  532. ctlr->nidrop++;
  533. csr_ack(ctlr, WIDropEv);
  534. }
  535. w_txstart(ether);
  536. }
  537. // Watcher to ensure that the card still works properly and
  538. // to request WStats updates once a minute.
  539. // BUG: it runs much more often, see the comment below.
  540. static void
  541. w_timer(void* arg)
  542. {
  543. Ether* ether = (Ether*) arg;
  544. Ctlr* ctlr = (Ctlr*)ether->ctlr;
  545. ctlr->timerproc = up;
  546. for(;;){
  547. tsleep(&ctlr->timer, return0, 0, 50);
  548. ctlr = (Ctlr*)ether->ctlr;
  549. if(ctlr == 0)
  550. break;
  551. if((ctlr->state & (Attached|Power)) != (Attached|Power))
  552. continue;
  553. ctlr->ticks++;
  554. ilock(ctlr);
  555. // Seems that the card gets frames BUT does
  556. // not send the interrupt; this is a problem because
  557. // I suspect it runs out of receive buffers and
  558. // stops receiving until a transmit watchdog
  559. // reenables the card.
  560. // The problem is serious because it leads to
  561. // poor rtts.
  562. // This can be seen clearly by commenting out
  563. // the next if and doing a ping: it will stop
  564. // receiving (although the icmp replies are being
  565. // issued from the remote) after a few seconds.
  566. // Of course this `bug' could be because I'm reading
  567. // the card frames in the wrong way; due to the
  568. // lack of documentation I cannot know.
  569. if(csr_ins(ctlr, WR_EvSts)&WEvs){
  570. ctlr->tickintr++;
  571. w_intr(ether);
  572. }
  573. if((ctlr->ticks % 10) == 0) {
  574. if(ctlr->txtmout && --ctlr->txtmout == 0){
  575. ctlr->nwatchdogs++;
  576. w_txdone(ctlr, WTxErrEv);
  577. if(w_enable(ether)){
  578. DEBUG("wavelan: wdog enable failed\n");
  579. }
  580. w_txstart(ether);
  581. }
  582. if((ctlr->ticks % 120) == 0)
  583. if(ctlr->txbusy == 0)
  584. w_cmd(ctlr, WCmdAskStats, WTyp_Stats);
  585. }
  586. iunlock(ctlr);
  587. }
  588. pexit("terminated", 0);
  589. }
  590. void
  591. w_multicast(void*, uchar*, int)
  592. {
  593. // BUG: to be added.
  594. }
  595. void
  596. w_attach(Ether* ether)
  597. {
  598. Ctlr* ctlr;
  599. char name[64];
  600. int rc;
  601. if(ether->ctlr == 0)
  602. return;
  603. snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
  604. ctlr = (Ctlr*) ether->ctlr;
  605. if((ctlr->state & Attached) == 0){
  606. ilock(ctlr);
  607. rc = w_enable(ether);
  608. iunlock(ctlr);
  609. if(rc == 0){
  610. ctlr->state |= Attached;
  611. kproc(name, w_timer, ether);
  612. } else
  613. print("#l%d: enable failed\n",ether->ctlrno);
  614. }
  615. }
  616. void
  617. w_detach(Ether* ether)
  618. {
  619. Ctlr* ctlr;
  620. char name[64];
  621. if(ether->ctlr == nil)
  622. return;
  623. snprint(name, sizeof(name), "#l%dtimer", ether->ctlrno);
  624. ctlr = (Ctlr*) ether->ctlr;
  625. if(ctlr->state & Attached){
  626. ilock(ctlr);
  627. w_intdis(ctlr);
  628. if(ctlr->timerproc){
  629. if(!postnote(ctlr->timerproc, 1, "kill", NExit))
  630. print("timerproc note not posted\n");
  631. print("w_detach, killing 0x%p\n", ctlr->timerproc);
  632. }
  633. ctlr->state &= ~Attached;
  634. iunlock(ctlr);
  635. }
  636. ether->ctlr = nil;
  637. }
  638. void
  639. w_power(Ether* ether, int on)
  640. {
  641. Ctlr *ctlr;
  642. ctlr = (Ctlr*) ether->ctlr;
  643. ilock(ctlr);
  644. iprint("w_power %d\n", on);
  645. if(on){
  646. if((ctlr->state & Power) == 0){
  647. if (wavelanreset(ether, ctlr) < 0){
  648. iprint("w_power: reset failed\n");
  649. iunlock(ctlr);
  650. w_detach(ether);
  651. free(ctlr);
  652. return;
  653. }
  654. if(ctlr->state & Attached)
  655. w_enable(ether);
  656. ctlr->state |= Power;
  657. }
  658. }else{
  659. if(ctlr->state & Power){
  660. if(ctlr->state & Attached)
  661. w_intdis(ctlr);
  662. ctlr->state &= ~Power;
  663. }
  664. }
  665. iunlock(ctlr);
  666. }
  667. #define PRINTSTAT(fmt,val) l += snprint(p+l, READSTR-l, (fmt), (val))
  668. #define PRINTSTR(fmt) l += snprint(p+l, READSTR-l, (fmt))
  669. long
  670. w_ifstat(Ether* ether, void* a, long n, ulong offset)
  671. {
  672. Ctlr *ctlr = (Ctlr*) ether->ctlr;
  673. char *k, *p;
  674. int i, l, txid;
  675. ether->oerrs = ctlr->ntxerr;
  676. ether->crcs = ctlr->nrxfcserr;
  677. ether->frames = 0;
  678. ether->buffs = ctlr->nrxdropnobuf;
  679. ether->overflows = 0;
  680. //
  681. // Offset must be zero or there's a possibility the
  682. // new data won't match the previous read.
  683. //
  684. if(n == 0 || offset != 0)
  685. return 0;
  686. p = malloc(READSTR);
  687. l = 0;
  688. PRINTSTAT("Signal: %d\n", ctlr->signal-149);
  689. PRINTSTAT("Noise: %d\n", ctlr->noise-149);
  690. PRINTSTAT("SNR: %ud\n", ctlr->signal-ctlr->noise);
  691. PRINTSTAT("Interrupts: %lud\n", ctlr->nints);
  692. PRINTSTAT("Double Interrupts: %lud\n", ctlr->ndoubleint);
  693. PRINTSTAT("TxPackets: %lud\n", ctlr->ntx);
  694. PRINTSTAT("RxPackets: %lud\n", ctlr->nrx);
  695. PRINTSTAT("TxErrors: %lud\n", ctlr->ntxerr);
  696. PRINTSTAT("RxErrors: %lud\n", ctlr->nrxerr);
  697. PRINTSTAT("TxRequests: %lud\n", ctlr->ntxrq);
  698. PRINTSTAT("AllocEvs: %lud\n", ctlr->nalloc);
  699. PRINTSTAT("InfoEvs: %lud\n", ctlr->ninfo);
  700. PRINTSTAT("InfoDrop: %lud\n", ctlr->nidrop);
  701. PRINTSTAT("WatchDogs: %lud\n", ctlr->nwatchdogs);
  702. PRINTSTAT("Ticks: %ud\n", ctlr->ticks);
  703. PRINTSTAT("TickIntr: %ud\n", ctlr->tickintr);
  704. k = ((ctlr->state & Attached) ? "attached" : "not attached");
  705. PRINTSTAT("Card %s", k);
  706. k = ((ctlr->state & Power) ? "on" : "off");
  707. PRINTSTAT("PCardower %s", k);
  708. k = ((ctlr->txbusy)? ", txbusy" : "");
  709. PRINTSTAT("%s\n", k);
  710. if(ctlr->hascrypt){
  711. PRINTSTR("Keys: ");
  712. for (i = 0; i < WNKeys; i++){
  713. if(ctlr->keys.keys[i].len == 0)
  714. PRINTSTR("none ");
  715. else if(SEEKEYS == 0)
  716. PRINTSTR("set ");
  717. else
  718. PRINTSTAT("%s ", ctlr->keys.keys[i].dat);
  719. }
  720. PRINTSTR("\n");
  721. }
  722. // real card stats
  723. ilock(ctlr);
  724. PRINTSTR("\nCard stats: \n");
  725. PRINTSTAT("Status: %ux\n", csr_ins(ctlr, WR_Sts));
  726. PRINTSTAT("Event status: %ux\n", csr_ins(ctlr, WR_EvSts));
  727. i = ltv_ins(ctlr, WTyp_Ptype);
  728. PRINTSTAT("Port type: %d\n", i);
  729. PRINTSTAT("Transmit rate: %d\n", ltv_ins(ctlr, WTyp_TxRate));
  730. PRINTSTAT("Current Transmit rate: %d\n",
  731. ltv_ins(ctlr, WTyp_CurTxRate));
  732. PRINTSTAT("Channel: %d\n", ltv_ins(ctlr, WTyp_Chan));
  733. PRINTSTAT("AP density: %d\n", ltv_ins(ctlr, WTyp_ApDens));
  734. PRINTSTAT("Promiscuous mode: %d\n", ltv_ins(ctlr, WTyp_Prom));
  735. if(i == 3)
  736. PRINTSTAT("SSID name: %s\n", ltv_inname(ctlr, WTyp_NetName));
  737. else {
  738. Wltv ltv;
  739. PRINTSTAT("Current name: %s\n", ltv_inname(ctlr, WTyp_CurName));
  740. ltv.type = WTyp_BaseID;
  741. ltv.len = 4;
  742. if(w_inltv(ctlr, &ltv))
  743. print("#l%d: unable to read base station mac addr\n", ether->ctlrno);
  744. l += snprint(p+l, READSTR-l, "Base station: %2.2x%2.2x%2.2x%2.2x%2.2x%2.2x\n",
  745. ltv.addr[0], ltv.addr[1], ltv.addr[2], ltv.addr[3], ltv.addr[4], ltv.addr[5]);
  746. }
  747. PRINTSTAT("Net name: %s\n", ltv_inname(ctlr, WTyp_WantName));
  748. PRINTSTAT("Node name: %s\n", ltv_inname(ctlr, WTyp_NodeName));
  749. if(ltv_ins(ctlr, WTyp_HasCrypt) == 0)
  750. PRINTSTR("WEP: not supported\n");
  751. else {
  752. if(ltv_ins(ctlr, WTyp_Crypt) == 0)
  753. PRINTSTR("WEP: disabled\n");
  754. else{
  755. PRINTSTR("WEP: enabled\n");
  756. k = ((ctlr->xclear)? "excluded": "included");
  757. PRINTSTAT("Clear packets: %s\n", k);
  758. txid = ltv_ins(ctlr, WTyp_TxKey);
  759. PRINTSTAT("Transmit key id: %d\n", txid);
  760. }
  761. }
  762. iunlock(ctlr);
  763. PRINTSTAT("ntxuframes: %lud\n", ctlr->ntxuframes);
  764. PRINTSTAT("ntxmframes: %lud\n", ctlr->ntxmframes);
  765. PRINTSTAT("ntxfrags: %lud\n", ctlr->ntxfrags);
  766. PRINTSTAT("ntxubytes: %lud\n", ctlr->ntxubytes);
  767. PRINTSTAT("ntxmbytes: %lud\n", ctlr->ntxmbytes);
  768. PRINTSTAT("ntxdeferred: %lud\n", ctlr->ntxdeferred);
  769. PRINTSTAT("ntxsretries: %lud\n", ctlr->ntxsretries);
  770. PRINTSTAT("ntxmultiretries: %lud\n", ctlr->ntxmultiretries);
  771. PRINTSTAT("ntxretrylimit: %lud\n", ctlr->ntxretrylimit);
  772. PRINTSTAT("ntxdiscards: %lud\n", ctlr->ntxdiscards);
  773. PRINTSTAT("nrxuframes: %lud\n", ctlr->nrxuframes);
  774. PRINTSTAT("nrxmframes: %lud\n", ctlr->nrxmframes);
  775. PRINTSTAT("nrxfrags: %lud\n", ctlr->nrxfrags);
  776. PRINTSTAT("nrxubytes: %lud\n", ctlr->nrxubytes);
  777. PRINTSTAT("nrxmbytes: %lud\n", ctlr->nrxmbytes);
  778. PRINTSTAT("nrxfcserr: %lud\n", ctlr->nrxfcserr);
  779. PRINTSTAT("nrxdropnobuf: %lud\n", ctlr->nrxdropnobuf);
  780. PRINTSTAT("nrxdropnosa: %lud\n", ctlr->nrxdropnosa);
  781. PRINTSTAT("nrxcantdecrypt: %lud\n", ctlr->nrxcantdecrypt);
  782. PRINTSTAT("nrxmsgfrag: %lud\n", ctlr->nrxmsgfrag);
  783. PRINTSTAT("nrxmsgbadfrag: %lud\n", ctlr->nrxmsgbadfrag);
  784. USED(l);
  785. n = readstr(offset, a, n, p);
  786. free(p);
  787. return n;
  788. }
  789. #undef PRINTSTR
  790. #undef PRINTSTAT
  791. int
  792. w_option(Ctlr* ctlr, char* buf, long n)
  793. {
  794. char *p;
  795. int i, r;
  796. WKey *key;
  797. Cmdbuf *cb;
  798. r = 0;
  799. cb = parsecmd(buf, n);
  800. if(cb->nf < 2)
  801. r = -1;
  802. else if(cistrcmp(cb->f[0], "essid") == 0){
  803. if(cistrcmp(cb->f[1],"default") == 0)
  804. p = "";
  805. else
  806. p = cb->f[1];
  807. if(ctlr->ptype == 3){
  808. memset(ctlr->netname, 0, sizeof(ctlr->netname));
  809. strncpy(ctlr->netname, p, WNameLen);
  810. }
  811. else{
  812. memset(ctlr->wantname, 0, sizeof(ctlr->wantname));
  813. strncpy(ctlr->wantname, p, WNameLen);
  814. }
  815. }
  816. else if(cistrcmp(cb->f[0], "station") == 0){
  817. memset(ctlr->nodename, 0, sizeof(ctlr->nodename));
  818. strncpy(ctlr->nodename, cb->f[1], WNameLen);
  819. }
  820. else if(cistrcmp(cb->f[0], "channel") == 0){
  821. if((i = atoi(cb->f[1])) >= 1 && i <= 16)
  822. ctlr->chan = i;
  823. else
  824. r = -1;
  825. }
  826. else if(cistrcmp(cb->f[0], "mode") == 0){
  827. if(cistrcmp(cb->f[1], "managed") == 0)
  828. ctlr->ptype = WPTypeManaged;
  829. else if(cistrcmp(cb->f[1], "wds") == 0)
  830. ctlr->ptype = WPTypeWDS;
  831. else if(cistrcmp(cb->f[1], "adhoc") == 0)
  832. ctlr->ptype = WPTypeAdHoc;
  833. else if((i = atoi(cb->f[1])) >= 1 && i <= 3)
  834. ctlr->ptype = i;
  835. else
  836. r = -1;
  837. }
  838. else if(cistrcmp(cb->f[0], "ibss") == 0){
  839. if(cistrcmp(cb->f[1], "on") == 0)
  840. ctlr->createibss = 1;
  841. else
  842. ctlr->createibss = 0;
  843. }
  844. else if(cistrcmp(cb->f[0], "crypt") == 0){
  845. if(cistrcmp(cb->f[1], "off") == 0)
  846. ctlr->crypt = 0;
  847. else if(cistrcmp(cb->f[1], "on") == 0 && ctlr->hascrypt)
  848. ctlr->crypt = 1;
  849. else
  850. r = -1;
  851. }
  852. else if(cistrcmp(cb->f[0], "clear") == 0){
  853. if(cistrcmp(cb->f[1], "on") == 0)
  854. ctlr->xclear = 0;
  855. else if(cistrcmp(cb->f[1], "off") == 0 && ctlr->hascrypt)
  856. ctlr->xclear = 1;
  857. else
  858. r = -1;
  859. }
  860. else if(cistrncmp(cb->f[0], "key", 3) == 0){
  861. if((i = atoi(cb->f[0]+3)) >= 1 && i <= WNKeys){
  862. ctlr->txkey = i-1;
  863. key = &ctlr->keys.keys[ctlr->txkey];
  864. key->len = strlen(cb->f[1]);
  865. if(key->len > WKeyLen)
  866. key->len = WKeyLen;
  867. memset(key->dat, 0, sizeof(key->dat));
  868. memmove(key->dat, cb->f[1], key->len);
  869. }
  870. else
  871. r = -1;
  872. }
  873. else if(cistrcmp(cb->f[0], "txkey") == 0){
  874. if((i = atoi(cb->f[1])) >= 1 && i <= WNKeys)
  875. ctlr->txkey = i-1;
  876. else
  877. r = -1;
  878. }
  879. else if(cistrcmp(cb->f[0], "pm") == 0){
  880. if(cistrcmp(cb->f[1], "off") == 0)
  881. ctlr->pmena = 0;
  882. else if(cistrcmp(cb->f[1], "on") == 0){
  883. ctlr->pmena = 1;
  884. if(cb->nf == 3){
  885. i = atoi(cb->f[2]);
  886. // check range here? what are the units?
  887. ctlr->pmwait = i;
  888. }
  889. }
  890. else
  891. r = -1;
  892. }
  893. else
  894. r = -2;
  895. free(cb);
  896. return r;
  897. }
  898. long
  899. w_ctl(Ether* ether, void* buf, long n)
  900. {
  901. Ctlr *ctlr;
  902. if((ctlr = ether->ctlr) == nil)
  903. error(Enonexist);
  904. if((ctlr->state & Attached) == 0)
  905. error(Eshutdown);
  906. ilock(ctlr);
  907. if(w_option(ctlr, buf, n)){
  908. iunlock(ctlr);
  909. error(Ebadctl);
  910. }
  911. if(ctlr->txbusy)
  912. w_txdone(ctlr, WTxErrEv);
  913. w_enable(ether);
  914. w_txstart(ether);
  915. iunlock(ctlr);
  916. return n;
  917. }
  918. void
  919. w_transmit(Ether* ether)
  920. {
  921. Ctlr* ctlr = ether->ctlr;
  922. if(ctlr == 0)
  923. return;
  924. ilock(ctlr);
  925. ctlr->ntxrq++;
  926. w_txstart(ether);
  927. iunlock(ctlr);
  928. }
  929. void
  930. w_promiscuous(void* arg, int on)
  931. {
  932. Ether* ether = (Ether*)arg;
  933. Ctlr* ctlr = ether->ctlr;
  934. if(ctlr == nil)
  935. error("card not found");
  936. if((ctlr->state & Attached) == 0)
  937. error("card not attached");
  938. ilock(ctlr);
  939. ltv_outs(ctlr, WTyp_Prom, (on?1:0));
  940. iunlock(ctlr);
  941. }
  942. void
  943. w_interrupt(Ureg* ,void* arg)
  944. {
  945. Ether* ether = (Ether*) arg;
  946. Ctlr* ctlr = (Ctlr*) ether->ctlr;
  947. if(ctlr == 0)
  948. return;
  949. ilock(ctlr);
  950. ctlr->nints++;
  951. w_intr(ether);
  952. iunlock(ctlr);
  953. }
  954. int
  955. wavelanreset(Ether* ether, Ctlr *ctlr)
  956. {
  957. Wltv ltv;
  958. iprint("wavelanreset, iob 0x%ux\n", ctlr->iob);
  959. w_intdis(ctlr);
  960. if(w_cmd(ctlr,WCmdIni,0)){
  961. iprint("#l%d: init failed\n", ether->ctlrno);
  962. return -1;
  963. }
  964. w_intdis(ctlr);
  965. ltv_outs(ctlr, WTyp_Tick, 8);
  966. ctlr->chan = 0;
  967. ctlr->ptype = WDfltPType;
  968. ctlr->txkey = 0;
  969. ctlr->createibss = 0;
  970. ctlr->keys.len = sizeof(WKey)*WNKeys/2 + 1;
  971. ctlr->keys.type = WTyp_Keys;
  972. if(ctlr->hascrypt = ltv_ins(ctlr, WTyp_HasCrypt))
  973. ctlr->crypt = 1;
  974. *ctlr->netname = *ctlr->wantname = 0;
  975. strcpy(ctlr->nodename, "Plan 9 STA");
  976. ctlr->netname[WNameLen-1] = 0;
  977. ctlr->wantname[WNameLen-1] = 0;
  978. ctlr->nodename[WNameLen-1] =0;
  979. ltv.type = WTyp_Mac;
  980. ltv.len = 4;
  981. if(w_inltv(ctlr, &ltv)){
  982. iprint("#l%d: unable to read mac addr\n",
  983. ether->ctlrno);
  984. return -1;
  985. }
  986. memmove(ether->ea, ltv.addr, Eaddrlen);
  987. if(ctlr->chan == 0)
  988. ctlr->chan = ltv_ins(ctlr, WTyp_Chan);
  989. ctlr->apdensity = WDfltApDens;
  990. ctlr->rtsthres = WDfltRtsThres;
  991. ctlr->txrate = WDfltTxRate;
  992. ctlr->maxlen = WMaxLen;
  993. ctlr->pmena = 0;
  994. ctlr->pmwait = 100;
  995. ctlr->signal = 1;
  996. ctlr->noise = 1;
  997. ctlr->state |= Power;
  998. // free old Ctlr struct if resetting after suspend
  999. if(ether->ctlr && ether->ctlr != ctlr)
  1000. free(ether->ctlr);
  1001. // link to ether
  1002. ether->ctlr = ctlr;
  1003. ether->mbps = 10;
  1004. ether->attach = w_attach;
  1005. ether->detach = w_detach;
  1006. ether->interrupt = w_interrupt;
  1007. ether->transmit = w_transmit;
  1008. ether->ifstat = w_ifstat;
  1009. ether->ctl = w_ctl;
  1010. ether->power = w_power;
  1011. ether->promiscuous = w_promiscuous;
  1012. ether->multicast = w_multicast;
  1013. ether->arg = ether;
  1014. DEBUG("#l%d: irq %ld port %lx type %s",
  1015. ether->ctlrno, ether->irq, ether->port, ether->type);
  1016. DEBUG(" %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX\n",
  1017. ether->ea[0], ether->ea[1], ether->ea[2],
  1018. ether->ea[3], ether->ea[4], ether->ea[5]);
  1019. return 0;
  1020. }
  1021. char* wavenames[] = {
  1022. "WaveLAN/IEEE",
  1023. "TrueMobile 1150",
  1024. "Instant Wireless ; Network PC CARD",
  1025. "Instant Wireless Network PC Card",
  1026. "Avaya Wireless PC Card",
  1027. "AirLancer MC-11",
  1028. nil,
  1029. };