Annotation of sys/dev/ic/rln.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: rln.c,v 1.18 2006/03/25 22:41:43 djm Exp $ */
2: /*
3: * David Leonard <d@openbsd.org>, 1999. Public Domain.
4: *
5: * Driver for the Proxim RangeLAN2 wireless network adaptor.
6: *
7: * Information and ideas gleaned from disassembly of Dave Koberstein's
8: * <davek@komacke.com> Linux driver (apparently based on Proxim source),
9: * from Yoichi Shinoda's <shinoda@cs.washington.edu> BSDI driver, and
10: * Geoff Voelker's <voelker@cs.washington.edu> Linux port of the same.
11: *
12: */
13:
14: #include "bpfilter.h"
15:
16: #include <sys/param.h>
17: #include <sys/systm.h>
18: #include <sys/mbuf.h>
19: #include <sys/socket.h>
20: #include <sys/ioctl.h>
21: #include <sys/syslog.h>
22: #include <sys/device.h>
23: #include <sys/kernel.h>
24:
25: #include <net/if.h>
26: #include <net/if_media.h>
27:
28: #ifdef INET
29: #include <netinet/in.h>
30: #include <netinet/if_ether.h>
31: #endif
32:
33: #if NBPFILTER > 0
34: #include <net/bpf.h>
35: #endif
36:
37: #include <machine/bus.h>
38: #include <machine/intr.h>
39:
40: #include <dev/ic/rln.h>
41: #include <dev/ic/rlnvar.h>
42: #include <dev/ic/rlnreg.h>
43: #include <dev/ic/rlncmd.h>
44:
45: /* Autoconfig definition of driver back-end. */
46: struct cfdriver rln_cd = {
47: NULL, "rln", DV_IFNET
48: };
49:
50: void rlninit(struct rln_softc *);
51: void rlnstart(struct ifnet*);
52: void rlnwatchdog(struct ifnet*);
53: int rlnioctl(struct ifnet *, u_long, caddr_t);
54: void rlnstop(struct rln_softc *);
55:
56: /* Interrupt handler. */
57: void rlnsoftintr(void *);
58:
59: /* Packet I/O. */
60: int rln_transmit(struct rln_softc *, struct mbuf *,
61: int, int);
62: struct mbuf * rlnget(struct rln_softc *, struct rln_mm_cmd *,
63: int);
64:
65: /* Card protocol-level functions. */
66: int rln_getenaddr(struct rln_softc *, u_int8_t *);
67: int rln_getpromvers(struct rln_softc *, char *, int);
68: int rln_sendinit(struct rln_softc *);
69: #if notyet
70: int rln_roamconfig(struct rln_softc *);
71: int rln_roam(struct rln_softc *);
72: int rln_multicast(struct rln_softc *, int);
73: int rln_searchsync(struct rln_softc *);
74: int rln_iosetparam(struct rln_softc *, struct rln_param *);
75: int rln_lockprom(struct rln_softc *);
76: int rln_ito(struct rln_softc *);
77: int rln_standby(struct rln_softc *);
78: #endif
79:
80: /* Back-end attach and configure. Assumes card has been reset. */
81: void
82: rlnconfig(sc)
83: struct rln_softc * sc;
84: {
85: struct ifnet * ifp = &sc->sc_arpcom.ac_if;
86: char promvers[7];
87: int i;
88:
89: dprintf(" [attach %p]", sc);
90:
91: /* Use the flags supplied from config. */
92: sc->sc_cardtype |= sc->sc_dev.dv_cfdata->cf_flags;
93:
94: /* Initialise values in the soft state. */
95: sc->sc_pktseq = 0; /* rln_newseq() */
96: sc->sc_txseq = 0;
97: sc->sc_state = 0;
98:
99: /* Initialise user-configurable params. */
100: sc->sc_param.rp_roam_config = RLN_ROAM_NORMAL;
101: sc->sc_param.rp_security = RLN_SECURITY_DEFAULT;
102: sc->sc_param.rp_station_type = RLN_STATIONTYPE_ALTMASTER;
103: sc->sc_param.rp_domain = 0;
104: sc->sc_param.rp_channel = 1;
105: sc->sc_param.rp_subchannel = 1;
106:
107: bzero(sc->sc_param.rp_master, sizeof sc->sc_param.rp_master);
108:
109: /* Initialise the message mailboxes. */
110: for (i = 0; i < RLN_NMBOX; i++)
111: sc->sc_mbox[i].mb_state = RLNMBOX_VOID;
112:
113: /* Probe for some properties. */
114: printf(", %s-piece",
115: (sc->sc_cardtype & RLN_CTYPE_ONE_PIECE) ? "one" : "two");
116: if (sc->sc_cardtype & RLN_CTYPE_OEM)
117: printf(" oem");
118: if (sc->sc_cardtype & RLN_CTYPE_UISA)
119: printf(" micro-isa");
120:
121: /* Read the card's PROM revision. */
122: if (rln_getpromvers(sc, promvers, sizeof promvers)) {
123: printf(": could not read PROM version\n");
124: return;
125: }
126: printf(", fw %.7s", promvers);
127:
128: /* Fetch the card's MAC address. */
129: if (rln_getenaddr(sc, sc->sc_arpcom.ac_enaddr)) {
130: printf(": could not read MAC address\n");
131: return;
132: }
133: printf(", addr %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
134:
135: timeout_set(&sc->sc_timeout, rlnsoftintr, sc);
136:
137: /* Attach as a network interface. */
138: bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
139: ifp->if_softc = sc;
140: ifp->if_start = rlnstart;
141: ifp->if_ioctl = rlnioctl;
142: ifp->if_watchdog = rlnwatchdog;
143: ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
144: IFQ_SET_READY(&ifp->if_snd);
145: if_attach(ifp);
146: ether_ifattach(ifp);
147: }
148:
149: /* Bring device up. */
150: void
151: rlninit(sc)
152: struct rln_softc * sc;
153: {
154: /* LLDInit() */
155: struct ifnet * ifp = &sc->sc_arpcom.ac_if;
156: int s;
157:
158: s = splnet();
159: dprintf(" [init]");
160:
161: sc->sc_intsel = 0;
162: sc->sc_status = 0;
163: sc->sc_control = 0;
164: ifp->if_flags &= ~IFF_RUNNING;
165: ifp->if_flags &= ~IFF_OACTIVE;
166:
167: /* Do a hard reset. */
168: if (rln_reset(sc)) {
169: printf("%s: could not reset card\n", sc->sc_dev.dv_xname);
170: goto fail;
171: }
172: sc->sc_state = 0; /* Also clears RLN_STATE_NEEDINIT. */
173:
174: /* Use this host's name as a master name. */
175: if (!cold && sc->sc_param.rp_master[0] == '\0') {
176: bcopy(hostname, sc->sc_param.rp_master,
177: min(hostnamelen, sizeof sc->sc_param.rp_master));
178: }
179:
180: rln_enable(sc, 1);
181:
182: /* Initialise operational params. */
183: if (rln_sendinit(sc)) {
184: printf("%s: could not set card parameters\n",
185: sc->sc_dev.dv_xname);
186: goto fail;
187: }
188: #if 0
189: rln_roamconfig(sc);
190: /* rln_lockprom(sc); */
191: /* SendSetITO() */
192: rln_multicast(sc, 1);
193: rln_roam(sc);
194:
195: /* Synchronise with something. */
196: rln_searchsync(sc);
197: #endif
198: ifp->if_flags |= IFF_RUNNING;
199: rlnstart(ifp);
200: splx(s);
201:
202: return;
203:
204: fail:
205: ifp->if_flags &= ~IFF_UP;
206: splx(s);
207: return;
208: }
209:
210: /* Start outputting on interface. This is always called at splnet(). */
211: void
212: rlnstart(ifp)
213: struct ifnet * ifp;
214: {
215: struct rln_softc * sc = (struct rln_softc *)ifp->if_softc;
216: struct mbuf * m0;
217: int len, pad, ret, s;
218:
219: dprintf(" start[");
220:
221: if (sc->sc_state & RLN_STATE_NEEDINIT)
222: rlninit(sc);
223:
224: /* Don't transmit if interface is busy or not running. */
225: if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) {
226: dprintf(" %s] ", (ifp->if_flags & IFF_OACTIVE) ?
227: "busy" : "stopped");
228: return;
229: }
230:
231: /* Don't transmit if we are not synchronised. */
232: if ((sc->sc_state & RLN_STATE_SYNC) == 0) {
233: dprintf(" nosync]");
234: return;
235: }
236:
237: rln_enable(sc, 1);
238:
239: startagain:
240: s = splnet();
241: IFQ_DEQUEUE(&ifp->if_snd, m0);
242: splx(s);
243:
244: if (m0 == NULL) {
245: dprintf(" empty]");
246: return;
247: }
248:
249: #if NBPFILTER > 0
250: /* Tap packet stream here for BPF listeners. */
251: if (ifp->if_bpf)
252: bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
253: #endif
254:
255: /* We need to use m->m_pkthdr.len, so require the header. */
256: if ((m0->m_flags & M_PKTHDR) == 0) {
257: printf("%s: no mbuf header\n", sc->sc_dev.dv_xname);
258: goto oerror;
259: }
260:
261: len = m0->m_pkthdr.len;
262:
263: #define PACKETMIN (sizeof (struct ether_header) + ETHERMIN)
264: #define PACKETMAX (sizeof (struct ether_header) + ETHERMTU + 4)
265:
266: /* Packet size has to be an even number between 60 and 1518 octets. */
267: pad = len & 1;
268: if (len + pad < PACKETMIN)
269: pad = PACKETMIN - len;
270:
271: if (len + pad > PACKETMAX) {
272: printf("%s: packet too big (%d > %d)\n",
273: sc->sc_dev.dv_xname, len + pad,
274: PACKETMAX);
275: ++ifp->if_oerrors;
276: m_freem(m0);
277: goto startagain;
278: }
279:
280: ret = rln_transmit(sc, m0, len, pad);
281: if (ret)
282: goto oerror;
283:
284: ifp->if_flags |= IFF_OACTIVE;
285: m_freem(m0);
286:
287: dprintf(" sent]");
288: return;
289:
290: oerror:
291: ++ifp->if_oerrors;
292: m_freem(m0);
293: rln_need_reset(sc);
294: return;
295: }
296:
297: /* Transmit one packet. */
298: int
299: rln_transmit(sc, m0, len, pad)
300: struct rln_softc * sc;
301: struct mbuf * m0;
302: int len;
303: int pad;
304: {
305: struct mbuf * m;
306: int zfirst;
307: int actlen;
308: int tlen = len + pad;
309: struct rln_msg_tx_state state;
310: static u_int8_t zeroes[60];
311: struct rln_mm_sendpacket cmd = { RLN_MM_SENDPACKET };
312:
313: /* Does the packet start with a zero bit? */
314: zfirst = ((*mtod(m0, u_int8_t *) & 1) == 0);
315:
316: cmd.mode =
317: RLN_MM_SENDPACKET_MODE_BIT7 |
318: (zfirst ? RLN_MM_SENDPACKET_MODE_ZFIRST : 0) |
319: (0 ? RLN_MM_SENDPACKET_MODE_QFSK : 0), /* sc->qfsk? */
320: cmd.power = 0x70; /* 0x70 or 0xf0 */
321: cmd.length_lo = htons(4 + tlen) & 0xff;
322: cmd.length_hi = (htons(4 + tlen) >> 8) & 0xff;
323: cmd.xxx1 = 0;
324: cmd.xxx2 = 0;
325: cmd.xxx3 = 0;
326:
327: /* A unique packet-level sequence number, independent of sc_seq. */
328: cmd.sequence = sc->sc_txseq;
329: sc->sc_txseq++;
330: if (sc->sc_txseq > RLN_MAXSEQ)
331: sc->sc_txseq = 0;
332:
333: dprintf(" T[%d+%d", len, pad);
334:
335: if (rln_msg_tx_start(sc, &cmd, sizeof cmd + tlen, &state))
336: goto error;
337:
338: cmd.mm_cmd.cmd_seq = rln_newseq(sc);
339:
340: /* Send the SENDPACKET command header */
341: #ifdef RLNDUMP
342: printf("%s: send %c%d seq %d data ", sc->sc_dev.dv_xname,
343: cmd.mm_cmd.cmd_letter, cmd.mm_cmd.cmd_fn, cmd.mm_cmd.cmd_seq);
344: RLNDUMPHEX(&cmd, sizeof cmd);
345: printf(":");
346: #endif
347: rln_msg_tx_data(sc, &cmd, sizeof cmd, &state);
348:
349: /* XXX do we need to insert a hardware header here??? */
350:
351: /* Follow the header immediately with the packet payload */
352: actlen = 0;
353: for (m = m0; m; m = m->m_next) {
354: if (m->m_len) {
355: #ifdef RLNDUMP
356: RLNDUMPHEX(mtod(m, void *), m->m_len);
357: #endif
358: rln_msg_tx_data(sc, mtod(m, void *), m->m_len, &state);
359: }
360: if (m->m_next)
361: printf("|");
362: actlen += m->m_len;
363: }
364: #ifdef DIAGNOSTIC
365: if (actlen != len)
366: panic("rln_transmit: len %d != %d", actlen, len);
367: if (pad > sizeof zeroes)
368: panic("rln_transmit: pad %d > %d", pad, sizeof zeroes);
369: #endif
370: if (pad) {
371: #ifdef RLNDUMP
372: printf(":");
373: RLNDUMPHEX(zeroes, pad);
374: #endif
375: rln_msg_tx_data(sc, zeroes, pad, &state);
376: }
377:
378: #ifdef RLNDUMP
379: printf("\n");
380: #endif
381: if (rln_msg_tx_end(sc, &state))
382: goto error;
383: return (0);
384:
385: error:
386: dprintf(" error]");
387: return (-1);
388: }
389:
390: /* (Supposedly) called when interrupts are suspiciously absent. */
391: void
392: rlnwatchdog(ifp)
393: struct ifnet * ifp;
394: {
395: struct rln_softc * sc = (struct rln_softc *)ifp->if_softc;
396:
397: log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
398: ++sc->sc_arpcom.ac_if.if_oerrors;
399: rlninit(sc);
400: rln_enable(sc, 1);
401: }
402:
403: /* Handle single card interrupt. */
404: int
405: rlnintr(arg)
406: void * arg;
407: {
408: struct rln_softc * sc = (struct rln_softc *)arg;
409:
410: dprintf("!");
411:
412: /* Tell card not to interrupt any more. */
413: rln_enable(sc, 0);
414:
415: if (cold)
416: /* During autoconfig - must handle interrupts now. */
417: rlnsoftintr(sc);
418: else
419: /* Handle later. */
420: timeout_add(&sc->sc_timeout, 1);
421:
422: return (1);
423: }
424:
425: /* Process earlier card interrupt at splsoftnet. */
426: void
427: rlnsoftintr(arg)
428: void * arg;
429: {
430: struct rln_softc *sc = (struct rln_softc *)arg;
431: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
432: int len;
433: u_int8_t w;
434: struct rln_mm_cmd hdr;
435: int s;
436:
437: s = splsoftnet();
438: dprintf(" si(");
439:
440: again:
441: /* Save wakeup state. */
442: w = rln_wakeup(sc, RLN_WAKEUP_SET);
443:
444: if ((len = rln_rx_request(sc, 300)) < 0) {
445: /* Error in transfer. */
446: rln_need_reset(sc);
447: rln_rx_end(sc);
448: } else if (len < sizeof hdr) {
449: /* Short message. */
450: rln_rx_end(sc);
451: printf("%s: short msg (%d)\n", sc->sc_dev.dv_xname, len);
452: ifp->if_ierrors++;
453: } else {
454: /* Valid message: read header and process. */
455: rln_rx_data(sc, &hdr, sizeof hdr);
456: rlnread(sc, &hdr, len);
457: }
458:
459: /* Ensure that wakeup state is unchanged if transmitting. */
460: if (ifp->if_flags & IFF_OACTIVE)
461: w |= RLN_WAKEUP_NOCHANGE;
462: rln_wakeup(sc, w);
463:
464: /* Check for more interrupts. */
465: if ((sc->sc_state & RLN_STATE_NEEDINIT) == 0 &&
466: rln_status_rx_ready(sc)) {
467: if (rln_status_rx_read(sc) == RLN_STATUS_RX_ERROR) {
468: #ifdef DIAGNOSTIC
469: printf("%s: protocol error\n", sc->sc_dev.dv_xname);
470: #endif
471: DELAY(100 * 1000); /* Woah, baby. */
472: rln_clear_nak(sc);
473: } else {
474: #ifdef DIAGNOSTIC
475: printf("%s: intr piggyback\n", sc->sc_dev.dv_xname);
476: #endif
477: goto again;
478: }
479: }
480:
481: rln_eoi(sc);
482: rln_enable(sc, 1);
483:
484: dprintf(")");
485: splx(s);
486: }
487:
488: /* Read and process a message from the card. */
489: void
490: rlnread(sc, hdr, len)
491: struct rln_softc *sc;
492: struct rln_mm_cmd *hdr;
493: int len;
494: {
495: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
496: struct mbuf *m;
497: u_int8_t data[1538];
498: u_int8_t *buf;
499: size_t buflen;
500: struct rln_pdata pd = RLN_PDATA_INIT;
501: struct rln_mm_synchronised * syncp = (struct rln_mm_synchronised *)data;
502: int s;
503:
504: dprintf(" [read]");
505:
506: /* Were we waiting for this message? */
507: if (rln_mbox_lock(sc, hdr->cmd_seq, (void **)&buf, &buflen) == 0) {
508: #ifdef DIAGNOSTIC
509: if (buflen < sizeof *hdr)
510: panic("rlnread buflen");
511: #endif
512: bcopy(hdr, buf, sizeof *hdr);
513: buf += sizeof *hdr;
514: len -= sizeof *hdr;
515: buflen -= sizeof *hdr;
516: if (len) {
517: if (len == buflen) /* Expected size */
518: rln_rx_pdata(sc, buf, len, &pd);
519: else if (len < buflen) { /* Underfill */
520: #ifdef DIAGNOSTIC
521: printf("%s: underfill %d<%d, cmd %c%d\n",
522: sc->sc_dev.dv_xname,
523: len, buflen,
524: hdr->cmd_letter, hdr->cmd_fn);
525: #endif
526: rln_rx_pdata(sc, buf, len, &pd);
527: } else { /* Overflow */
528: #ifdef DIAGNOSTIC
529: printf("%s: overflow %d>%d, cmd %c%d\n",
530: sc->sc_dev.dv_xname,
531: len, buflen,
532: hdr->cmd_letter, hdr->cmd_fn);
533: #endif
534: rln_rx_pdata(sc, buf, buflen, &pd);
535: /* Drain the rest somewhere. */
536: rln_rx_pdata(sc, data, len - buflen, &pd);
537: }
538: }
539: rln_rx_end(sc);
540:
541: /* This message can now be handled by the waiter. */
542: rln_mbox_unlock(sc, hdr->cmd_seq, len + sizeof *hdr);
543: return;
544: }
545:
546: /* Otherwise, handle the message, right here, right now. */
547:
548: /* Check if we can cope with the size of this message. */
549: if (len > sizeof data) {
550: printf("%s: msg too big (%d)\n", sc->sc_dev.dv_xname, len);
551: ifp->if_ierrors++;
552: rln_rx_end(sc);
553: /* rln_need_reset(sc); */
554: return;
555: }
556:
557: /* Check for error results. */
558: if (hdr->cmd_error & 0x80) {
559: printf("%s: command error 0x%02x command %c%d len=%d\n",
560: sc->sc_dev.dv_xname,
561: hdr->cmd_error & ~0x80,
562: hdr->cmd_letter, hdr->cmd_fn,
563: len);
564: ifp->if_ierrors++;
565: rln_rx_end(sc);
566: rln_need_reset(sc);
567: return;
568: }
569:
570: /*
571: * "b1": Receiving a packet is a special case.
572: * We wish to read the data with pio straight into an
573: * mbuf to avoid a memory-memory copy.
574: */
575: if (hdr->cmd_letter == 'b' && hdr->cmd_fn == 1) {
576: m = rlnget(sc, hdr, len);
577: rln_rx_end(sc);
578: if (m == NULL)
579: return;
580: ifp->if_ipackets++;
581: #ifdef DIAGNOSTIC
582: if (bcmp(mtod(m, u_int8_t *), "prox", 4) == 0) {
583: printf("%s: proxim special packet received\n",
584: sc->sc_dev.dv_xname);
585: }
586: #endif
587:
588: #if NBPFILTER > 0
589: if (ifp->if_bpf)
590: bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
591: #endif
592:
593: ether_input_mbuf(ifp, m);
594: return;
595: }
596:
597:
598: /* Otherwise we read the packet into a buffer on the stack. */
599: bcopy(hdr, data, sizeof *hdr);
600: if (len > sizeof *hdr)
601: rln_rx_pdata(sc, data + sizeof *hdr, len - sizeof *hdr, &pd);
602: rln_rx_end(sc);
603:
604: #ifdef RLNDUMP
605: printf("%s: recv %c%d seq %d data ", sc->sc_dev.dv_xname,
606: hdr->cmd_letter, hdr->cmd_fn, hdr->cmd_seq);
607: RLNDUMPHEX(hdr, sizeof hdr);
608: printf(":");
609: RLNDUMPHEX(data + sizeof hdr, len - sizeof hdr);
610: printf("\n");
611: #endif
612:
613: switch (RLN_MM_CMD(hdr->cmd_letter, hdr->cmd_fn)) {
614: case RLN_MM_CMD('b', 0): /* b0: Transmit done. */
615: #ifdef DIAGNOSTIC
616: if (len != 7)
617: printf("%s: 'b0' len %d != 7\n",
618: sc->sc_dev.dv_xname, len);
619: #endif
620: ifp->if_flags &= ~IFF_OACTIVE;
621: ifp->if_opackets++;
622: s = splnet();
623: rlnstart(ifp);
624: splx(s);
625: break;
626:
627: case RLN_MM_CMD('a', 20): /* a20: Card fault. */
628: printf("%s: hardware fault\n", sc->sc_dev.dv_xname);
629: break;
630:
631: case RLN_MM_CMD('a', 4): /* a4: Sync'd. */
632: if (bcmp(syncp->enaddr, sc->sc_arpcom.ac_enaddr,
633: ETHER_ADDR_LEN) == 0) {
634: /* Sync'd to own enaddr. */
635: /*
636: * From http://www.proxim.com/support/faq/7400.shtml
637: * 3. RLNSETUP reports that I'm synchronized to my own MAC address. What
638: * does that mean?
639: * You are the acting Master for this network. Either you are
640: * configured as the Master or as an Alternate Master. If you are an
641: * Alternate Master, you may be out of range or on a different Domain
642: * and Security ID from the true Master.
643: */
644:
645: printf("%s: nothing to sync to; now master ",
646: sc->sc_dev.dv_xname);
647: }
648: else
649: printf("%s: synchronised to ", sc->sc_dev.dv_xname);
650: printf("%.11s (%s) channel %d/%d\n",
651: syncp->mastername,
652: ether_sprintf(syncp->enaddr),
653: syncp->channel,
654: syncp->subchannel);
655:
656: /* Record the new circumstances. */
657: sc->sc_param.rp_channel = syncp->channel;
658: sc->sc_param.rp_subchannel = syncp->subchannel;
659: sc->sc_state |= RLN_STATE_SYNC;
660:
661: /* Resume sending. */
662: s = splnet();
663: rlnstart(ifp);
664: splx(s);
665: break;
666:
667: case RLN_MM_CMD('a', 5): /* a4: Lost sync. */
668: printf("%s: lost sync\n", sc->sc_dev.dv_xname);
669: sc->sc_state &= ~RLN_STATE_SYNC;
670: break;
671:
672: case RLN_MM_CMD('a', 18): /* a18: Roaming. */
673: printf("%s: roaming\n", sc->sc_dev.dv_xname);
674: break;
675: default:
676: #ifdef DIAGNOSTIC
677: printf("%s: msg `%c%d' seq %d data {",
678: sc->sc_dev.dv_xname,
679: hdr->cmd_letter, hdr->cmd_fn, hdr->cmd_seq);
680: RLNDUMPHEX(hdr, sizeof hdr);
681: printf(":");
682: RLNDUMPHEX(data, len);
683: printf("}\n");
684: #endif
685: break;
686: }
687:
688: }
689:
690: /* Extract a received network packet from the card. */
691: struct mbuf *
692: rlnget(sc, hdr, totlen)
693: struct rln_softc *sc;
694: struct rln_mm_cmd *hdr;
695: int totlen;
696: {
697: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
698: int len;
699: int pad;
700: struct mbuf *m, **mp, *top;
701: struct rln_pdata pd = RLN_PDATA_INIT;
702: struct {
703: u_int8_t rssi;
704: u_int8_t xxx1; /* always 00? */
705: u_int16_t len; /* payload length */
706: u_int8_t xxx2; /* always 00? */
707: u_int8_t xxx3; /* always c0? */
708: u_int8_t seq;
709: u_int8_t xxx4;
710: struct ether_addr to; /* destination station addr */
711: struct ether_addr from; /* sending station addr */
712: } hwhdr;
713:
714: dprintf(" [get]");
715:
716: #ifdef RLNDUMP
717: /* Decode the command header: */
718: printf("%s: recv %c%d seq %d data ", sc->sc_dev.dv_xname,
719: hdr->cmd_letter, hdr->cmd_fn, hdr->cmd_seq);
720: RLNDUMPHEX(hdr, sizeof hdr);
721: printf(":");
722: #endif
723: totlen -= sizeof *hdr;
724:
725: #ifdef DIAGNOSTIC
726: if (totlen <= 0) {
727: printf("%s: empty packet", sc->sc_dev.dv_xname);
728: goto drop;
729: }
730: #endif
731:
732: /* Decode the hardware header: */
733: rln_rx_pdata(sc, &hwhdr, sizeof hwhdr, &pd);
734: totlen -= sizeof hwhdr;
735: #ifdef RLNDUMP
736: RLNDUMPHEX(&hwhdr, sizeof hwhdr);
737: printf("/");
738: #endif
739: /* (Most of the following code fleeced from elink3.c.) */
740:
741: MGETHDR(m, M_DONTWAIT, MT_DATA);
742: if (m == NULL)
743: goto drop;
744: m->m_pkthdr.rcvif = ifp;
745: m->m_pkthdr.len = totlen;
746: /*
747: * Insert some leading padding in the mbuf, so that payload data is
748: * aligned.
749: */
750: pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
751: m->m_data += pad;
752: len = MHLEN - pad;
753: top = 0;
754: mp = ⊤
755:
756: while (totlen > 0) {
757: if (top) {
758: MGET(m, M_DONTWAIT, MT_DATA);
759: if (m == NULL) {
760: m_freem(top);
761: goto drop;
762: }
763: len = MLEN;
764: }
765: if (totlen >= MINCLSIZE) {
766: MCLGET(m, M_DONTWAIT);
767: if (m->m_flags & M_EXT) {
768: len = MCLBYTES;
769: if (!top) {
770: m->m_data += pad;
771: len -= pad;
772: }
773: }
774: }
775: len = min(totlen, len);
776: rln_rx_pdata(sc, mtod(m, u_int8_t *), len, &pd);
777: #ifdef RLNDUMP
778: RLNDUMPHEX(mtod(m, u_int8_t *), len);
779: if (totlen != len)
780: printf("|");
781: #endif
782: m->m_len = len;
783: totlen -= len;
784: *mp = m;
785: mp = &m->m_next;
786: }
787: #ifdef RLNDUMP
788: printf("\n");
789: #endif
790: return top;
791:
792: drop:
793: #ifdef RLNDUMP
794: printf(": drop\n");
795: #endif
796: ifp->if_iqdrops++;
797: return NULL;
798: }
799:
800: /* Interface control. */
801: int
802: rlnioctl(ifp, cmd, data)
803: struct ifnet *ifp;
804: u_long cmd;
805: caddr_t data;
806: {
807: struct rln_softc *sc = ifp->if_softc;
808: struct ifaddr *ifa = (struct ifaddr *)data;
809: int s, error;
810: int need_init;
811:
812: printf("%s: ioctl cmd[%c/%d] data=%x\n", sc->sc_dev.dv_xname,
813: IOCGROUP(cmd), IOCBASECMD(cmd), data);
814:
815: s = splnet();
816: if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) != 0) {
817: splx(s);
818: return error;
819: }
820:
821: switch (cmd) {
822: case SIOCSIFADDR:
823: /* Set address. */
824: ifp->if_flags |= IFF_UP;
825:
826: switch (ifa->ifa_addr->sa_family) {
827: #ifdef INET
828: case AF_INET:
829: rlninit(sc);
830: arp_ifinit(&sc->sc_arpcom, ifa);
831: break;
832: #endif
833: default:
834: rlninit(sc);
835: break;
836: }
837: break;
838:
839: case SIOCSIFFLAGS:
840: need_init = 0;
841:
842: if ((ifp->if_flags & IFF_UP) == 0 &&
843: (ifp->if_flags & IFF_RUNNING) != 0) {
844: /* Was running, want down: stop. */
845: rlnstop(sc);
846: } else if ((ifp->if_flags & IFF_UP) != 0 &&
847: (ifp->if_flags & IFF_RUNNING) == 0) {
848: /* Was not running, want up: start. */
849: need_init = 1;
850: }
851:
852: if (ifp->if_flags & IFF_RUNNING) {
853: if ((ifp->if_flags & IFF_PROMISC) &&
854: (sc->sc_state & RLN_STATE_PROMISC) == 0) {
855: sc->sc_state |= RLN_STATE_PROMISC;
856: need_init = 1;
857: }
858: else if ((ifp->if_flags & IFF_PROMISC) == 0 &&
859: (sc->sc_state & RLN_STATE_PROMISC)) {
860: sc->sc_state &= ~RLN_STATE_PROMISC;
861: need_init = 1;
862: }
863: }
864:
865: if (need_init)
866: rlninit(sc);
867:
868: break;
869:
870: case SIOCADDMULTI:
871: case SIOCDELMULTI:
872: error = EOPNOTSUPP;
873: break;
874:
875: #if notyet
876: case RLNIOSPARAM:
877: error = rln_iosetparam(sc, (struct rln_param *)&data);
878: break;
879:
880: case RLNIOGPARAM:
881: bcopy(&sc->sc_param, (struct rln_param *)&data,
882: sizeof sc->sc_param);
883: break;
884: #endif
885:
886: default:
887: error = EINVAL;
888: break;
889: }
890:
891: splx(s);
892: return (error);
893: }
894:
895: /* Stop output from the card. */
896: void
897: rlnstop(sc)
898: struct rln_softc *sc;
899: {
900: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
901:
902: dprintf(" [stop]");
903: ifp->if_flags &= ~IFF_RUNNING;
904: rln_enable(sc, 0);
905: }
906:
907: /* Get MAC address from card. */
908: int
909: rln_getenaddr(sc, enaddr)
910: struct rln_softc *sc;
911: u_int8_t * enaddr;
912: {
913: struct rln_mm_cmd query = RLN_MM_GETENADDR;
914: struct rln_mm_gotenaddr response = { RLN_MM_GETENADDR };
915:
916: if (rln_msg_txrx(sc, &query, sizeof query,
917: &response, sizeof response))
918: return (-1);
919: bcopy(response.enaddr, enaddr, sizeof response.enaddr);
920: return (0);
921: };
922:
923: /* Get firmware version string from card. */
924: int
925: rln_getpromvers(sc, ver, verlen)
926: struct rln_softc *sc;
927: char *ver;
928: int verlen;
929: {
930: struct rln_mm_cmd query = RLN_MM_GETPROMVERSION;
931: struct rln_mm_gotpromversion response = { RLN_MM_GOTPROMVERSION };
932: int i;
933:
934: #ifdef DIAGNOSTIC
935: if (verlen != sizeof response.version)
936: panic("rln_getpromvers");
937: #endif
938:
939: if (rln_msg_txrx(sc, &query, sizeof query,
940: &response, sizeof response))
941: return (-1);
942: bcopy(response.version, ver, verlen);
943: /* Nul trailing spaces. */
944: for (i = verlen - 1; i >= 0 && ver[i] <= ' '; i--)
945: ver[i] = '\0';
946: return (0);
947: };
948:
949: /* Set default operational parameters on card. */
950: int
951: rln_sendinit(sc)
952: struct rln_softc *sc;
953: {
954: struct rln_mm_init init = { RLN_MM_INIT };
955: struct rln_mm_initted iresponse;
956: #if 0
957: struct rln_mm_setmagic magic = { RLN_MM_SETMAGIC };
958: struct rln_mm_disablehopping hop = { RLN_MM_DISABLEHOPPING };
959: struct rln_mm_cmd response;
960: #endif
961:
962: bzero((char *)&init + sizeof init.mm_cmd,
963: sizeof init - sizeof init.mm_cmd);
964:
965: dprintf(" [setting parameters]");
966: init.opmode = (sc->sc_state & RLN_STATE_PROMISC ?
967: RLN_MM_INIT_OPMODE_PROMISC : RLN_MM_INIT_OPMODE_NORMAL);
968: init.stationtype = sc->sc_param.rp_station_type;
969:
970: /* Spread-spectrum frequency hopping. */
971: init.hop_period = 1;
972: init.bfreq = 2;
973: init.sfreq = 7;
974:
975: /* Choose channel. */
976: init.channel = sc->sc_param.rp_channel;
977: init.subchannel = sc->sc_param.rp_subchannel;
978: init.domain = sc->sc_param.rp_domain;
979:
980: /* Name of this station when acting as master. */
981: bcopy(sc->sc_param.rp_master, init.mastername, sizeof init.mastername);
982:
983: /* Security params. */
984: init.sec1 = (sc->sc_param.rp_security & 0x0000ff) >> 0;
985: init.sec2 = (sc->sc_param.rp_security & 0x00ff00) >> 8;
986: init.sec3 = (sc->sc_param.rp_security & 0xff0000) >> 16;
987:
988: init.sync_to = 1;
989: bzero(init.syncname, sizeof init.syncname);
990:
991: if (rln_msg_txrx(sc, &init, sizeof init,
992: &iresponse, sizeof iresponse))
993: return (-1);
994: #if 0
995: dprintf(" [setting magic]");
996: magic.fairness_slot = 3; /* lite: 1, norm: 3, off: -1 */
997: magic.deferral_slot = 3; /* lite: 0, norm: 3, off: -1 */
998: magic.regular_mac_retry = 7;
999: magic.frag_mac_retry = 10;
1000: magic.regular_mac_qfsk = 2;
1001: magic.frag_mac_qfsk = 5;
1002: magic.xxx1 = 0xff;
1003: magic.xxx2 = 0xff;
1004: magic.xxx3 = 0xff;
1005: magic.xxx4 = 0x00;
1006: if (rln_msg_txrx(sc, &magic, sizeof magic,
1007: &response, sizeof response))
1008: return (-1);
1009:
1010: dprintf(" [disabling freq hopping]");
1011: hop.hopflag = RLN_MM_DISABLEHOPPING_HOPFLAG_DISABLE;
1012: if (rln_msg_txrx(sc, &hop, sizeof hop,
1013: &response, sizeof response))
1014: return (-1);
1015:
1016: #endif
1017: return (0);
1018: }
1019:
1020: #if notyet
1021: /* Configure the way the card leaves a basestation. */
1022: int
1023: rln_roamconfig(sc)
1024: struct rln_softc *sc;
1025: {
1026: struct rln_mm_setroaming roam = { RLN_MM_SETROAMING };
1027: struct rln_mm_cmd response;
1028: static int retry[3] = { 6, 6, 4 };
1029: static int rssi[3] = { 5, 15, 5 };
1030:
1031: dprintf(" [roamconfig]");
1032: #ifdef DIAGNOSTIC
1033: if (sc->sc_param.rp_roam_config > 2)
1034: panic("roamconfig");
1035: #endif
1036: roam.sync_alarm = 0;
1037: roam.retry_thresh = retry[sc->sc_param.rp_roam_config];
1038: roam.rssi_threshold = rssi[sc->sc_param.rp_roam_config];
1039: roam.xxx1 = 0x5a;
1040: roam.sync_rssi_threshold = 0;
1041: roam.xxx2 = 0x5a;
1042: roam.missed_sync = 0x4;
1043: if (rln_msg_txrx(sc, &roam, sizeof roam,
1044: &response, sizeof response))
1045: return (-1);
1046:
1047: return (0);
1048: }
1049:
1050: /* Enable roaming. */
1051: int
1052: rln_roam(sc)
1053: struct rln_softc *sc;
1054: {
1055: struct rln_mm_cmd roam = RLN_MM_ROAM;
1056: struct rln_mm_cmd response;
1057:
1058: return (rln_msg_txrx(sc, &roam, sizeof roam,
1059: &response, sizeof response));
1060: }
1061:
1062: /* Enable multicast capability. */
1063: int
1064: rln_multicast(sc, enable)
1065: struct rln_softc *sc;
1066: int enable;
1067: {
1068: struct ifnet *ifp = &sc->sc_arpcom.ac_if;
1069: struct rln_mm_multicast mcast = { RLN_MM_MULTICAST };
1070: struct rln_mm_cmd response;
1071: int ret;
1072:
1073: mcast.enable = enable;
1074:
1075: ret = rln_msg_txrx(sc, &mcast, sizeof mcast,
1076: &response, sizeof response);
1077: if (ret == 0) {
1078: if (enable)
1079: ifp->if_flags |= IFF_MULTICAST;
1080: else
1081: ifp->if_flags &= ~IFF_MULTICAST;
1082: }
1083: return (ret);
1084: }
1085:
1086: /* Search for and sync with any master. */
1087: int
1088: rln_searchsync(sc)
1089: struct rln_softc *sc;
1090: {
1091: struct rln_mm_search search = { RLN_MM_SEARCH };
1092: struct rln_mm_searching response;
1093:
1094: bzero(search.xxx1, sizeof search.xxx1);
1095: search.domain = sc->sc_param.rp_domain;
1096: search.roaming = 1;
1097: search.xxx3 = 0;
1098: search.xxx4 = 1;
1099: search.xxx5 = 0;
1100: bzero(search.xxx6, sizeof search.xxx6);
1101:
1102: return (rln_msg_txrx(sc, &search, sizeof search,
1103: &response, sizeof response));
1104: }
1105:
1106: /* Set values from an external parameter block. */
1107: int
1108: rln_iosetparam(sc, param)
1109: struct rln_softc *sc;
1110: struct rln_param *param;
1111: {
1112: int error = 0;
1113:
1114: if (param->rp_roam_config > 2)
1115: error = EINVAL;
1116: if (param->rp_security > 0x00ffffff)
1117: error = EINVAL;
1118: if (param->rp_station_type > 2)
1119: error = EINVAL;
1120: if (param->rp_channel > 15)
1121: error = EINVAL;
1122: if (param->rp_subchannel > 15)
1123: error = EINVAL;
1124: if (error == 0) {
1125: /* Apply immediately. */
1126: bcopy(param, &sc->sc_param, sizeof *param);
1127: if (rln_sendinit(sc))
1128: error = EIO;
1129: }
1130: return (error);
1131: }
1132:
1133: /* Protect the eeprom from storing a security ID(?) */
1134: int
1135: rln_lockprom(sc)
1136: struct rln_softc *sc;
1137: {
1138: struct rln_mm_cmd lock = RLN_MM_EEPROM_PROTECT;
1139: struct rln_mm_cmd response;
1140:
1141: /* XXX Always yields an error? */
1142: return (rln_msg_txrx(sc, &lock, sizeof lock,
1143: &response, sizeof response));
1144: }
1145:
1146: /* Set the h/w Inactivity Time Out timer on the card. */
1147: int
1148: rln_ito(sc)
1149: struct rln_softc * sc;
1150: {
1151: struct rln_mm_setito ito = { RLN_MM_MULTICAST };
1152: struct rln_mm_cmd response;
1153:
1154: ito.xxx = 3;
1155: ito.timeout = LLDInactivityTimeOut /* enabler, 0 or 1 */;
1156: ito.bd_wakeup = LLDBDWakeup /* 0 */;
1157: ito.pm_sync = LLDPMSync /* 0 */;
1158: ito.sniff_time = ito.timeout ? LLDSniffTime /* 0 */ : 0;
1159:
1160: if (rln_msg_txrx(sc, &ito, sizeof ito,
1161: &response, sizeof response))
1162: return (-1);
1163: }
1164:
1165: /* Put the card into standby mode. */
1166: int
1167: rln_standby(sc)
1168: struct rln_softc * sc;
1169: {
1170: struct rln_mm_standby standby = { RLN_MM_STANDBY };
1171:
1172: standby.xxx = 0;
1173: if (rln_msg_txrx(sc, &ito, sizeof ito, NULL, 0))
1174: return (-1);
1175: }
1176:
1177: void
1178: rln_crypt(userkey, cardkey)
1179: char *userkey; /* User's string (max 20 chars). */
1180: u_int8_t *cardkey; /* 20 bits (3 bytes) */
1181: {
1182: /*
1183: * From <http://www.proxim.com/learn/whiteppr/rl2security.shtml>
1184: * "RangeLAN2 Security Features":
1185: *
1186: * The Security ID is a unique, 20 character alphanumeric
1187: * string defined and configured by the user. It must be
1188: * identically configured in every radio intended to
1189: * communicate with others in the same network. Once
1190: * configured, the Security ID is reduced to 20 bits by a
1191: * proprietary algorithm confidential to Proxim. It is
1192: * merged with the radio MAC address (a 12 character field
1193: * unique to every radio), scrambled and stored using another
1194: * proprietary, confidential algorithm.
1195: */
1196: int32_t key;
1197: int8_t ret;
1198: int i;
1199: int len;
1200: int32_t multiplicand = 0x80000181;
1201: int64_t res;
1202:
1203: /*
1204: * This algorithm is `compatible' with Proxim's first
1205: * `proprietary confidential algorithm': i.e., it appears
1206: * to be functionally identical.
1207: */
1208: len = strlen(s);
1209: key = 0x030201;
1210: for (i = 0; i < len; i++) {
1211:
1212: key *= userkey[i];
1213: res = (int64_t)multiplicand * key;
1214: key = key - 0xfffffd *
1215: (((key + (int32_t)(res >> 32)) >> 23) - (key >> 31));
1216: }
1217:
1218: cardkey[0] = (key >> 16) & 0xff;
1219: cardkey[1] = (key >> 8) & 0xff;
1220: cardkey[2] = key & 0xff;
1221:
1222: cardkey[0] |= 0x03; /* Restrict key space by 2 bits. */
1223: }
1224: #endif
CVSweb