summaryrefslogtreecommitdiff
path: root/sys/dev/ic/rln.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/rln.c')
-rw-r--r--sys/dev/ic/rln.c1224
1 files changed, 0 insertions, 1224 deletions
diff --git a/sys/dev/ic/rln.c b/sys/dev/ic/rln.c
deleted file mode 100644
index 5f0820abff2..00000000000
--- a/sys/dev/ic/rln.c
+++ /dev/null
@@ -1,1224 +0,0 @@
-/* $OpenBSD: rln.c,v 1.18 2006/03/25 22:41:43 djm Exp $ */
-/*
- * David Leonard <d@openbsd.org>, 1999. Public Domain.
- *
- * Driver for the Proxim RangeLAN2 wireless network adaptor.
- *
- * Information and ideas gleaned from disassembly of Dave Koberstein's
- * <davek@komacke.com> Linux driver (apparently based on Proxim source),
- * from Yoichi Shinoda's <shinoda@cs.washington.edu> BSDI driver, and
- * Geoff Voelker's <voelker@cs.washington.edu> Linux port of the same.
- *
- */
-
-#include "bpfilter.h"
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/syslog.h>
-#include <sys/device.h>
-#include <sys/kernel.h>
-
-#include <net/if.h>
-#include <net/if_media.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#endif
-
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#endif
-
-#include <machine/bus.h>
-#include <machine/intr.h>
-
-#include <dev/ic/rln.h>
-#include <dev/ic/rlnvar.h>
-#include <dev/ic/rlnreg.h>
-#include <dev/ic/rlncmd.h>
-
-/* Autoconfig definition of driver back-end. */
-struct cfdriver rln_cd = {
- NULL, "rln", DV_IFNET
-};
-
-void rlninit(struct rln_softc *);
-void rlnstart(struct ifnet*);
-void rlnwatchdog(struct ifnet*);
-int rlnioctl(struct ifnet *, u_long, caddr_t);
-void rlnstop(struct rln_softc *);
-
-/* Interrupt handler. */
-void rlnsoftintr(void *);
-
-/* Packet I/O. */
-int rln_transmit(struct rln_softc *, struct mbuf *,
- int, int);
-struct mbuf * rlnget(struct rln_softc *, struct rln_mm_cmd *,
- int);
-
-/* Card protocol-level functions. */
-int rln_getenaddr(struct rln_softc *, u_int8_t *);
-int rln_getpromvers(struct rln_softc *, char *, int);
-int rln_sendinit(struct rln_softc *);
-#if notyet
-int rln_roamconfig(struct rln_softc *);
-int rln_roam(struct rln_softc *);
-int rln_multicast(struct rln_softc *, int);
-int rln_searchsync(struct rln_softc *);
-int rln_iosetparam(struct rln_softc *, struct rln_param *);
-int rln_lockprom(struct rln_softc *);
-int rln_ito(struct rln_softc *);
-int rln_standby(struct rln_softc *);
-#endif
-
-/* Back-end attach and configure. Assumes card has been reset. */
-void
-rlnconfig(sc)
- struct rln_softc * sc;
-{
- struct ifnet * ifp = &sc->sc_arpcom.ac_if;
- char promvers[7];
- int i;
-
- dprintf(" [attach %p]", sc);
-
- /* Use the flags supplied from config. */
- sc->sc_cardtype |= sc->sc_dev.dv_cfdata->cf_flags;
-
- /* Initialise values in the soft state. */
- sc->sc_pktseq = 0; /* rln_newseq() */
- sc->sc_txseq = 0;
- sc->sc_state = 0;
-
- /* Initialise user-configurable params. */
- sc->sc_param.rp_roam_config = RLN_ROAM_NORMAL;
- sc->sc_param.rp_security = RLN_SECURITY_DEFAULT;
- sc->sc_param.rp_station_type = RLN_STATIONTYPE_ALTMASTER;
- sc->sc_param.rp_domain = 0;
- sc->sc_param.rp_channel = 1;
- sc->sc_param.rp_subchannel = 1;
-
- bzero(sc->sc_param.rp_master, sizeof sc->sc_param.rp_master);
-
- /* Initialise the message mailboxes. */
- for (i = 0; i < RLN_NMBOX; i++)
- sc->sc_mbox[i].mb_state = RLNMBOX_VOID;
-
- /* Probe for some properties. */
- printf(", %s-piece",
- (sc->sc_cardtype & RLN_CTYPE_ONE_PIECE) ? "one" : "two");
- if (sc->sc_cardtype & RLN_CTYPE_OEM)
- printf(" oem");
- if (sc->sc_cardtype & RLN_CTYPE_UISA)
- printf(" micro-isa");
-
- /* Read the card's PROM revision. */
- if (rln_getpromvers(sc, promvers, sizeof promvers)) {
- printf(": could not read PROM version\n");
- return;
- }
- printf(", fw %.7s", promvers);
-
- /* Fetch the card's MAC address. */
- if (rln_getenaddr(sc, sc->sc_arpcom.ac_enaddr)) {
- printf(": could not read MAC address\n");
- return;
- }
- printf(", addr %s", ether_sprintf(sc->sc_arpcom.ac_enaddr));
-
- timeout_set(&sc->sc_timeout, rlnsoftintr, sc);
-
- /* Attach as a network interface. */
- bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
- ifp->if_softc = sc;
- ifp->if_start = rlnstart;
- ifp->if_ioctl = rlnioctl;
- ifp->if_watchdog = rlnwatchdog;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;
- IFQ_SET_READY(&ifp->if_snd);
- if_attach(ifp);
- ether_ifattach(ifp);
-}
-
-/* Bring device up. */
-void
-rlninit(sc)
- struct rln_softc * sc;
-{
- /* LLDInit() */
- struct ifnet * ifp = &sc->sc_arpcom.ac_if;
- int s;
-
- s = splnet();
- dprintf(" [init]");
-
- sc->sc_intsel = 0;
- sc->sc_status = 0;
- sc->sc_control = 0;
- ifp->if_flags &= ~IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
-
- /* Do a hard reset. */
- if (rln_reset(sc)) {
- printf("%s: could not reset card\n", sc->sc_dev.dv_xname);
- goto fail;
- }
- sc->sc_state = 0; /* Also clears RLN_STATE_NEEDINIT. */
-
- /* Use this host's name as a master name. */
- if (!cold && sc->sc_param.rp_master[0] == '\0') {
- bcopy(hostname, sc->sc_param.rp_master,
- min(hostnamelen, sizeof sc->sc_param.rp_master));
- }
-
- rln_enable(sc, 1);
-
- /* Initialise operational params. */
- if (rln_sendinit(sc)) {
- printf("%s: could not set card parameters\n",
- sc->sc_dev.dv_xname);
- goto fail;
- }
-#if 0
- rln_roamconfig(sc);
- /* rln_lockprom(sc); */
- /* SendSetITO() */
- rln_multicast(sc, 1);
- rln_roam(sc);
-
- /* Synchronise with something. */
- rln_searchsync(sc);
-#endif
- ifp->if_flags |= IFF_RUNNING;
- rlnstart(ifp);
- splx(s);
-
- return;
-
- fail:
- ifp->if_flags &= ~IFF_UP;
- splx(s);
- return;
-}
-
-/* Start outputting on interface. This is always called at splnet(). */
-void
-rlnstart(ifp)
- struct ifnet * ifp;
-{
- struct rln_softc * sc = (struct rln_softc *)ifp->if_softc;
- struct mbuf * m0;
- int len, pad, ret, s;
-
- dprintf(" start[");
-
- if (sc->sc_state & RLN_STATE_NEEDINIT)
- rlninit(sc);
-
- /* Don't transmit if interface is busy or not running. */
- if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) {
- dprintf(" %s] ", (ifp->if_flags & IFF_OACTIVE) ?
- "busy" : "stopped");
- return;
- }
-
- /* Don't transmit if we are not synchronised. */
- if ((sc->sc_state & RLN_STATE_SYNC) == 0) {
- dprintf(" nosync]");
- return;
- }
-
- rln_enable(sc, 1);
-
- startagain:
- s = splnet();
- IFQ_DEQUEUE(&ifp->if_snd, m0);
- splx(s);
-
- if (m0 == NULL) {
- dprintf(" empty]");
- return;
- }
-
-#if NBPFILTER > 0
- /* Tap packet stream here for BPF listeners. */
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m0, BPF_DIRECTION_OUT);
-#endif
-
- /* We need to use m->m_pkthdr.len, so require the header. */
- if ((m0->m_flags & M_PKTHDR) == 0) {
- printf("%s: no mbuf header\n", sc->sc_dev.dv_xname);
- goto oerror;
- }
-
- len = m0->m_pkthdr.len;
-
-#define PACKETMIN (sizeof (struct ether_header) + ETHERMIN)
-#define PACKETMAX (sizeof (struct ether_header) + ETHERMTU + 4)
-
- /* Packet size has to be an even number between 60 and 1518 octets. */
- pad = len & 1;
- if (len + pad < PACKETMIN)
- pad = PACKETMIN - len;
-
- if (len + pad > PACKETMAX) {
- printf("%s: packet too big (%d > %d)\n",
- sc->sc_dev.dv_xname, len + pad,
- PACKETMAX);
- ++ifp->if_oerrors;
- m_freem(m0);
- goto startagain;
- }
-
- ret = rln_transmit(sc, m0, len, pad);
- if (ret)
- goto oerror;
-
- ifp->if_flags |= IFF_OACTIVE;
- m_freem(m0);
-
- dprintf(" sent]");
- return;
-
-oerror:
- ++ifp->if_oerrors;
- m_freem(m0);
- rln_need_reset(sc);
- return;
-}
-
-/* Transmit one packet. */
-int
-rln_transmit(sc, m0, len, pad)
- struct rln_softc * sc;
- struct mbuf * m0;
- int len;
- int pad;
-{
- struct mbuf * m;
- int zfirst;
- int actlen;
- int tlen = len + pad;
- struct rln_msg_tx_state state;
- static u_int8_t zeroes[60];
- struct rln_mm_sendpacket cmd = { RLN_MM_SENDPACKET };
-
- /* Does the packet start with a zero bit? */
- zfirst = ((*mtod(m0, u_int8_t *) & 1) == 0);
-
- cmd.mode =
- RLN_MM_SENDPACKET_MODE_BIT7 |
- (zfirst ? RLN_MM_SENDPACKET_MODE_ZFIRST : 0) |
- (0 ? RLN_MM_SENDPACKET_MODE_QFSK : 0), /* sc->qfsk? */
- cmd.power = 0x70; /* 0x70 or 0xf0 */
- cmd.length_lo = htons(4 + tlen) & 0xff;
- cmd.length_hi = (htons(4 + tlen) >> 8) & 0xff;
- cmd.xxx1 = 0;
- cmd.xxx2 = 0;
- cmd.xxx3 = 0;
-
- /* A unique packet-level sequence number, independent of sc_seq. */
- cmd.sequence = sc->sc_txseq;
- sc->sc_txseq++;
- if (sc->sc_txseq > RLN_MAXSEQ)
- sc->sc_txseq = 0;
-
- dprintf(" T[%d+%d", len, pad);
-
- if (rln_msg_tx_start(sc, &cmd, sizeof cmd + tlen, &state))
- goto error;
-
- cmd.mm_cmd.cmd_seq = rln_newseq(sc);
-
- /* Send the SENDPACKET command header */
-#ifdef RLNDUMP
- printf("%s: send %c%d seq %d data ", sc->sc_dev.dv_xname,
- cmd.mm_cmd.cmd_letter, cmd.mm_cmd.cmd_fn, cmd.mm_cmd.cmd_seq);
- RLNDUMPHEX(&cmd, sizeof cmd);
- printf(":");
-#endif
- rln_msg_tx_data(sc, &cmd, sizeof cmd, &state);
-
- /* XXX do we need to insert a hardware header here??? */
-
- /* Follow the header immediately with the packet payload */
- actlen = 0;
- for (m = m0; m; m = m->m_next) {
- if (m->m_len) {
-#ifdef RLNDUMP
- RLNDUMPHEX(mtod(m, void *), m->m_len);
-#endif
- rln_msg_tx_data(sc, mtod(m, void *), m->m_len, &state);
- }
- if (m->m_next)
- printf("|");
- actlen += m->m_len;
- }
-#ifdef DIAGNOSTIC
- if (actlen != len)
- panic("rln_transmit: len %d != %d", actlen, len);
- if (pad > sizeof zeroes)
- panic("rln_transmit: pad %d > %d", pad, sizeof zeroes);
-#endif
- if (pad) {
-#ifdef RLNDUMP
- printf(":");
- RLNDUMPHEX(zeroes, pad);
-#endif
- rln_msg_tx_data(sc, zeroes, pad, &state);
- }
-
-#ifdef RLNDUMP
- printf("\n");
-#endif
- if (rln_msg_tx_end(sc, &state))
- goto error;
- return (0);
-
- error:
- dprintf(" error]");
- return (-1);
-}
-
-/* (Supposedly) called when interrupts are suspiciously absent. */
-void
-rlnwatchdog(ifp)
- struct ifnet * ifp;
-{
- struct rln_softc * sc = (struct rln_softc *)ifp->if_softc;
-
- log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
- ++sc->sc_arpcom.ac_if.if_oerrors;
- rlninit(sc);
- rln_enable(sc, 1);
-}
-
-/* Handle single card interrupt. */
-int
-rlnintr(arg)
- void * arg;
-{
- struct rln_softc * sc = (struct rln_softc *)arg;
-
- dprintf("!");
-
- /* Tell card not to interrupt any more. */
- rln_enable(sc, 0);
-
- if (cold)
- /* During autoconfig - must handle interrupts now. */
- rlnsoftintr(sc);
- else
- /* Handle later. */
- timeout_add(&sc->sc_timeout, 1);
-
- return (1);
-}
-
-/* Process earlier card interrupt at splsoftnet. */
-void
-rlnsoftintr(arg)
- void * arg;
-{
- struct rln_softc *sc = (struct rln_softc *)arg;
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- int len;
- u_int8_t w;
- struct rln_mm_cmd hdr;
- int s;
-
- s = splsoftnet();
- dprintf(" si(");
-
- again:
- /* Save wakeup state. */
- w = rln_wakeup(sc, RLN_WAKEUP_SET);
-
- if ((len = rln_rx_request(sc, 300)) < 0) {
- /* Error in transfer. */
- rln_need_reset(sc);
- rln_rx_end(sc);
- } else if (len < sizeof hdr) {
- /* Short message. */
- rln_rx_end(sc);
- printf("%s: short msg (%d)\n", sc->sc_dev.dv_xname, len);
- ifp->if_ierrors++;
- } else {
- /* Valid message: read header and process. */
- rln_rx_data(sc, &hdr, sizeof hdr);
- rlnread(sc, &hdr, len);
- }
-
- /* Ensure that wakeup state is unchanged if transmitting. */
- if (ifp->if_flags & IFF_OACTIVE)
- w |= RLN_WAKEUP_NOCHANGE;
- rln_wakeup(sc, w);
-
- /* Check for more interrupts. */
- if ((sc->sc_state & RLN_STATE_NEEDINIT) == 0 &&
- rln_status_rx_ready(sc)) {
- if (rln_status_rx_read(sc) == RLN_STATUS_RX_ERROR) {
-#ifdef DIAGNOSTIC
- printf("%s: protocol error\n", sc->sc_dev.dv_xname);
-#endif
- DELAY(100 * 1000); /* Woah, baby. */
- rln_clear_nak(sc);
- } else {
-#ifdef DIAGNOSTIC
- printf("%s: intr piggyback\n", sc->sc_dev.dv_xname);
-#endif
- goto again;
- }
- }
-
- rln_eoi(sc);
- rln_enable(sc, 1);
-
- dprintf(")");
- splx(s);
-}
-
-/* Read and process a message from the card. */
-void
-rlnread(sc, hdr, len)
- struct rln_softc *sc;
- struct rln_mm_cmd *hdr;
- int len;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- struct mbuf *m;
- u_int8_t data[1538];
- u_int8_t *buf;
- size_t buflen;
- struct rln_pdata pd = RLN_PDATA_INIT;
- struct rln_mm_synchronised * syncp = (struct rln_mm_synchronised *)data;
- int s;
-
- dprintf(" [read]");
-
- /* Were we waiting for this message? */
- if (rln_mbox_lock(sc, hdr->cmd_seq, (void **)&buf, &buflen) == 0) {
-#ifdef DIAGNOSTIC
- if (buflen < sizeof *hdr)
- panic("rlnread buflen");
-#endif
- bcopy(hdr, buf, sizeof *hdr);
- buf += sizeof *hdr;
- len -= sizeof *hdr;
- buflen -= sizeof *hdr;
- if (len) {
- if (len == buflen) /* Expected size */
- rln_rx_pdata(sc, buf, len, &pd);
- else if (len < buflen) { /* Underfill */
-#ifdef DIAGNOSTIC
- printf("%s: underfill %d<%d, cmd %c%d\n",
- sc->sc_dev.dv_xname,
- len, buflen,
- hdr->cmd_letter, hdr->cmd_fn);
-#endif
- rln_rx_pdata(sc, buf, len, &pd);
- } else { /* Overflow */
-#ifdef DIAGNOSTIC
- printf("%s: overflow %d>%d, cmd %c%d\n",
- sc->sc_dev.dv_xname,
- len, buflen,
- hdr->cmd_letter, hdr->cmd_fn);
-#endif
- rln_rx_pdata(sc, buf, buflen, &pd);
- /* Drain the rest somewhere. */
- rln_rx_pdata(sc, data, len - buflen, &pd);
- }
- }
- rln_rx_end(sc);
-
- /* This message can now be handled by the waiter. */
- rln_mbox_unlock(sc, hdr->cmd_seq, len + sizeof *hdr);
- return;
- }
-
- /* Otherwise, handle the message, right here, right now. */
-
- /* Check if we can cope with the size of this message. */
- if (len > sizeof data) {
- printf("%s: msg too big (%d)\n", sc->sc_dev.dv_xname, len);
- ifp->if_ierrors++;
- rln_rx_end(sc);
- /* rln_need_reset(sc); */
- return;
- }
-
- /* Check for error results. */
- if (hdr->cmd_error & 0x80) {
- printf("%s: command error 0x%02x command %c%d len=%d\n",
- sc->sc_dev.dv_xname,
- hdr->cmd_error & ~0x80,
- hdr->cmd_letter, hdr->cmd_fn,
- len);
- ifp->if_ierrors++;
- rln_rx_end(sc);
- rln_need_reset(sc);
- return;
- }
-
- /*
- * "b1": Receiving a packet is a special case.
- * We wish to read the data with pio straight into an
- * mbuf to avoid a memory-memory copy.
- */
- if (hdr->cmd_letter == 'b' && hdr->cmd_fn == 1) {
- m = rlnget(sc, hdr, len);
- rln_rx_end(sc);
- if (m == NULL)
- return;
- ifp->if_ipackets++;
-#ifdef DIAGNOSTIC
- if (bcmp(mtod(m, u_int8_t *), "prox", 4) == 0) {
- printf("%s: proxim special packet received\n",
- sc->sc_dev.dv_xname);
- }
-#endif
-
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
-#endif
-
- ether_input_mbuf(ifp, m);
- return;
- }
-
-
- /* Otherwise we read the packet into a buffer on the stack. */
- bcopy(hdr, data, sizeof *hdr);
- if (len > sizeof *hdr)
- rln_rx_pdata(sc, data + sizeof *hdr, len - sizeof *hdr, &pd);
- rln_rx_end(sc);
-
-#ifdef RLNDUMP
- printf("%s: recv %c%d seq %d data ", sc->sc_dev.dv_xname,
- hdr->cmd_letter, hdr->cmd_fn, hdr->cmd_seq);
- RLNDUMPHEX(hdr, sizeof hdr);
- printf(":");
- RLNDUMPHEX(data + sizeof hdr, len - sizeof hdr);
- printf("\n");
-#endif
-
- switch (RLN_MM_CMD(hdr->cmd_letter, hdr->cmd_fn)) {
- case RLN_MM_CMD('b', 0): /* b0: Transmit done. */
-#ifdef DIAGNOSTIC
- if (len != 7)
- printf("%s: 'b0' len %d != 7\n",
- sc->sc_dev.dv_xname, len);
-#endif
- ifp->if_flags &= ~IFF_OACTIVE;
- ifp->if_opackets++;
- s = splnet();
- rlnstart(ifp);
- splx(s);
- break;
-
- case RLN_MM_CMD('a', 20): /* a20: Card fault. */
- printf("%s: hardware fault\n", sc->sc_dev.dv_xname);
- break;
-
- case RLN_MM_CMD('a', 4): /* a4: Sync'd. */
- if (bcmp(syncp->enaddr, sc->sc_arpcom.ac_enaddr,
- ETHER_ADDR_LEN) == 0) {
- /* Sync'd to own enaddr. */
- /*
- * From http://www.proxim.com/support/faq/7400.shtml
- * 3. RLNSETUP reports that I'm synchronized to my own MAC address. What
- * does that mean?
- * You are the acting Master for this network. Either you are
- * configured as the Master or as an Alternate Master. If you are an
- * Alternate Master, you may be out of range or on a different Domain
- * and Security ID from the true Master.
- */
-
- printf("%s: nothing to sync to; now master ",
- sc->sc_dev.dv_xname);
- }
- else
- printf("%s: synchronised to ", sc->sc_dev.dv_xname);
- printf("%.11s (%s) channel %d/%d\n",
- syncp->mastername,
- ether_sprintf(syncp->enaddr),
- syncp->channel,
- syncp->subchannel);
-
- /* Record the new circumstances. */
- sc->sc_param.rp_channel = syncp->channel;
- sc->sc_param.rp_subchannel = syncp->subchannel;
- sc->sc_state |= RLN_STATE_SYNC;
-
- /* Resume sending. */
- s = splnet();
- rlnstart(ifp);
- splx(s);
- break;
-
- case RLN_MM_CMD('a', 5): /* a4: Lost sync. */
- printf("%s: lost sync\n", sc->sc_dev.dv_xname);
- sc->sc_state &= ~RLN_STATE_SYNC;
- break;
-
- case RLN_MM_CMD('a', 18): /* a18: Roaming. */
- printf("%s: roaming\n", sc->sc_dev.dv_xname);
- break;
- default:
-#ifdef DIAGNOSTIC
- printf("%s: msg `%c%d' seq %d data {",
- sc->sc_dev.dv_xname,
- hdr->cmd_letter, hdr->cmd_fn, hdr->cmd_seq);
- RLNDUMPHEX(hdr, sizeof hdr);
- printf(":");
- RLNDUMPHEX(data, len);
- printf("}\n");
-#endif
- break;
- }
-
-}
-
-/* Extract a received network packet from the card. */
-struct mbuf *
-rlnget(sc, hdr, totlen)
- struct rln_softc *sc;
- struct rln_mm_cmd *hdr;
- int totlen;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- int len;
- int pad;
- struct mbuf *m, **mp, *top;
- struct rln_pdata pd = RLN_PDATA_INIT;
- struct {
- u_int8_t rssi;
- u_int8_t xxx1; /* always 00? */
- u_int16_t len; /* payload length */
- u_int8_t xxx2; /* always 00? */
- u_int8_t xxx3; /* always c0? */
- u_int8_t seq;
- u_int8_t xxx4;
- struct ether_addr to; /* destination station addr */
- struct ether_addr from; /* sending station addr */
- } hwhdr;
-
- dprintf(" [get]");
-
-#ifdef RLNDUMP
- /* Decode the command header: */
- printf("%s: recv %c%d seq %d data ", sc->sc_dev.dv_xname,
- hdr->cmd_letter, hdr->cmd_fn, hdr->cmd_seq);
- RLNDUMPHEX(hdr, sizeof hdr);
- printf(":");
-#endif
- totlen -= sizeof *hdr;
-
-#ifdef DIAGNOSTIC
- if (totlen <= 0) {
- printf("%s: empty packet", sc->sc_dev.dv_xname);
- goto drop;
- }
-#endif
-
- /* Decode the hardware header: */
- rln_rx_pdata(sc, &hwhdr, sizeof hwhdr, &pd);
- totlen -= sizeof hwhdr;
-#ifdef RLNDUMP
- RLNDUMPHEX(&hwhdr, sizeof hwhdr);
- printf("/");
-#endif
- /* (Most of the following code fleeced from elink3.c.) */
-
- MGETHDR(m, M_DONTWAIT, MT_DATA);
- if (m == NULL)
- goto drop;
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = totlen;
- /*
- * Insert some leading padding in the mbuf, so that payload data is
- * aligned.
- */
- pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
- m->m_data += pad;
- len = MHLEN - pad;
- top = 0;
- mp = &top;
-
- while (totlen > 0) {
- if (top) {
- MGET(m, M_DONTWAIT, MT_DATA);
- if (m == NULL) {
- m_freem(top);
- goto drop;
- }
- len = MLEN;
- }
- if (totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if (m->m_flags & M_EXT) {
- len = MCLBYTES;
- if (!top) {
- m->m_data += pad;
- len -= pad;
- }
- }
- }
- len = min(totlen, len);
- rln_rx_pdata(sc, mtod(m, u_int8_t *), len, &pd);
-#ifdef RLNDUMP
- RLNDUMPHEX(mtod(m, u_int8_t *), len);
- if (totlen != len)
- printf("|");
-#endif
- m->m_len = len;
- totlen -= len;
- *mp = m;
- mp = &m->m_next;
- }
-#ifdef RLNDUMP
- printf("\n");
-#endif
- return top;
-
-drop:
-#ifdef RLNDUMP
- printf(": drop\n");
-#endif
- ifp->if_iqdrops++;
- return NULL;
-}
-
-/* Interface control. */
-int
-rlnioctl(ifp, cmd, data)
- struct ifnet *ifp;
- u_long cmd;
- caddr_t data;
-{
- struct rln_softc *sc = ifp->if_softc;
- struct ifaddr *ifa = (struct ifaddr *)data;
- int s, error;
- int need_init;
-
- printf("%s: ioctl cmd[%c/%d] data=%x\n", sc->sc_dev.dv_xname,
- IOCGROUP(cmd), IOCBASECMD(cmd), data);
-
- s = splnet();
- if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) != 0) {
- splx(s);
- return error;
- }
-
- switch (cmd) {
- case SIOCSIFADDR:
- /* Set address. */
- ifp->if_flags |= IFF_UP;
-
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- rlninit(sc);
- arp_ifinit(&sc->sc_arpcom, ifa);
- break;
-#endif
- default:
- rlninit(sc);
- break;
- }
- break;
-
- case SIOCSIFFLAGS:
- need_init = 0;
-
- if ((ifp->if_flags & IFF_UP) == 0 &&
- (ifp->if_flags & IFF_RUNNING) != 0) {
- /* Was running, want down: stop. */
- rlnstop(sc);
- } else if ((ifp->if_flags & IFF_UP) != 0 &&
- (ifp->if_flags & IFF_RUNNING) == 0) {
- /* Was not running, want up: start. */
- need_init = 1;
- }
-
- if (ifp->if_flags & IFF_RUNNING) {
- if ((ifp->if_flags & IFF_PROMISC) &&
- (sc->sc_state & RLN_STATE_PROMISC) == 0) {
- sc->sc_state |= RLN_STATE_PROMISC;
- need_init = 1;
- }
- else if ((ifp->if_flags & IFF_PROMISC) == 0 &&
- (sc->sc_state & RLN_STATE_PROMISC)) {
- sc->sc_state &= ~RLN_STATE_PROMISC;
- need_init = 1;
- }
- }
-
- if (need_init)
- rlninit(sc);
-
- break;
-
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- error = EOPNOTSUPP;
- break;
-
-#if notyet
- case RLNIOSPARAM:
- error = rln_iosetparam(sc, (struct rln_param *)&data);
- break;
-
- case RLNIOGPARAM:
- bcopy(&sc->sc_param, (struct rln_param *)&data,
- sizeof sc->sc_param);
- break;
-#endif
-
- default:
- error = EINVAL;
- break;
- }
-
- splx(s);
- return (error);
-}
-
-/* Stop output from the card. */
-void
-rlnstop(sc)
- struct rln_softc *sc;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
-
- dprintf(" [stop]");
- ifp->if_flags &= ~IFF_RUNNING;
- rln_enable(sc, 0);
-}
-
-/* Get MAC address from card. */
-int
-rln_getenaddr(sc, enaddr)
- struct rln_softc *sc;
- u_int8_t * enaddr;
-{
- struct rln_mm_cmd query = RLN_MM_GETENADDR;
- struct rln_mm_gotenaddr response = { RLN_MM_GETENADDR };
-
- if (rln_msg_txrx(sc, &query, sizeof query,
- &response, sizeof response))
- return (-1);
- bcopy(response.enaddr, enaddr, sizeof response.enaddr);
- return (0);
-};
-
-/* Get firmware version string from card. */
-int
-rln_getpromvers(sc, ver, verlen)
- struct rln_softc *sc;
- char *ver;
- int verlen;
-{
- struct rln_mm_cmd query = RLN_MM_GETPROMVERSION;
- struct rln_mm_gotpromversion response = { RLN_MM_GOTPROMVERSION };
- int i;
-
-#ifdef DIAGNOSTIC
- if (verlen != sizeof response.version)
- panic("rln_getpromvers");
-#endif
-
- if (rln_msg_txrx(sc, &query, sizeof query,
- &response, sizeof response))
- return (-1);
- bcopy(response.version, ver, verlen);
- /* Nul trailing spaces. */
- for (i = verlen - 1; i >= 0 && ver[i] <= ' '; i--)
- ver[i] = '\0';
- return (0);
-};
-
-/* Set default operational parameters on card. */
-int
-rln_sendinit(sc)
- struct rln_softc *sc;
-{
- struct rln_mm_init init = { RLN_MM_INIT };
- struct rln_mm_initted iresponse;
-#if 0
- struct rln_mm_setmagic magic = { RLN_MM_SETMAGIC };
- struct rln_mm_disablehopping hop = { RLN_MM_DISABLEHOPPING };
- struct rln_mm_cmd response;
-#endif
-
- bzero((char *)&init + sizeof init.mm_cmd,
- sizeof init - sizeof init.mm_cmd);
-
- dprintf(" [setting parameters]");
- init.opmode = (sc->sc_state & RLN_STATE_PROMISC ?
- RLN_MM_INIT_OPMODE_PROMISC : RLN_MM_INIT_OPMODE_NORMAL);
- init.stationtype = sc->sc_param.rp_station_type;
-
- /* Spread-spectrum frequency hopping. */
- init.hop_period = 1;
- init.bfreq = 2;
- init.sfreq = 7;
-
- /* Choose channel. */
- init.channel = sc->sc_param.rp_channel;
- init.subchannel = sc->sc_param.rp_subchannel;
- init.domain = sc->sc_param.rp_domain;
-
- /* Name of this station when acting as master. */
- bcopy(sc->sc_param.rp_master, init.mastername, sizeof init.mastername);
-
- /* Security params. */
- init.sec1 = (sc->sc_param.rp_security & 0x0000ff) >> 0;
- init.sec2 = (sc->sc_param.rp_security & 0x00ff00) >> 8;
- init.sec3 = (sc->sc_param.rp_security & 0xff0000) >> 16;
-
- init.sync_to = 1;
- bzero(init.syncname, sizeof init.syncname);
-
- if (rln_msg_txrx(sc, &init, sizeof init,
- &iresponse, sizeof iresponse))
- return (-1);
-#if 0
- dprintf(" [setting magic]");
- magic.fairness_slot = 3; /* lite: 1, norm: 3, off: -1 */
- magic.deferral_slot = 3; /* lite: 0, norm: 3, off: -1 */
- magic.regular_mac_retry = 7;
- magic.frag_mac_retry = 10;
- magic.regular_mac_qfsk = 2;
- magic.frag_mac_qfsk = 5;
- magic.xxx1 = 0xff;
- magic.xxx2 = 0xff;
- magic.xxx3 = 0xff;
- magic.xxx4 = 0x00;
- if (rln_msg_txrx(sc, &magic, sizeof magic,
- &response, sizeof response))
- return (-1);
-
- dprintf(" [disabling freq hopping]");
- hop.hopflag = RLN_MM_DISABLEHOPPING_HOPFLAG_DISABLE;
- if (rln_msg_txrx(sc, &hop, sizeof hop,
- &response, sizeof response))
- return (-1);
-
-#endif
- return (0);
-}
-
-#if notyet
-/* Configure the way the card leaves a basestation. */
-int
-rln_roamconfig(sc)
- struct rln_softc *sc;
-{
- struct rln_mm_setroaming roam = { RLN_MM_SETROAMING };
- struct rln_mm_cmd response;
- static int retry[3] = { 6, 6, 4 };
- static int rssi[3] = { 5, 15, 5 };
-
- dprintf(" [roamconfig]");
-#ifdef DIAGNOSTIC
- if (sc->sc_param.rp_roam_config > 2)
- panic("roamconfig");
-#endif
- roam.sync_alarm = 0;
- roam.retry_thresh = retry[sc->sc_param.rp_roam_config];
- roam.rssi_threshold = rssi[sc->sc_param.rp_roam_config];
- roam.xxx1 = 0x5a;
- roam.sync_rssi_threshold = 0;
- roam.xxx2 = 0x5a;
- roam.missed_sync = 0x4;
- if (rln_msg_txrx(sc, &roam, sizeof roam,
- &response, sizeof response))
- return (-1);
-
- return (0);
-}
-
-/* Enable roaming. */
-int
-rln_roam(sc)
- struct rln_softc *sc;
-{
- struct rln_mm_cmd roam = RLN_MM_ROAM;
- struct rln_mm_cmd response;
-
- return (rln_msg_txrx(sc, &roam, sizeof roam,
- &response, sizeof response));
-}
-
-/* Enable multicast capability. */
-int
-rln_multicast(sc, enable)
- struct rln_softc *sc;
- int enable;
-{
- struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- struct rln_mm_multicast mcast = { RLN_MM_MULTICAST };
- struct rln_mm_cmd response;
- int ret;
-
- mcast.enable = enable;
-
- ret = rln_msg_txrx(sc, &mcast, sizeof mcast,
- &response, sizeof response);
- if (ret == 0) {
- if (enable)
- ifp->if_flags |= IFF_MULTICAST;
- else
- ifp->if_flags &= ~IFF_MULTICAST;
- }
- return (ret);
-}
-
-/* Search for and sync with any master. */
-int
-rln_searchsync(sc)
- struct rln_softc *sc;
-{
- struct rln_mm_search search = { RLN_MM_SEARCH };
- struct rln_mm_searching response;
-
- bzero(search.xxx1, sizeof search.xxx1);
- search.domain = sc->sc_param.rp_domain;
- search.roaming = 1;
- search.xxx3 = 0;
- search.xxx4 = 1;
- search.xxx5 = 0;
- bzero(search.xxx6, sizeof search.xxx6);
-
- return (rln_msg_txrx(sc, &search, sizeof search,
- &response, sizeof response));
-}
-
-/* Set values from an external parameter block. */
-int
-rln_iosetparam(sc, param)
- struct rln_softc *sc;
- struct rln_param *param;
-{
- int error = 0;
-
- if (param->rp_roam_config > 2)
- error = EINVAL;
- if (param->rp_security > 0x00ffffff)
- error = EINVAL;
- if (param->rp_station_type > 2)
- error = EINVAL;
- if (param->rp_channel > 15)
- error = EINVAL;
- if (param->rp_subchannel > 15)
- error = EINVAL;
- if (error == 0) {
- /* Apply immediately. */
- bcopy(param, &sc->sc_param, sizeof *param);
- if (rln_sendinit(sc))
- error = EIO;
- }
- return (error);
-}
-
-/* Protect the eeprom from storing a security ID(?) */
-int
-rln_lockprom(sc)
- struct rln_softc *sc;
-{
- struct rln_mm_cmd lock = RLN_MM_EEPROM_PROTECT;
- struct rln_mm_cmd response;
-
- /* XXX Always yields an error? */
- return (rln_msg_txrx(sc, &lock, sizeof lock,
- &response, sizeof response));
-}
-
-/* Set the h/w Inactivity Time Out timer on the card. */
-int
-rln_ito(sc)
- struct rln_softc * sc;
-{
- struct rln_mm_setito ito = { RLN_MM_MULTICAST };
- struct rln_mm_cmd response;
-
- ito.xxx = 3;
- ito.timeout = LLDInactivityTimeOut /* enabler, 0 or 1 */;
- ito.bd_wakeup = LLDBDWakeup /* 0 */;
- ito.pm_sync = LLDPMSync /* 0 */;
- ito.sniff_time = ito.timeout ? LLDSniffTime /* 0 */ : 0;
-
- if (rln_msg_txrx(sc, &ito, sizeof ito,
- &response, sizeof response))
- return (-1);
-}
-
-/* Put the card into standby mode. */
-int
-rln_standby(sc)
- struct rln_softc * sc;
-{
- struct rln_mm_standby standby = { RLN_MM_STANDBY };
-
- standby.xxx = 0;
- if (rln_msg_txrx(sc, &ito, sizeof ito, NULL, 0))
- return (-1);
-}
-
-void
-rln_crypt(userkey, cardkey)
- char *userkey; /* User's string (max 20 chars). */
- u_int8_t *cardkey; /* 20 bits (3 bytes) */
-{
- /*
- * From <http://www.proxim.com/learn/whiteppr/rl2security.shtml>
- * "RangeLAN2 Security Features":
- *
- * The Security ID is a unique, 20 character alphanumeric
- * string defined and configured by the user. It must be
- * identically configured in every radio intended to
- * communicate with others in the same network. Once
- * configured, the Security ID is reduced to 20 bits by a
- * proprietary algorithm confidential to Proxim. It is
- * merged with the radio MAC address (a 12 character field
- * unique to every radio), scrambled and stored using another
- * proprietary, confidential algorithm.
- */
- int32_t key;
- int8_t ret;
- int i;
- int len;
- int32_t multiplicand = 0x80000181;
- int64_t res;
-
- /*
- * This algorithm is `compatible' with Proxim's first
- * `proprietary confidential algorithm': i.e., it appears
- * to be functionally identical.
- */
- len = strlen(s);
- key = 0x030201;
- for (i = 0; i < len; i++) {
-
- key *= userkey[i];
- res = (int64_t)multiplicand * key;
- key = key - 0xfffffd *
- (((key + (int32_t)(res >> 32)) >> 23) - (key >> 31));
- }
-
- cardkey[0] = (key >> 16) & 0xff;
- cardkey[1] = (key >> 8) & 0xff;
- cardkey[2] = key & 0xff;
-
- cardkey[0] |= 0x03; /* Restrict key space by 2 bits. */
-}
-#endif