root/dev/ic/rln.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rlnconfig
  2. rlninit
  3. rlnstart
  4. rln_transmit
  5. rlnwatchdog
  6. rlnintr
  7. rlnsoftintr
  8. rlnread
  9. rlnget
  10. rlnioctl
  11. rlnstop
  12. rln_getenaddr
  13. rln_getpromvers
  14. rln_sendinit
  15. rln_roamconfig
  16. rln_roam
  17. rln_multicast
  18. rln_searchsync
  19. rln_iosetparam
  20. rln_lockprom
  21. rln_ito
  22. rln_standby
  23. rln_crypt

    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 = &top;
  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

/* [<][>][^][v][top][bottom][index][help] */