1 /* $OpenBSD: rln.c,v 1.16 2004/05/12 06:35:10 tedu 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
rlnconfig(sc)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
rlninit(sc)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
rlnstart(ifp)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 = splimp();
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);
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
rln_transmit(sc,m0,len,pad)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
rlnwatchdog(ifp)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
rlnintr(arg)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
rlnsoftintr(arg)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
rlnread(sc,hdr,len)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);
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 *
rlnget(sc,hdr,totlen)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
rlnioctl(ifp,cmd,data)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
rlnstop(sc)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
rln_getenaddr(sc,enaddr)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
rln_getpromvers(sc,ver,verlen)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
rln_sendinit(sc)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
rln_roamconfig(sc)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
rln_roam(sc)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
rln_multicast(sc,enable)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
rln_searchsync(sc)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
rln_iosetparam(sc,param)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
rln_lockprom(sc)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
rln_ito(sc)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
rln_standby(sc)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
rln_crypt(userkey,cardkey)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
1225