This source file includes following definitions.
- rlnconfig
- rlninit
- rlnstart
- rln_transmit
- rlnwatchdog
- rlnintr
- rlnsoftintr
- rlnread
- rlnget
- rlnioctl
- rlnstop
- rln_getenaddr
- rln_getpromvers
- rln_sendinit
- rln_roamconfig
- rln_roam
- rln_multicast
- rln_searchsync
- rln_iosetparam
- rln_lockprom
- rln_ito
- rln_standby
- rln_crypt
1
2
3
4
5
6
7
8
9
10
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
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
57 void rlnsoftintr(void *);
58
59
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
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
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
92 sc->sc_cardtype |= sc->sc_dev.dv_cfdata->cf_flags;
93
94
95 sc->sc_pktseq = 0;
96 sc->sc_txseq = 0;
97 sc->sc_state = 0;
98
99
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
110 for (i = 0; i < RLN_NMBOX; i++)
111 sc->sc_mbox[i].mb_state = RLNMBOX_VOID;
112
113
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
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
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
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
150 void
151 rlninit(sc)
152 struct rln_softc * sc;
153 {
154
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
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;
173
174
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
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
191
192 rln_multicast(sc, 1);
193 rln_roam(sc);
194
195
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
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
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
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
251 if (ifp->if_bpf)
252 bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
253 #endif
254
255
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
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
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
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),
320 cmd.power = 0x70;
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
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
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
350
351
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
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
404 int
405 rlnintr(arg)
406 void * arg;
407 {
408 struct rln_softc * sc = (struct rln_softc *)arg;
409
410 dprintf("!");
411
412
413 rln_enable(sc, 0);
414
415 if (cold)
416
417 rlnsoftintr(sc);
418 else
419
420 timeout_add(&sc->sc_timeout, 1);
421
422 return (1);
423 }
424
425
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
442 w = rln_wakeup(sc, RLN_WAKEUP_SET);
443
444 if ((len = rln_rx_request(sc, 300)) < 0) {
445
446 rln_need_reset(sc);
447 rln_rx_end(sc);
448 } else if (len < sizeof hdr) {
449
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
455 rln_rx_data(sc, &hdr, sizeof hdr);
456 rlnread(sc, &hdr, len);
457 }
458
459
460 if (ifp->if_flags & IFF_OACTIVE)
461 w |= RLN_WAKEUP_NOCHANGE;
462 rln_wakeup(sc, w);
463
464
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);
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
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
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)
518 rln_rx_pdata(sc, buf, len, &pd);
519 else if (len < buflen) {
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 {
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
536 rln_rx_pdata(sc, data, len - buflen, &pd);
537 }
538 }
539 rln_rx_end(sc);
540
541
542 rln_mbox_unlock(sc, hdr->cmd_seq, len + sizeof *hdr);
543 return;
544 }
545
546
547
548
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
554 return;
555 }
556
557
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
572
573
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
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):
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):
628 printf("%s: hardware fault\n", sc->sc_dev.dv_xname);
629 break;
630
631 case RLN_MM_CMD('a', 4):
632 if (bcmp(syncp->enaddr, sc->sc_arpcom.ac_enaddr,
633 ETHER_ADDR_LEN) == 0) {
634
635
636
637
638
639
640
641
642
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
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
662 s = splnet();
663 rlnstart(ifp);
664 splx(s);
665 break;
666
667 case RLN_MM_CMD('a', 5):
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):
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
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;
705 u_int16_t len;
706 u_int8_t xxx2;
707 u_int8_t xxx3;
708 u_int8_t seq;
709 u_int8_t xxx4;
710 struct ether_addr to;
711 struct ether_addr from;
712 } hwhdr;
713
714 dprintf(" [get]");
715
716 #ifdef RLNDUMP
717
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
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
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
748
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
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
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
845 rlnstop(sc);
846 } else if ((ifp->if_flags & IFF_UP) != 0 &&
847 (ifp->if_flags & IFF_RUNNING) == 0) {
848
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
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
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
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
944 for (i = verlen - 1; i >= 0 && ver[i] <= ' '; i--)
945 ver[i] = '\0';
946 return (0);
947 };
948
949
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
971 init.hop_period = 1;
972 init.bfreq = 2;
973 init.sfreq = 7;
974
975
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
981 bcopy(sc->sc_param.rp_master, init.mastername, sizeof init.mastername);
982
983
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;
997 magic.deferral_slot = 3;
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
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
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
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
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
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
1126 bcopy(param, &sc->sc_param, sizeof *param);
1127 if (rln_sendinit(sc))
1128 error = EIO;
1129 }
1130 return (error);
1131 }
1132
1133
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
1142 return (rln_msg_txrx(sc, &lock, sizeof lock,
1143 &response, sizeof response));
1144 }
1145
1146
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 ;
1156 ito.bd_wakeup = LLDBDWakeup ;
1157 ito.pm_sync = LLDPMSync ;
1158 ito.sniff_time = ito.timeout ? LLDSniffTime : 0;
1159
1160 if (rln_msg_txrx(sc, &ito, sizeof ito,
1161 &response, sizeof response))
1162 return (-1);
1163 }
1164
1165
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;
1180 u_int8_t *cardkey;
1181 {
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
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
1205
1206
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;
1223 }
1224 #endif