summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/ic/malo.c134
-rw-r--r--sys/dev/ic/malo.h3
2 files changed, 132 insertions, 5 deletions
diff --git a/sys/dev/ic/malo.c b/sys/dev/ic/malo.c
index b7722cf8a43..7f715619f3b 100644
--- a/sys/dev/ic/malo.c
+++ b/sys/dev/ic/malo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: malo.c,v 1.33 2006/11/23 22:03:07 mglocker Exp $ */
+/* $OpenBSD: malo.c,v 1.34 2006/11/24 20:45:33 mglocker Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -122,6 +122,7 @@ struct malo_tx_desc {
#define MALO_CMD_SET_ANTENNA 0x0020
#define MALO_CMD_SET_PRESCAN 0x0107
#define MALO_CMD_SET_POSTSCAN 0x0108
+#define MALO_CMD_SET_RATE 0x0110
#define MALO_CMD_SET_CHANNEL 0x010a
#define MALO_CMD_SET_RTS 0x0113
#define MALO_CMD_RESPONSE 0x8000
@@ -194,6 +195,12 @@ struct malo_cmd_channel {
uint8_t channel;
} __packed;
+struct malo_cmd_rate {
+ uint8_t dataratetype;
+ uint8_t rateindex;
+ uint8_t aprates[14];
+} __packed;
+
#define malo_mem_write4(sc, off, x) \
bus_space_write_4((sc)->sc_mem1_bt, (sc)->sc_mem1_bh, (off), (x))
#define malo_mem_write2(sc, off, x) \
@@ -241,6 +248,8 @@ void malo_newassoc(struct ieee80211com *ic, struct ieee80211_node *ni,
struct ieee80211_node *
malo_node_alloc(struct ieee80211com *ic);
int malo_media_change(struct ifnet *ifp);
+void malo_media_status(struct ifnet *ifp, struct ifmediareq *imr);
+int malo_chip2rate(int chip_rate);
void malo_next_scan(void *arg);
void malo_tx_intr(struct malo_softc *sc);
int malo_tx_mgt(struct malo_softc *sc, struct mbuf *m0,
@@ -271,6 +280,7 @@ int malo_cmd_set_aid(struct malo_softc *sc, uint8_t *bssid,
uint16_t associd);
int malo_cmd_set_txpower(struct malo_softc *sc, unsigned int powerlevel);
int malo_cmd_set_rts(struct malo_softc *sc, uint32_t threshold);
+int malo_cmd_set_rate(struct malo_softc *sc, uint8_t rate);
/* supported rates */
const struct ieee80211_rateset malo_rates_11b =
@@ -382,7 +392,7 @@ malo_attach(struct malo_softc *sc)
ic->ic_newassoc = malo_newassoc;
ic->ic_node_alloc = malo_node_alloc;
- ieee80211_media_init(ifp, malo_media_change, ieee80211_media_status);
+ ieee80211_media_init(ifp, malo_media_change, malo_media_status);
#if NBPFILTER > 0
bpfattach(&sc->sc_drvbpf, ifp, DLT_IEEE802_11_RADIO,
@@ -1027,13 +1037,19 @@ malo_stop(struct malo_softc *sc)
if (ifp->if_flags & IFF_RUNNING)
malo_cmd_reset(sc);
+ /* device is not running anymore */
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ /* change back to initial state */
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+ /* reset RX / TX rings */
malo_reset_tx_ring(sc, &sc->sc_txring);
malo_reset_rx_ring(sc, &sc->sc_rxring);
+ /* set initial rate */
+ sc->sc_last_txrate = 0;
+
/* power off cardbus socket */
if (sc->sc_disable)
sc->sc_disable(sc);
@@ -1082,7 +1098,6 @@ malo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
break;
case IEEE80211_S_ASSOC:
DPRINTF(("newstate ASSOC\n"));
-#if 0
if (ic->ic_flags & IEEE80211_F_SHPREAMBLE)
malo_cmd_set_radio(sc, 1, 3); /* short preamble */
else
@@ -1090,7 +1105,13 @@ malo_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
malo_cmd_set_aid(sc, ic->ic_bss->ni_bssid,
ic->ic_bss->ni_associd);
-#endif
+
+ if (ic->ic_fixed_rate == -1)
+ /* automatic rate adaption */
+ malo_cmd_set_rate(sc, 0);
+ else
+ /* fixed rate */
+ malo_cmd_set_rate(sc, 0); /* XXX */
break;
case IEEE80211_S_RUN:
DPRINTF(("newstate RUN\n"));
@@ -1140,6 +1161,63 @@ malo_media_change(struct ifnet *ifp)
}
void
+malo_media_status(struct ifnet *ifp, struct ifmediareq *imr)
+{
+ struct malo_softc *sc = ifp->if_softc;
+ struct ieee80211com *ic = &sc->sc_ic;
+ int rate;
+
+ imr->ifm_status = IFM_AVALID;
+ imr->ifm_active = IFM_IEEE80211;
+ if (ic->ic_state == IEEE80211_S_RUN)
+ imr->ifm_status |= IFM_ACTIVE;
+
+ /* convert chip bitmap rate to 802.11 rate */
+ rate = malo_chip2rate(sc->sc_last_txrate);
+ imr->ifm_active |= ieee80211_rate2media(ic, rate, ic->ic_curmode);
+
+ switch (ic->ic_opmode) {
+ case IEEE80211_M_STA:
+ break;
+ case IEEE80211_M_IBSS:
+ imr->ifm_active |= IFM_IEEE80211_ADHOC;
+ break;
+ case IEEE80211_M_MONITOR:
+ imr->ifm_active |= IFM_IEEE80211_MONITOR;
+ break;
+ case IEEE80211_M_AHDEMO:
+ break;
+ case IEEE80211_M_HOSTAP:
+ break;
+ }
+}
+
+int
+malo_chip2rate(int chip_rate)
+{
+ switch (chip_rate) {
+ /* CCK rates */
+ case 0: return 2;
+ case 1: return 4;
+ case 2: return 11;
+ case 3: return 22;
+
+ /* OFDM rates */
+ case 5: return 12;
+ case 6: return 18;
+ case 7: return 24;
+ case 8: return 36;
+ case 9: return 48;
+ case 10: return 72;
+ case 11: return 96;
+ case 12: return 108;
+
+ /* unknown rate: should not happen */
+ default: return 0;
+ }
+}
+
+void
malo_next_scan(void *arg)
{
struct malo_softc *sc = arg;
@@ -1195,6 +1273,9 @@ malo_tx_intr(struct malo_softc *sc)
break;
}
+ /* save last used TX rate */
+ sc->sc_last_txrate = desc->datarate;
+
/* cleanup TX data and TX descritpor */
bus_dmamap_sync(sc->sc_dmat, data->map, 0,
data->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
@@ -2032,3 +2113,48 @@ malo_cmd_set_rts(struct malo_softc *sc, uint32_t threshold)
return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
}
+
+int
+malo_cmd_set_rate(struct malo_softc *sc, uint8_t rate)
+{
+ struct ieee80211com *ic = &sc->sc_ic;
+ struct malo_cmdheader *hdr = sc->sc_cmd_mem;
+ struct malo_cmd_rate *body;
+
+ hdr->cmd = htole16(MALO_CMD_SET_RATE);
+ hdr->size = htole16(sizeof(*hdr) + sizeof(*body));
+ hdr->seqnum = 1;
+ hdr->result = 0;
+ body = (struct malo_cmd_rate *)(hdr + 1);
+
+ bzero(body, sizeof(*body));
+
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
+ /* TODO */
+ } else {
+ body->aprates[0] = 2;
+ body->aprates[1] = 4;
+ body->aprates[2] = 11;
+ body->aprates[3] = 22;
+ if (ic->ic_curmode == IEEE80211_MODE_11G) {
+ body->aprates[4] = 0;
+ body->aprates[5] = 12;
+ body->aprates[6] = 18;
+ body->aprates[7] = 24;
+ body->aprates[8] = 36;
+ body->aprates[9] = 48;
+ body->aprates[10] = 72;
+ body->aprates[11] = 96;
+ body->aprates[12] = 108;
+ }
+ }
+
+ if (rate != 0) {
+ /* TODO */
+ }
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_cmd_dmam, 0, PAGE_SIZE,
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
+
+ return (malo_send_cmd_dma(sc, sc->sc_cmd_dmaaddr));
+}
diff --git a/sys/dev/ic/malo.h b/sys/dev/ic/malo.h
index 05b661f9e87..91634cf1ec8 100644
--- a/sys/dev/ic/malo.h
+++ b/sys/dev/ic/malo.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: malo.h,v 1.8 2006/11/07 21:39:32 mglocker Exp $ */
+/* $OpenBSD: malo.h,v 1.9 2006/11/24 20:45:33 mglocker Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@@ -105,6 +105,7 @@ struct malo_softc {
struct timeout sc_scan_to;
int sc_tx_timer;
+ int sc_last_txrate;
#if NBPFILTER > 0
caddr_t sc_drvbpf;