diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2007-06-07 20:20:16 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2007-06-07 20:20:16 +0000 |
commit | 2151f4451c5f87978d5c21794dc33a45a8b6b11c (patch) | |
tree | 50d4fb653e63bb21e53567c66208d43fefe67c39 /sys/dev/ic/atw.c | |
parent | a6375dcfa344ccca09970470724321331cb34fd6 (diff) |
move ieee80211_compute_duration() and ieee80211_compute_duration1()
functions into the two drivers that use them (atw and rtw.)
this code is not generic enough to be used by other drivers and
there is no chance that it will ever be used in newer driver since
it supports 802.11b only.
plus, it hurts my eyes each time i look into ieee80211_output.c.
"fine with me as long as the logic doesn't change in the functions" jsg@
Diffstat (limited to 'sys/dev/ic/atw.c')
-rw-r--r-- | sys/dev/ic/atw.c | 172 |
1 files changed, 170 insertions, 2 deletions
diff --git a/sys/dev/ic/atw.c b/sys/dev/ic/atw.c index 02bdc497f9e..a6a42f15b75 100644 --- a/sys/dev/ic/atw.c +++ b/sys/dev/ic/atw.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atw.c,v 1.52 2007/02/14 04:49:43 jsg Exp $ */ +/* $OpenBSD: atw.c,v 1.53 2007/06/07 20:20:15 damien Exp $ */ /* $NetBSD: atw.c,v 1.69 2004/07/23 07:07:55 dyoung Exp $ */ /*- @@ -255,6 +255,9 @@ void atw_node_free(struct ieee80211com *, struct ieee80211_node *); static __inline uint32_t atw_last_even_tsft(uint32_t, uint32_t, uint32_t); uint64_t atw_get_tsft(struct atw_softc *sc); void atw_change_ibss(struct atw_softc *); +int atw_compute_duration1(int, int, uint32_t, int, struct atw_duration *); +int atw_compute_duration(struct ieee80211_frame *, int, uint32_t, int, + int, struct atw_duration *, struct atw_duration *, int *, int); /* * Tuner/transceiver/modem @@ -3410,6 +3413,171 @@ atw_watchdog(struct ifnet *ifp) ieee80211_watchdog(ifp); } +/* + * Arguments in: + * + * paylen: payload length (no FCS, no WEP header) + * + * hdrlen: header length + * + * rate: MSDU speed, units 500kb/s + * + * flags: IEEE80211_F_SHPREAMBLE (use short preamble), + * IEEE80211_F_SHSLOT (use short slot length) + * + * Arguments out: + * + * d: 802.11 Duration field for RTS, + * 802.11 Duration field for data frame, + * PLCP Length for data frame, + * residual octets at end of data slot + */ +int +atw_compute_duration1(int len, int use_ack, uint32_t flags, int rate, + struct atw_duration *d) +{ + int pre, ctsrate; + int ack, bitlen, data_dur, remainder; + + /* RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK + * DATA reserves medium for SIFS | ACK + * + * XXXMYC: no ACK on multicast/broadcast or control packets + */ + + bitlen = len * 8; + + pre = IEEE80211_DUR_DS_SIFS; + if ((flags & IEEE80211_F_SHPREAMBLE) != 0) + pre += IEEE80211_DUR_DS_SHORT_PREAMBLE + + IEEE80211_DUR_DS_FAST_PLCPHDR; + else + pre += IEEE80211_DUR_DS_LONG_PREAMBLE + + IEEE80211_DUR_DS_SLOW_PLCPHDR; + + d->d_residue = 0; + data_dur = (bitlen * 2) / rate; + remainder = (bitlen * 2) % rate; + if (remainder != 0) { + d->d_residue = (rate - remainder) / 16; + data_dur++; + } + + switch (rate) { + case 2: /* 1 Mb/s */ + case 4: /* 2 Mb/s */ + /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */ + ctsrate = 2; + break; + case 11: /* 5.5 Mb/s */ + case 22: /* 11 Mb/s */ + case 44: /* 22 Mb/s */ + /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */ + ctsrate = 4; + break; + default: + /* TBD */ + return -1; + } + + d->d_plcp_len = data_dur; + + ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0; + + d->d_rts_dur = + pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate + + pre + data_dur + + ack; + + d->d_data_dur = ack; + + return 0; +} + +/* + * Arguments in: + * + * wh: 802.11 header + * + * len: packet length + * + * rate: MSDU speed, units 500kb/s + * + * fraglen: fragment length, set to maximum (or higher) for no + * fragmentation + * + * flags: IEEE80211_F_WEPON (hardware adds WEP), + * IEEE80211_F_SHPREAMBLE (use short preamble), + * IEEE80211_F_SHSLOT (use short slot length) + * + * Arguments out: + * + * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields + * of first/only fragment + * + * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields + * of first/only fragment + */ +int +atw_compute_duration(struct ieee80211_frame *wh, int len, uint32_t flags, + int fraglen, int rate, struct atw_duration *d0, struct atw_duration *dn, + int *npktp, int debug) +{ + int ack, rc; + int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen; + + if ((wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) == IEEE80211_FC1_DIR_DSTODS) + hdrlen = sizeof(struct ieee80211_frame_addr4); + else + hdrlen = sizeof(struct ieee80211_frame); + + paylen = len - hdrlen; + + if ((flags & IEEE80211_F_WEPON) != 0) + overlen = IEEE80211_WEP_TOTLEN + IEEE80211_CRC_LEN; + else + overlen = IEEE80211_CRC_LEN; + + npkt = paylen / fraglen; + lastlen0 = paylen % fraglen; + + if (npkt == 0) /* no fragments */ + lastlen = paylen + overlen; + else if (lastlen0 != 0) { /* a short "tail" fragment */ + lastlen = lastlen0 + overlen; + npkt++; + } else /* full-length "tail" fragment */ + lastlen = fraglen + overlen; + + if (npktp != NULL) + *npktp = npkt; + + if (npkt > 1) + firstlen = fraglen + overlen; + else + firstlen = paylen + overlen; + + if (debug) { + printf("%s: npkt %d firstlen %d lastlen0 %d lastlen %d " + "fraglen %d overlen %d len %d rate %d flags %08x\n", + __func__, npkt, firstlen, lastlen0, lastlen, fraglen, + overlen, len, rate, flags); + } + + ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) && + (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL; + + rc = atw_compute_duration1(firstlen + hdrlen, ack, flags, rate, d0); + if (rc == -1) + return rc; + + if (npkt <= 1) { + *dn = *d0; + return 0; + } + return atw_compute_duration1(lastlen + hdrlen, ack, flags, rate, dn); +} + #ifdef ATW_DEBUG void atw_dump_pkt(struct ifnet *ifp, struct mbuf *m0) @@ -3520,7 +3688,7 @@ atw_start(struct ifnet *ifp) else rate = MAX(2, ieee80211_get_rate(ic)); - if (ieee80211_compute_duration(wh, m0->m_pkthdr.len, + if (atw_compute_duration(wh, m0->m_pkthdr.len, ic->ic_flags & ~IEEE80211_F_WEPON, ic->ic_fragthreshold, rate, &txs->txs_d0, &txs->txs_dn, &npkt, (sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) == |