diff options
-rw-r--r-- | sys/dev/pcmcia/if_malo.c | 176 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_maloreg.h | 11 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_malovar.h | 52 |
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; |