summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pcmcia/if_malo.c176
-rw-r--r--sys/dev/pcmcia/if_maloreg.h11
-rw-r--r--sys/dev/pcmcia/if_malovar.h52
3 files changed, 227 insertions, 12 deletions
diff --git a/sys/dev/pcmcia/if_malo.c b/sys/dev/pcmcia/if_malo.c
index d0ee0c1ffc8..b1296f9193c 100644
--- a/sys/dev/pcmcia/if_malo.c
+++ b/sys/dev/pcmcia/if_malo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_malo.c,v 1.12 2007/06/04 20:29:51 mglocker Exp $ */
+/* $OpenBSD: if_malo.c,v 1.13 2007/06/08 22:08:21 mglocker Exp $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
@@ -82,6 +82,8 @@ void cmalo_detach(void *);
int cmalo_intr(void *);
void cmalo_intr_mask(struct malo_softc *, int);
void cmalo_rx(struct malo_softc *);
+void cmalo_start(struct ifnet *);
+int cmalo_tx(struct malo_softc *, struct mbuf *);
void cmalo_hexdump(void *, int);
int cmalo_cmd_get_hwspec(struct malo_softc *);
@@ -92,6 +94,7 @@ int cmalo_cmd_set_channel(struct malo_softc *, uint16_t);
int cmalo_cmd_set_txpower(struct malo_softc *, int16_t);
int cmalo_cmd_set_antenna(struct malo_softc *, uint16_t);
int cmalo_cmd_set_macctrl(struct malo_softc *);
+int cmalo_cmd_set_assoc(struct malo_softc *);
int cmalo_cmd_request(struct malo_softc *, uint16_t, int);
int cmalo_cmd_response(struct malo_softc *);
@@ -270,7 +273,7 @@ cmalo_attach(void *arg)
ifp->if_softc = sc;
ifp->if_ioctl = cmalo_ioctl;
ifp->if_init = cmalo_init;
- //ifp->if_start = cmalo_start;
+ ifp->if_start = cmalo_start;
//ifp->if_watchdog = cmalo_watchdog;
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST;
strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
@@ -563,6 +566,10 @@ cmalo_init(struct ifnet *ifp)
if (cmalo_cmd_set_channel(sc, sc->sc_curchan) != 0)
return (EIO);
+ cmalo_cmd_set_assoc(sc);
+
+ ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+
/* device up */
ifp->if_flags |= IFF_RUNNING;
@@ -604,6 +611,31 @@ cmalo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
{
struct malo_softc *sc = ic->ic_if.if_softc;
+ switch (nstate) {
+ case IEEE80211_S_INIT:
+ DPRINTF(1, "%s: newstate is IEEE80211_S_INIT\n",
+ sc->sc_dev.dv_xname);
+ break;
+ case IEEE80211_S_SCAN:
+ DPRINTF(1, "%s: newstate is IEEE80211_S_SCAN\n",
+ sc->sc_dev.dv_xname);
+ break;
+ case IEEE80211_S_AUTH:
+ DPRINTF(1, "%s: newstate is IEEE80211_S_AUTH\n",
+ sc->sc_dev.dv_xname);
+ break;
+ case IEEE80211_S_ASSOC:
+ DPRINTF(1, "%s: newstate is IEEE80211_S_ASSOC\n",
+ sc->sc_dev.dv_xname);
+ break;
+ case IEEE80211_S_RUN:
+ DPRINTF(1, "%s: newstate is IEEE80211_S_RUN\n",
+ sc->sc_dev.dv_xname);
+ break;
+ default:
+ break;
+ }
+
return (sc->sc_newstate(ic, nstate, arg));
}
@@ -651,6 +683,9 @@ cmalo_intr(void *arg)
DPRINTF(2, "%s: interrupt handler called (intr = 0x%04x)\n",
sc->sc_dev.dv_xname, intr);
+ if (intr & MALO_VAL_HOST_INTR_TX)
+ /* TX frame sent */
+ DPRINTF(2, "%s: TX frame sent\n", sc->sc_dev.dv_xname);
if (intr & MALO_VAL_HOST_INTR_RX)
/* RX frame received */
cmalo_rx(sc);
@@ -705,8 +740,8 @@ cmalo_rx(struct malo_softc *sc)
uc[i] = htole16(MALO_READ_2(sc, MALO_REG_DATA_READ));
if (psize & 0x0001)
uc[i] = MALO_READ_1(sc, MALO_REG_DATA_READ);
- MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_DATA_DL_OVER);
- MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_DATA_DL_OVER);
+ MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_RX_DL_OVER);
+ MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_RX_DL_OVER);
/* access RX packet descriptor */
rxdesc = (struct malo_rx_desc *)sc->sc_data;
@@ -754,8 +789,72 @@ cmalo_rx(struct malo_softc *sc)
ether_input_mbuf(ifp, m);
ifp->if_ipackets++;
}
+}
- m_freem(m);
+void
+cmalo_start(struct ifnet *ifp)
+{
+ struct malo_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct mbuf *m;
+
+ for (;;) {
+ IF_POLL(&ic->ic_mgtq, m);
+ if (m != NULL) {
+ IF_DEQUEUE(&ic->ic_mgtq, m);
+ /* all mgmt frames are handled by the FW */
+ }
+
+ IFQ_POLL(&ifp->if_snd, m);
+ if (m != NULL) {
+ IFQ_DEQUEUE(&ifp->if_snd, m);
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+ if (cmalo_tx(sc, m) != 0) {
+ ifp->if_oerrors++;
+ break;
+ }
+ } else
+ break;
+ }
+}
+
+int
+cmalo_tx(struct malo_softc *sc, struct mbuf *m)
+{
+ struct malo_tx_desc *txdesc = sc->sc_data;
+ uint8_t *data;
+ uint16_t psize, *uc;
+ int i;
+
+ bzero(sc->sc_data, sizeof(*txdesc));
+ psize = sizeof(*txdesc) + m->m_pkthdr.len;
+ data = mtod(m, uint8_t *);
+
+ /* prepare TX descriptor */
+ txdesc->pkgoffset = htole32(sizeof(*txdesc));
+ txdesc->pkglen = htole16(m->m_pkthdr.len);
+ bcopy(data, txdesc->dstaddrhigh, ETHER_ADDR_LEN);
+
+ /* copy mbuf packet to the buffer */
+ bcopy(data, sc->sc_data + sizeof(*txdesc), m->m_pkthdr.len);
+
+ /* send TX packet to the device */
+ MALO_WRITE_2(sc, MALO_REG_DATA_WRITE_LEN, psize);
+ uc = (uint16_t *)sc->sc_data;
+ for (i = 0; i < psize / 2; i++)
+ MALO_WRITE_2(sc, MALO_REG_DATA_WRITE, uc[i]);
+ if (psize & 0x0001)
+ MALO_WRITE_1(sc, MALO_REG_DATA_WRITE, uc[i]);
+ MALO_WRITE_1(sc, MALO_REG_HOST_STATUS, MALO_VAL_TX_DL_OVER);
+ MALO_WRITE_2(sc, MALO_REG_CARD_INTR_CAUSE, MALO_VAL_TX_DL_OVER);
+
+ DPRINTF(2, "%s: TX pkglen=%d, pkgoffset=%d\n",
+ sc->sc_dev.dv_xname, txdesc->pkglen, txdesc->pkgoffset);
+
+ return (0);
}
void
@@ -1005,6 +1104,65 @@ cmalo_cmd_set_macctrl(struct malo_softc *sc)
}
int
+cmalo_cmd_set_assoc(struct malo_softc *sc)
+{
+ struct malo_cmd_header *hdr = sc->sc_cmd;
+ struct malo_cmd_body_assoc *body;
+ struct malo_cmd_body_assoc_ssid *body_ssid;
+ struct malo_cmd_body_assoc_phy *body_phy;
+ struct malo_cmd_body_assoc_cf *body_cf;
+ struct malo_cmd_body_assoc_rate *body_rate;
+ uint16_t psize;
+ uint8_t ap[] = { 0x00, 0x17, 0x9a, 0x44, 0xda, 0x83 }; /* XXX */
+ uint8_t chan[] = { 0x01 }; /* XXX */
+
+ bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
+ psize = sizeof(*hdr) + sizeof(*body);
+
+ hdr->cmd = htole16(MALO_CMD_ASSOC);
+ hdr->seqnum = htole16(1);
+ hdr->result = 0;
+
+ body = (struct malo_cmd_body_assoc *)(hdr + 1);
+ bcopy(ap, body->peermac, ETHER_ADDR_LEN);
+ body->capinfo = 0;
+ body->listenintrv = htole16(10);
+
+ body_ssid = sc->sc_cmd + psize;
+ body_ssid->type = htole16(MALO_TLV_TYPE_SSID);
+ body_ssid->size = htole16(6);
+ bcopy("nazgul", body_ssid->data, 6);
+ psize += (sizeof(*body_ssid) - 1) + body_ssid->size;
+
+ body_phy = sc->sc_cmd + psize;
+ body_phy->type = htole16(MALO_TLV_TYPE_PHY);
+ body_phy->size = htole16(1);
+ bcopy(chan, body_phy->data, 1);
+ psize += sizeof(*body_phy);
+
+ body_cf = sc->sc_cmd + psize;
+ body_cf->type = htole16(MALO_TLV_TYPE_CF);
+ body_cf->size = htole16(0);
+ psize += sizeof(*body_cf);
+
+ body_rate = sc->sc_cmd + psize;
+ body_rate->type = htole16(MALO_TLV_TYPE_RATES);
+ body_rate->size = htole16(0);
+ psize += sizeof(*body_rate);
+
+ hdr->size = htole16(psize - sizeof(*hdr));
+
+ /* process command request */
+ if (cmalo_cmd_request(sc, psize, 0) != 0)
+ return (EIO);
+
+ /* process command repsonse */
+ cmalo_cmd_response(sc);
+
+ return (0);
+}
+
+int
cmalo_cmd_request(struct malo_softc *sc, uint16_t psize, int no_response)
{
uint16_t *uc;
@@ -1026,7 +1184,7 @@ cmalo_cmd_request(struct malo_softc *sc, uint16_t psize, int no_response)
/* wait for the command response */
sc->sc_cmd_running = 1;
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < 50; i++) {
if (sc->sc_cmd_running == 0)
break;
tsleep(sc, 0, "malocmd", 1);
@@ -1045,7 +1203,9 @@ cmalo_cmd_response(struct malo_softc *sc)
{
struct malo_cmd_header *hdr = sc->sc_cmd;
uint16_t psize, *uc;
- int i;
+ int i, s;
+
+ s = splnet(); /* XXX */
bzero(sc->sc_cmd, MALO_CMD_BUFFER_SIZE);
@@ -1117,5 +1277,7 @@ cmalo_cmd_response(struct malo_softc *sc)
break;
}
+ splx(s);
+
return (0);
}
diff --git a/sys/dev/pcmcia/if_maloreg.h b/sys/dev/pcmcia/if_maloreg.h
index aa8563b990f..d2ac2e2654a 100644
--- a/sys/dev/pcmcia/if_maloreg.h
+++ b/sys/dev/pcmcia/if_maloreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_maloreg.h,v 1.5 2007/06/01 23:43:32 mglocker Exp $ */
+/* $OpenBSD: if_maloreg.h,v 1.6 2007/06/08 22:08:21 mglocker Exp $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
@@ -22,6 +22,8 @@
#define MALO_REG_HOST_INTR_MASK 0x04
#define MALO_REG_DATA_READ 0x10
#define MALO_REG_CMD_READ 0x12
+#define MALO_REG_DATA_WRITE_LEN 0x14
+#define MALO_REG_DATA_WRITE 0x16
#define MALO_REG_CMD_WRITE_LEN 0x18
#define MALO_REG_CMD_WRITE 0x1a
#define MALO_REG_CARD_STATUS 0x20
@@ -36,10 +38,12 @@
#define MALO_VAL_SCRATCH_READY 0x00
#define MALO_VAL_SCRATCH_FW_LOADED 0x5a
#define MALO_VAL_HOST_INTR_MASK_ON 0x001f
-#define MALO_VAL_DATA_DL_OVER 0x02
+#define MALO_VAL_TX_DL_OVER 0x01
+#define MALO_VAL_RX_DL_OVER 0x02
#define MALO_VAL_CMD_DL_OVER 0x04
/* interrupt reasons */
+#define MALO_VAL_HOST_INTR_TX (1 << 0)
#define MALO_VAL_HOST_INTR_RX (1 << 1)
#define MALO_VAL_HOST_INTR_CMD (1 << 3)
@@ -47,13 +51,12 @@
#define MALO_CMD_RESP 0x8000
#define MALO_CMD_HWSPEC 0x0003
#define MALO_CMD_RESET 0x0005
-#define MALO_CMD_STATUS 0x000a
#define MALO_CMD_RADIO 0x001c
#define MALO_CMD_CHANNEL 0x001d
#define MALO_CMD_TXPOWER 0x001e
#define MALO_CMD_ANTENNA 0x0020
#define MALO_CMD_MACCTRL 0x0028
-#define MALO_CMD_MACADDR 0x004d
+#define MALO_CMD_ASSOC 0x0050
/* FW command values */
#define MALO_CMD_RADIO_OFF 0x0000
diff --git a/sys/dev/pcmcia/if_malovar.h b/sys/dev/pcmcia/if_malovar.h
index 3458981c9bf..f54d5409b29 100644
--- a/sys/dev/pcmcia/if_malovar.h
+++ b/sys/dev/pcmcia/if_malovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_malovar.h,v 1.8 2007/06/04 20:29:51 mglocker Exp $ */
+/* $OpenBSD: if_malovar.h,v 1.9 2007/06/08 22:08:21 mglocker Exp $ */
/*
* Copyright (c) 2007 Marcus Glocker <mglocker@openbsd.org>
@@ -48,6 +48,7 @@ struct malo_cmd_header {
uint16_t size;
uint16_t seqnum;
uint16_t result;
+ /* malo_cmd_body */
};
/* FW command bodies */
@@ -94,6 +95,42 @@ struct malo_cmd_body_macctrl {
uint16_t reserved;
} __packed;
+struct malo_cmd_body_assoc {
+ uint8_t peermac[ETHER_ADDR_LEN];
+ uint16_t capinfo;
+ uint16_t listenintrv;
+ uint16_t bcnperiod;
+ uint8_t dtimperiod;
+ /* malo_cmd_body_assoc_ssid */
+ /* malo_cmd_body_assoc_phy */
+ /* malo_cmd_body_assoc_cf */
+ /* malo_cmd_body_assoc_rate */
+} __packed;
+#define MALO_TLV_TYPE_SSID 0x0000
+#define MALO_TLV_TYPE_PHY 0x0003
+#define MALO_TLV_TYPE_CF 0x0004
+#define MALO_TLV_TYPE_RATES 0x0001
+struct malo_cmd_body_assoc_ssid {
+ uint16_t type;
+ uint16_t size;
+ uint8_t data[1];
+} __packed;
+struct malo_cmd_body_assoc_phy {
+ uint16_t type;
+ uint16_t size;
+ uint8_t data[1];
+} __packed;
+struct malo_cmd_body_assoc_cf {
+ uint16_t type;
+ uint16_t size;
+ uint8_t data[1];
+} __packed;
+struct malo_cmd_body_assoc_rate {
+ uint16_t type;
+ uint16_t size;
+ uint8_t data[1];
+} __packed;
+
/* RX descriptor */
#define MALO_RX_STATUS_OK 0x0001
struct malo_rx_desc {
@@ -109,6 +146,19 @@ struct malo_rx_desc {
uint8_t reserved2[3];
} __packed;
+/* TX descriptor */
+struct malo_tx_desc {
+ uint32_t status;
+ uint32_t control;
+ uint32_t pkgoffset;
+ uint16_t pkglen;
+ uint8_t dstaddrhigh[2];
+ uint8_t dstaddrlow[4];
+ uint8_t priority;
+ uint8_t flags;
+ uint8_t reserved[2];
+} __packed;
+
struct malo_softc {
struct device sc_dev;
struct ieee80211com sc_ic;