2005-06-20 06:49:18 +04:00
|
|
|
/* $NetBSD: rtw.c,v 1.47 2005/06/20 02:49:18 atatat Exp $ */
|
2004-09-26 06:29:15 +04:00
|
|
|
/*-
|
|
|
|
* Copyright (c) 2004, 2005 David Young. All rights reserved.
|
|
|
|
*
|
|
|
|
* Programmed for NetBSD by David Young.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
* 3. The name of David Young may not be used to endorse or promote
|
|
|
|
* products derived from this software without specific prior
|
|
|
|
* written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
|
|
|
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
|
|
|
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
|
|
|
|
* Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
|
|
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
|
|
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
|
|
* OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* Device driver for the Realtek RTL8180 802.11 MAC/BBP.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/cdefs.h>
|
2005-06-20 06:49:18 +04:00
|
|
|
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.47 2005/06/20 02:49:18 atatat Exp $");
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
#include "bpfilter.h"
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
#include <sys/sysctl.h>
|
2005-02-27 03:26:58 +03:00
|
|
|
#include <sys/systm.h>
|
2004-09-26 06:29:15 +04:00
|
|
|
#include <sys/callout.h>
|
2005-02-27 03:26:58 +03:00
|
|
|
#include <sys/mbuf.h>
|
2004-09-26 06:29:15 +04:00
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
|
|
|
#include <machine/endian.h>
|
|
|
|
#include <machine/bus.h>
|
|
|
|
#include <machine/intr.h> /* splnet */
|
|
|
|
|
|
|
|
#include <uvm/uvm_extern.h>
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
#include <net/if.h>
|
|
|
|
#include <net/if_media.h>
|
|
|
|
#include <net/if_ether.h>
|
|
|
|
|
|
|
|
#include <net80211/ieee80211_var.h>
|
|
|
|
#include <net80211/ieee80211_compat.h>
|
|
|
|
#include <net80211/ieee80211_radiotap.h>
|
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
#if NBPFILTER > 0
|
2004-09-26 06:29:15 +04:00
|
|
|
#include <net/bpf.h>
|
2005-02-27 03:26:58 +03:00
|
|
|
#endif
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
#include <dev/ic/rtwreg.h>
|
|
|
|
#include <dev/ic/rtwvar.h>
|
|
|
|
#include <dev/ic/rtwphyio.h>
|
|
|
|
#include <dev/ic/rtwphy.h>
|
|
|
|
|
|
|
|
#include <dev/ic/smc93cx6var.h>
|
|
|
|
|
|
|
|
#define KASSERT2(__cond, __msg) \
|
|
|
|
do { \
|
|
|
|
if (!(__cond)) \
|
|
|
|
panic __msg ; \
|
|
|
|
} while (0)
|
|
|
|
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
int rtw_rfprog_fallback = 0;
|
|
|
|
int rtw_host_rfio = 0;
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
#ifdef RTW_DEBUG
|
2004-12-25 09:58:37 +03:00
|
|
|
int rtw_debug = 0;
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
int rtw_rxbufs_limit = RTW_RXQLEN;
|
2004-09-26 06:29:15 +04:00
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
#define NEXT_ATTACH_STATE(sc, state) do { \
|
|
|
|
DPRINTF(sc, RTW_DEBUG_ATTACH, \
|
|
|
|
("%s: attach state %s\n", __func__, #state)); \
|
|
|
|
sc->sc_attach_state = state; \
|
2004-09-26 06:29:15 +04:00
|
|
|
} while (0)
|
|
|
|
|
2004-12-27 09:12:28 +03:00
|
|
|
int rtw_dwelltime = 200; /* milliseconds */
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-19 11:19:25 +03:00
|
|
|
static void rtw_start(struct ifnet *);
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
static void rtw_led_attach(struct rtw_led_state *, void *);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
static void rtw_led_init(struct rtw_regs *);
|
|
|
|
static void rtw_led_slowblink(void *);
|
|
|
|
static void rtw_led_fastblink(void *);
|
|
|
|
static void rtw_led_set(struct rtw_led_state *, struct rtw_regs *, int);
|
|
|
|
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
static int rtw_sysctl_verify_rfio(SYSCTLFN_PROTO);
|
|
|
|
static int rtw_sysctl_verify_rfprog(SYSCTLFN_PROTO);
|
|
|
|
#ifdef RTW_DEBUG
|
2004-12-25 09:58:37 +03:00
|
|
|
static void rtw_print_txdesc(struct rtw_softc *, const char *,
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
static int rtw_sysctl_verify_debug(SYSCTLFN_PROTO);
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
static int rtw_sysctl_verify_rxbufs_limit(SYSCTLFN_PROTO);
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup sysctl(3) MIB, hw.rtw.*
|
|
|
|
*
|
|
|
|
* TBD condition CTLFLAG_PERMANENT on being an LKM or not
|
|
|
|
*/
|
|
|
|
SYSCTL_SETUP(sysctl_rtw, "sysctl rtw(4) subtree setup")
|
|
|
|
{
|
|
|
|
int rc;
|
2005-06-20 06:49:18 +04:00
|
|
|
const struct sysctlnode *cnode, *rnode;
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
|
|
|
|
if ((rc = sysctl_createv(clog, 0, NULL, &rnode,
|
|
|
|
CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw", NULL,
|
|
|
|
NULL, 0, NULL, 0, CTL_HW, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
if ((rc = sysctl_createv(clog, 0, &rnode, &rnode,
|
|
|
|
CTLFLAG_PERMANENT, CTLTYPE_NODE, "rtw",
|
|
|
|
"Realtek RTL818x 802.11 controls",
|
|
|
|
NULL, 0, NULL, 0, CTL_CREATE, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
/* control debugging printfs */
|
|
|
|
if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
|
|
|
|
"debug", SYSCTL_DESCR("Enable RTL818x debugging output"),
|
|
|
|
rtw_sysctl_verify_debug, 0, &rtw_debug, 0,
|
|
|
|
CTL_CREATE, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
|
|
|
|
/* Limit rx buffers, for simulating resource exhaustion. */
|
|
|
|
if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
|
|
|
|
"rxbufs_limit",
|
|
|
|
SYSCTL_DESCR("Set rx buffers limit"),
|
|
|
|
rtw_sysctl_verify_rxbufs_limit, 0, &rtw_rxbufs_limit, 0,
|
|
|
|
CTL_CREATE, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
/* set fallback RF programming method */
|
|
|
|
if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
|
|
|
|
"rfprog_fallback",
|
|
|
|
SYSCTL_DESCR("Set fallback RF programming method"),
|
|
|
|
rtw_sysctl_verify_rfprog, 0, &rtw_rfprog_fallback, 0,
|
|
|
|
CTL_CREATE, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* force host to control RF I/O bus */
|
|
|
|
if ((rc = sysctl_createv(clog, 0, &rnode, &cnode,
|
|
|
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
|
|
|
|
"host_rfio", SYSCTL_DESCR("Enable host control of RF I/O"),
|
|
|
|
rtw_sysctl_verify_rfio, 0, &rtw_host_rfio, 0,
|
|
|
|
CTL_CREATE, CTL_EOL)) != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
return;
|
|
|
|
err:
|
|
|
|
printf("%s: sysctl_createv failed (rc = %d)\n", __func__, rc);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rtw_sysctl_verify(SYSCTLFN_ARGS, int lower, int upper)
|
|
|
|
{
|
|
|
|
int error, t;
|
|
|
|
struct sysctlnode node;
|
|
|
|
|
|
|
|
node = *rnode;
|
|
|
|
t = *(int*)rnode->sysctl_data;
|
|
|
|
node.sysctl_data = &t;
|
|
|
|
error = sysctl_lookup(SYSCTLFN_CALL(&node));
|
|
|
|
if (error || newp == NULL)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
if (t < lower || t > upper)
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
*(int*)rnode->sysctl_data = t;
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rtw_sysctl_verify_rfprog(SYSCTLFN_ARGS)
|
|
|
|
{
|
2005-06-10 06:35:34 +04:00
|
|
|
return rtw_sysctl_verify(SYSCTLFN_CALL(__UNCONST(rnode)), 0,
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
MASK_AND_RSHIFT(RTW_CONFIG4_RFTYPE_MASK, RTW_CONFIG4_RFTYPE_MASK));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rtw_sysctl_verify_rfio(SYSCTLFN_ARGS)
|
|
|
|
{
|
2005-06-10 06:35:34 +04:00
|
|
|
return rtw_sysctl_verify(SYSCTLFN_CALL(__UNCONST(rnode)), 0, 1);
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
#ifdef RTW_DEBUG
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
static int
|
|
|
|
rtw_sysctl_verify_debug(SYSCTLFN_ARGS)
|
|
|
|
{
|
2005-06-10 06:35:34 +04:00
|
|
|
return rtw_sysctl_verify(SYSCTLFN_CALL(__UNCONST(rnode)),
|
|
|
|
0, RTW_DEBUG_MAX);
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
}
|
|
|
|
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
static int
|
|
|
|
rtw_sysctl_verify_rxbufs_limit(SYSCTLFN_ARGS)
|
|
|
|
{
|
2005-06-10 06:35:34 +04:00
|
|
|
return rtw_sysctl_verify(SYSCTLFN_CALL(__UNCONST(rnode)),
|
|
|
|
0, RTW_RXQLEN);
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static void
|
|
|
|
rtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where)
|
|
|
|
{
|
2004-12-25 09:58:37 +03:00
|
|
|
#define PRINTREG32(sc, reg) \
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_REGDUMP, \
|
|
|
|
("%s: reg[ " #reg " / %03x ] = %08x\n", \
|
2004-09-26 06:29:15 +04:00
|
|
|
dvname, reg, RTW_READ(regs, reg)))
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
#define PRINTREG16(sc, reg) \
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_REGDUMP, \
|
|
|
|
("%s: reg[ " #reg " / %03x ] = %04x\n", \
|
2004-09-26 06:29:15 +04:00
|
|
|
dvname, reg, RTW_READ16(regs, reg)))
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
#define PRINTREG8(sc, reg) \
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_REGDUMP, \
|
|
|
|
("%s: reg[ " #reg " / %03x ] = %02x\n", \
|
2004-09-26 06:29:15 +04:00
|
|
|
dvname, reg, RTW_READ8(regs, reg)))
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_REGDUMP, ("%s: %s\n", dvname, where));
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
PRINTREG32(regs, RTW_IDR0);
|
|
|
|
PRINTREG32(regs, RTW_IDR1);
|
|
|
|
PRINTREG32(regs, RTW_MAR0);
|
|
|
|
PRINTREG32(regs, RTW_MAR1);
|
|
|
|
PRINTREG32(regs, RTW_TSFTRL);
|
|
|
|
PRINTREG32(regs, RTW_TSFTRH);
|
|
|
|
PRINTREG32(regs, RTW_TLPDA);
|
|
|
|
PRINTREG32(regs, RTW_TNPDA);
|
|
|
|
PRINTREG32(regs, RTW_THPDA);
|
|
|
|
PRINTREG32(regs, RTW_TCR);
|
|
|
|
PRINTREG32(regs, RTW_RCR);
|
|
|
|
PRINTREG32(regs, RTW_TINT);
|
|
|
|
PRINTREG32(regs, RTW_TBDA);
|
|
|
|
PRINTREG32(regs, RTW_ANAPARM);
|
|
|
|
PRINTREG32(regs, RTW_BB);
|
|
|
|
PRINTREG32(regs, RTW_PHYCFG);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP0L);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP0H);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP1L);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP1H);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP2LL);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP2LH);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP2HL);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP2HH);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP3LL);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP3LH);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP3HL);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP3HH);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP4LL);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP4LH);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP4HL);
|
|
|
|
PRINTREG32(regs, RTW_WAKEUP4HH);
|
|
|
|
PRINTREG32(regs, RTW_DK0);
|
|
|
|
PRINTREG32(regs, RTW_DK1);
|
|
|
|
PRINTREG32(regs, RTW_DK2);
|
|
|
|
PRINTREG32(regs, RTW_DK3);
|
|
|
|
PRINTREG32(regs, RTW_RETRYCTR);
|
|
|
|
PRINTREG32(regs, RTW_RDSAR);
|
|
|
|
PRINTREG32(regs, RTW_FER);
|
|
|
|
PRINTREG32(regs, RTW_FEMR);
|
|
|
|
PRINTREG32(regs, RTW_FPSR);
|
|
|
|
PRINTREG32(regs, RTW_FFER);
|
|
|
|
|
|
|
|
/* 16-bit registers */
|
|
|
|
PRINTREG16(regs, RTW_BRSR);
|
|
|
|
PRINTREG16(regs, RTW_IMR);
|
|
|
|
PRINTREG16(regs, RTW_ISR);
|
|
|
|
PRINTREG16(regs, RTW_BCNITV);
|
|
|
|
PRINTREG16(regs, RTW_ATIMWND);
|
|
|
|
PRINTREG16(regs, RTW_BINTRITV);
|
|
|
|
PRINTREG16(regs, RTW_ATIMTRITV);
|
|
|
|
PRINTREG16(regs, RTW_CRC16ERR);
|
|
|
|
PRINTREG16(regs, RTW_CRC0);
|
|
|
|
PRINTREG16(regs, RTW_CRC1);
|
|
|
|
PRINTREG16(regs, RTW_CRC2);
|
|
|
|
PRINTREG16(regs, RTW_CRC3);
|
|
|
|
PRINTREG16(regs, RTW_CRC4);
|
|
|
|
PRINTREG16(regs, RTW_CWR);
|
|
|
|
|
|
|
|
/* 8-bit registers */
|
|
|
|
PRINTREG8(regs, RTW_CR);
|
|
|
|
PRINTREG8(regs, RTW_9346CR);
|
|
|
|
PRINTREG8(regs, RTW_CONFIG0);
|
|
|
|
PRINTREG8(regs, RTW_CONFIG1);
|
|
|
|
PRINTREG8(regs, RTW_CONFIG2);
|
|
|
|
PRINTREG8(regs, RTW_MSR);
|
|
|
|
PRINTREG8(regs, RTW_CONFIG3);
|
|
|
|
PRINTREG8(regs, RTW_CONFIG4);
|
|
|
|
PRINTREG8(regs, RTW_TESTR);
|
|
|
|
PRINTREG8(regs, RTW_PSR);
|
|
|
|
PRINTREG8(regs, RTW_SCR);
|
|
|
|
PRINTREG8(regs, RTW_PHYDELAY);
|
|
|
|
PRINTREG8(regs, RTW_CRCOUNT);
|
|
|
|
PRINTREG8(regs, RTW_PHYADDR);
|
|
|
|
PRINTREG8(regs, RTW_PHYDATAW);
|
|
|
|
PRINTREG8(regs, RTW_PHYDATAR);
|
|
|
|
PRINTREG8(regs, RTW_CONFIG5);
|
|
|
|
PRINTREG8(regs, RTW_TPPOLL);
|
|
|
|
|
|
|
|
PRINTREG16(regs, RTW_BSSID16);
|
|
|
|
PRINTREG32(regs, RTW_BSSID32);
|
|
|
|
#undef PRINTREG32
|
|
|
|
#undef PRINTREG16
|
|
|
|
#undef PRINTREG8
|
|
|
|
}
|
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
|
|
|
|
void
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_continuous_tx_enable(struct rtw_softc *sc, int enable)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
|
|
|
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t tcr;
|
2004-09-26 06:29:15 +04:00
|
|
|
tcr = RTW_READ(regs, RTW_TCR);
|
|
|
|
tcr &= ~RTW_TCR_LBK_MASK;
|
|
|
|
if (enable)
|
|
|
|
tcr |= RTW_TCR_LBK_CONT;
|
|
|
|
else
|
|
|
|
tcr |= RTW_TCR_LBK_NORMAL;
|
|
|
|
RTW_WRITE(regs, RTW_TCR, tcr);
|
|
|
|
RTW_SYNC(regs, RTW_TCR, RTW_TCR);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_ANAPARM);
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
rtw_txdac_enable(sc, !enable);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_ANAPARM);/* XXX Voodoo from Linux. */
|
|
|
|
rtw_set_access(regs, RTW_ACCESS_NONE);
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
}
|
|
|
|
|
2004-12-27 01:59:41 +03:00
|
|
|
#ifdef RTW_DEBUG
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
static const char *
|
|
|
|
rtw_access_string(enum rtw_access access)
|
|
|
|
{
|
|
|
|
switch (access) {
|
|
|
|
case RTW_ACCESS_NONE:
|
|
|
|
return "none";
|
|
|
|
case RTW_ACCESS_CONFIG:
|
|
|
|
return "config";
|
|
|
|
case RTW_ACCESS_ANAPARM:
|
|
|
|
return "anaparm";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
2004-12-27 01:59:41 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
|
|
|
|
static void
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess)
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
{
|
|
|
|
KASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
KASSERT(regs->r_access >= RTW_ACCESS_NONE &&
|
|
|
|
regs->r_access <= RTW_ACCESS_ANAPARM);
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if (naccess == regs->r_access)
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
switch (naccess) {
|
|
|
|
case RTW_ACCESS_NONE:
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
switch (regs->r_access) {
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
case RTW_ACCESS_ANAPARM:
|
|
|
|
rtw_anaparm_enable(regs, 0);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case RTW_ACCESS_CONFIG:
|
|
|
|
rtw_config0123_enable(regs, 0);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case RTW_ACCESS_NONE:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case RTW_ACCESS_CONFIG:
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
switch (regs->r_access) {
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
case RTW_ACCESS_NONE:
|
|
|
|
rtw_config0123_enable(regs, 1);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case RTW_ACCESS_CONFIG:
|
|
|
|
break;
|
|
|
|
case RTW_ACCESS_ANAPARM:
|
|
|
|
rtw_anaparm_enable(regs, 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case RTW_ACCESS_ANAPARM:
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
switch (regs->r_access) {
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
case RTW_ACCESS_NONE:
|
|
|
|
rtw_config0123_enable(regs, 1);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case RTW_ACCESS_CONFIG:
|
|
|
|
rtw_anaparm_enable(regs, 1);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case RTW_ACCESS_ANAPARM:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
void
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(struct rtw_regs *regs, enum rtw_access access)
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
{
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access1(regs, access);
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ACCESS,
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
("%s: access %s -> %s\n", __func__,
|
|
|
|
rtw_access_string(regs->r_access),
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_access_string(access)));
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
regs->r_access = access;
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
/*
|
|
|
|
* Enable registers, switch register banks.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
rtw_config0123_enable(struct rtw_regs *regs, int enable)
|
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t ecr;
|
2004-09-26 06:29:15 +04:00
|
|
|
ecr = RTW_READ8(regs, RTW_9346CR);
|
|
|
|
ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK);
|
|
|
|
if (enable)
|
|
|
|
ecr |= RTW_9346CR_EEM_CONFIG;
|
2004-12-20 04:13:45 +03:00
|
|
|
else {
|
|
|
|
RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3));
|
2004-09-26 06:29:15 +04:00
|
|
|
ecr |= RTW_9346CR_EEM_NORMAL;
|
2004-12-20 04:13:45 +03:00
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_WRITE8(regs, RTW_9346CR, ecr);
|
|
|
|
RTW_SYNC(regs, RTW_9346CR, RTW_9346CR);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* requires rtw_config0123_enable(, 1) */
|
|
|
|
void
|
|
|
|
rtw_anaparm_enable(struct rtw_regs *regs, int enable)
|
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t cfg3;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
cfg3 = RTW_READ8(regs, RTW_CONFIG3);
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
cfg3 |= RTW_CONFIG3_CLKRUNEN;
|
|
|
|
if (enable)
|
|
|
|
cfg3 |= RTW_CONFIG3_PARMEN;
|
|
|
|
else
|
2004-09-26 06:29:15 +04:00
|
|
|
cfg3 &= ~RTW_CONFIG3_PARMEN;
|
|
|
|
RTW_WRITE8(regs, RTW_CONFIG3, cfg3);
|
|
|
|
RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* requires rtw_anaparm_enable(, 1) */
|
|
|
|
void
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
rtw_txdac_enable(struct rtw_softc *sc, int enable)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t anaparm;
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
anaparm = RTW_READ(regs, RTW_ANAPARM);
|
|
|
|
if (enable)
|
|
|
|
anaparm &= ~RTW_ANAPARM_TXDACOFF;
|
|
|
|
else
|
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
RTW_WRITE(regs, RTW_ANAPARM, anaparm);
|
|
|
|
RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_chip_reset1(struct rtw_regs *regs, const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t cr;
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
int i;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
RTW_WRITE8(regs, RTW_CR, RTW_CR_RST);
|
|
|
|
|
|
|
|
RTW_WBR(regs, RTW_CR, RTW_CR);
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
for (i = 0; i < 1000; i++) {
|
2004-09-26 06:29:15 +04:00
|
|
|
if ((cr = RTW_READ8(regs, RTW_CR) & RTW_CR_RST) == 0) {
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_RESET,
|
|
|
|
("%s: reset in %dus\n", dvname, i));
|
2004-09-26 06:29:15 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
RTW_RBR(regs, RTW_CR, RTW_CR);
|
2004-12-25 09:58:37 +03:00
|
|
|
DELAY(10); /* 10us */
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
2004-12-20 03:28:02 +03:00
|
|
|
printf("%s: reset failed\n", dvname);
|
2004-09-26 06:29:15 +04:00
|
|
|
return ETIMEDOUT;
|
|
|
|
}
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
static __inline int
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_chip_reset(struct rtw_regs *regs, const char *dvname)
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
{
|
|
|
|
uint32_t tcr;
|
|
|
|
|
|
|
|
/* from Linux driver */
|
|
|
|
tcr = RTW_TCR_CWMIN | RTW_TCR_MXDMA_2048 |
|
|
|
|
LSHIFT(7, RTW_TCR_SRL_MASK) | LSHIFT(7, RTW_TCR_LRL_MASK);
|
|
|
|
|
|
|
|
RTW_WRITE(regs, RTW_TCR, tcr);
|
|
|
|
|
|
|
|
RTW_WBW(regs, RTW_CR, RTW_TCR);
|
|
|
|
|
|
|
|
return rtw_chip_reset1(regs, dvname);
|
|
|
|
}
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
static void
|
|
|
|
rtw_wep_setkeys(struct rtw_softc *sc, struct ieee80211_wepkey *wk, int txkey)
|
|
|
|
{
|
|
|
|
uint8_t cfg0, scr;
|
|
|
|
int i, j, tx_key_len;
|
|
|
|
struct rtw_regs *regs;
|
|
|
|
union rtw_keys *rk;
|
|
|
|
|
|
|
|
regs = &sc->sc_regs;
|
|
|
|
rk = &sc->sc_keys;
|
|
|
|
|
|
|
|
(void)memset(rk->rk_keys, 0, sizeof(rk->rk_keys));
|
|
|
|
|
|
|
|
scr = RTW_READ8(regs, RTW_SCR);
|
|
|
|
cfg0 = RTW_READ8(regs, RTW_CONFIG0);
|
|
|
|
scr &= ~(RTW_SCR_KM_MASK | RTW_SCR_TXSECON | RTW_SCR_RXSECON);
|
|
|
|
cfg0 &= ~(RTW_CONFIG0_WEP104 | RTW_CONFIG0_WEP40);
|
|
|
|
|
|
|
|
rtw_set_access(regs, RTW_ACCESS_CONFIG);
|
|
|
|
|
|
|
|
if ((sc->sc_ic.ic_flags & IEEE80211_F_PRIVACY) == 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
tx_key_len = wk[txkey].wk_len;
|
|
|
|
|
|
|
|
switch (tx_key_len) {
|
|
|
|
case 5:
|
|
|
|
scr |= RTW_SCR_TXSECON | RTW_SCR_RXSECON | RTW_SCR_KM_WEP40;
|
|
|
|
break;
|
|
|
|
case 13:
|
|
|
|
scr |= RTW_SCR_TXSECON | RTW_SCR_RXSECON | RTW_SCR_KM_WEP104;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg0 |= RTW_CONFIG0_WEP104 | RTW_CONFIG0_WEP40;
|
|
|
|
|
|
|
|
for (i = j = 0; i < IEEE80211_WEP_NKID; i++) {
|
|
|
|
if (i == txkey)
|
|
|
|
sc->sc_txkey = j;
|
|
|
|
else if (wk[i].wk_len != tx_key_len)
|
|
|
|
continue;
|
|
|
|
(void)memcpy(rk->rk_keys[j++], wk[i].wk_key, wk[i].wk_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
bus_space_write_region_4(regs->r_bt, regs->r_bh,
|
|
|
|
RTW_DK0, rk->rk_words,
|
|
|
|
sizeof(rk->rk_words) / sizeof(rk->rk_words[0]));
|
|
|
|
|
|
|
|
bus_space_barrier(regs->r_bt, regs->r_bh, RTW_DK0,
|
|
|
|
sizeof(rk->rk_words) / sizeof(rk->rk_words[0]),
|
|
|
|
BUS_SPACE_BARRIER_SYNC);
|
|
|
|
|
|
|
|
RTW_WRITE8(regs, RTW_CONFIG0, cfg0);
|
|
|
|
RTW_WBW(regs, RTW_CONFIG0, RTW_SCR);
|
|
|
|
RTW_WRITE8(regs, RTW_SCR, scr);
|
|
|
|
RTW_SYNC(regs, RTW_SCR, RTW_SCR);
|
|
|
|
rtw_set_access(regs, RTW_ACCESS_NONE);
|
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static __inline int
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_recall_eeprom(struct rtw_regs *regs, const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int i;
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t ecr;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
ecr = RTW_READ8(regs, RTW_9346CR);
|
|
|
|
ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD;
|
|
|
|
RTW_WRITE8(regs, RTW_9346CR, ecr);
|
|
|
|
|
|
|
|
RTW_WBR(regs, RTW_9346CR, RTW_9346CR);
|
|
|
|
|
|
|
|
/* wait 2.5ms for completion */
|
|
|
|
for (i = 0; i < 25; i++) {
|
|
|
|
ecr = RTW_READ8(regs, RTW_9346CR);
|
|
|
|
if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) {
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_RESET,
|
|
|
|
("%s: recall EEPROM in %dus\n", dvname, i * 100));
|
2004-09-26 06:29:15 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
RTW_RBR(regs, RTW_9346CR, RTW_9346CR);
|
|
|
|
DELAY(100);
|
|
|
|
}
|
2004-12-20 03:28:02 +03:00
|
|
|
printf("%s: recall EEPROM failed\n", dvname);
|
2004-09-26 06:29:15 +04:00
|
|
|
return ETIMEDOUT;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int
|
|
|
|
rtw_reset(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
int rc;
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
uint8_t config1;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-20 03:28:02 +03:00
|
|
|
if ((rc = rtw_chip_reset(&sc->sc_regs, sc->sc_dev.dv_xname)) != 0)
|
2004-09-26 06:29:15 +04:00
|
|
|
return rc;
|
|
|
|
|
2004-12-20 03:28:02 +03:00
|
|
|
if ((rc = rtw_recall_eeprom(&sc->sc_regs, sc->sc_dev.dv_xname)) != 0)
|
2004-09-26 06:29:15 +04:00
|
|
|
;
|
|
|
|
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
config1 = RTW_READ8(&sc->sc_regs, RTW_CONFIG1);
|
|
|
|
RTW_WRITE8(&sc->sc_regs, RTW_CONFIG1, config1 & ~RTW_CONFIG1_PMEN);
|
2004-09-26 06:29:15 +04:00
|
|
|
/* TBD turn off maximum power saving? */
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdesc_dmamaps_create(bus_dma_tag_t dmat, struct rtw_txsoft *descs,
|
2004-09-26 06:29:15 +04:00
|
|
|
u_int ndescs)
|
|
|
|
{
|
|
|
|
int i, rc = 0;
|
|
|
|
for (i = 0; i < ndescs; i++) {
|
|
|
|
rc = bus_dmamap_create(dmat, MCLBYTES, RTW_MAXPKTSEGS, MCLBYTES,
|
2004-12-29 04:06:52 +03:00
|
|
|
0, 0, &descs[i].ts_dmamap);
|
2004-09-26 06:29:15 +04:00
|
|
|
if (rc != 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_dmamaps_create(bus_dma_tag_t dmat, struct rtw_rxsoft *descs,
|
2004-09-26 06:29:15 +04:00
|
|
|
u_int ndescs)
|
|
|
|
{
|
|
|
|
int i, rc = 0;
|
|
|
|
for (i = 0; i < ndescs; i++) {
|
|
|
|
rc = bus_dmamap_create(dmat, MCLBYTES, 1, MCLBYTES, 0, 0,
|
2004-12-29 04:06:52 +03:00
|
|
|
&descs[i].rs_dmamap);
|
2004-09-26 06:29:15 +04:00
|
|
|
if (rc != 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t dmat, struct rtw_rxsoft *descs,
|
2004-09-26 06:29:15 +04:00
|
|
|
u_int ndescs)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ndescs; i++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
if (descs[i].rs_dmamap != NULL)
|
|
|
|
bus_dmamap_destroy(dmat, descs[i].rs_dmamap);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdesc_dmamaps_destroy(bus_dma_tag_t dmat, struct rtw_txsoft *descs,
|
2004-09-26 06:29:15 +04:00
|
|
|
u_int ndescs)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ndescs; i++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
if (descs[i].ts_dmamap != NULL)
|
|
|
|
bus_dmamap_destroy(dmat, descs[i].ts_dmamap);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
rtw_srom_free(struct rtw_srom *sr)
|
|
|
|
{
|
|
|
|
sr->sr_size = 0;
|
|
|
|
if (sr->sr_content == NULL)
|
|
|
|
return;
|
|
|
|
free(sr->sr_content, M_DEVBUF);
|
|
|
|
sr->sr_content = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_srom_defaults(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold,
|
|
|
|
enum rtw_rfchipid *rfchipid, uint32_t *rcr)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
*flags |= (RTW_F_DIGPHY|RTW_F_ANTDIV);
|
|
|
|
*cs_threshold = RTW_SR_ENERGYDETTHR_DEFAULT;
|
|
|
|
*rcr |= RTW_RCR_ENCS1;
|
|
|
|
*rfchipid = RTW_RFCHIPID_PHILIPS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_srom_parse(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold,
|
|
|
|
enum rtw_rfchipid *rfchipid, uint32_t *rcr, enum rtw_locale *locale,
|
2004-12-20 03:28:02 +03:00
|
|
|
const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const char *rfname, *paname;
|
|
|
|
char scratch[sizeof("unknown 0xXX")];
|
2005-06-10 06:35:34 +04:00
|
|
|
uint16_t srom_version;
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t mac[IEEE80211_ADDR_LEN];
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
*flags &= ~(RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV);
|
|
|
|
*rcr &= ~(RTW_RCR_ENCS1 | RTW_RCR_ENCS2);
|
|
|
|
|
2005-06-10 06:35:34 +04:00
|
|
|
srom_version = RTW_SR_GET16(sr, RTW_SR_VERSION);
|
|
|
|
printf("%s: SROM version %d.%d", dvname,
|
|
|
|
srom_version >> 8, srom_version & 0xff);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2005-06-10 06:35:34 +04:00
|
|
|
if (srom_version <= 0x0101) {
|
2004-09-26 06:29:15 +04:00
|
|
|
printf(" is not understood, limping along with defaults\n");
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_srom_defaults(sr, flags, cs_threshold, rfchipid, rcr);
|
2004-09-26 06:29:15 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
for (i = 0; i < IEEE80211_ADDR_LEN; i++)
|
|
|
|
mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i);
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH,
|
|
|
|
("%s: EEPROM MAC %s\n", dvname, ether_sprintf(mac)));
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
*cs_threshold = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR);
|
|
|
|
|
|
|
|
if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW_CONFIG2_ANT) != 0)
|
|
|
|
*flags |= RTW_F_ANTDIV;
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
/* Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems
|
|
|
|
* to be reversed.
|
|
|
|
*/
|
|
|
|
if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0)
|
2004-09-26 06:29:15 +04:00
|
|
|
*flags |= RTW_F_DIGPHY;
|
|
|
|
if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0)
|
|
|
|
*flags |= RTW_F_DFLANTB;
|
|
|
|
|
|
|
|
*rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM),
|
|
|
|
RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1);
|
|
|
|
|
|
|
|
*rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID);
|
|
|
|
switch (*rfchipid) {
|
|
|
|
case RTW_RFCHIPID_GCT: /* this combo seen in the wild */
|
|
|
|
rfname = "GCT GRF5101";
|
|
|
|
paname = "Winspring WS9901";
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_MAXIM:
|
|
|
|
rfname = "Maxim MAX2820"; /* guess */
|
|
|
|
paname = "Maxim MAX2422"; /* guess */
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_INTERSIL:
|
|
|
|
rfname = "Intersil HFA3873"; /* guess */
|
|
|
|
paname = "Intersil <unknown>";
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_PHILIPS: /* this combo seen in the wild */
|
|
|
|
rfname = "Philips SA2400A";
|
|
|
|
paname = "Philips SA2411";
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_RFMD:
|
|
|
|
/* this is the same front-end as an atw(4)! */
|
|
|
|
rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */
|
|
|
|
"LNA: RFMD RF2494, " /* mentioned in Realtek docs */
|
|
|
|
"SYN: Silicon Labs Si4126"; /* inferred from
|
|
|
|
* reference driver
|
|
|
|
*/
|
|
|
|
paname = "RFMD RF2189"; /* mentioned in Realtek docs */
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_RESERVED:
|
|
|
|
rfname = paname = "reserved";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
snprintf(scratch, sizeof(scratch), "unknown 0x%02x", *rfchipid);
|
|
|
|
rfname = paname = scratch;
|
|
|
|
}
|
2004-12-20 03:28:02 +03:00
|
|
|
printf("%s: RF: %s, PA: %s\n", dvname, rfname, paname);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_GL_MASK) {
|
|
|
|
case RTW_CONFIG0_GL_USA:
|
|
|
|
*locale = RTW_LOCALE_USA;
|
|
|
|
break;
|
|
|
|
case RTW_CONFIG0_GL_EUROPE:
|
|
|
|
*locale = RTW_LOCALE_EUROPE;
|
|
|
|
break;
|
|
|
|
case RTW_CONFIG0_GL_JAPAN:
|
|
|
|
*locale = RTW_LOCALE_JAPAN;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*locale = RTW_LOCALE_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns -1 on failure. */
|
|
|
|
static int
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_srom_read(struct rtw_regs *regs, uint32_t flags, struct rtw_srom *sr,
|
2004-12-20 03:28:02 +03:00
|
|
|
const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
struct seeprom_descriptor sd;
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t ecr;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
(void)memset(&sd, 0, sizeof(sd));
|
|
|
|
|
|
|
|
ecr = RTW_READ8(regs, RTW_9346CR);
|
|
|
|
|
|
|
|
if ((flags & RTW_F_9356SROM) != 0) {
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: 93c56 SROM\n", dvname));
|
2004-09-26 06:29:15 +04:00
|
|
|
sr->sr_size = 256;
|
|
|
|
sd.sd_chip = C56_66;
|
|
|
|
} else {
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH, ("%s: 93c46 SROM\n", dvname));
|
2004-09-26 06:29:15 +04:00
|
|
|
sr->sr_size = 128;
|
|
|
|
sd.sd_chip = C46;
|
|
|
|
}
|
|
|
|
|
|
|
|
ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK |
|
2005-01-04 04:04:52 +03:00
|
|
|
RTW_9346CR_EEM_MASK | RTW_9346CR_EECS);
|
2004-09-26 06:29:15 +04:00
|
|
|
ecr |= RTW_9346CR_EEM_PROGRAM;
|
|
|
|
|
|
|
|
RTW_WRITE8(regs, RTW_9346CR, ecr);
|
|
|
|
|
|
|
|
sr->sr_content = malloc(sr->sr_size, M_DEVBUF, M_NOWAIT);
|
|
|
|
|
|
|
|
if (sr->sr_content == NULL) {
|
2004-12-20 03:28:02 +03:00
|
|
|
printf("%s: unable to allocate SROM buffer\n", dvname);
|
2004-09-26 06:29:15 +04:00
|
|
|
return ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
(void)memset(sr->sr_content, 0, sr->sr_size);
|
|
|
|
|
|
|
|
/* RTL8180 has a single 8-bit register for controlling the
|
|
|
|
* 93cx6 SROM. There is no "ready" bit. The RTL8180
|
|
|
|
* input/output sense is the reverse of read_seeprom's.
|
|
|
|
*/
|
|
|
|
sd.sd_tag = regs->r_bt;
|
|
|
|
sd.sd_bsh = regs->r_bh;
|
|
|
|
sd.sd_regsize = 1;
|
|
|
|
sd.sd_control_offset = RTW_9346CR;
|
|
|
|
sd.sd_status_offset = RTW_9346CR;
|
|
|
|
sd.sd_dataout_offset = RTW_9346CR;
|
|
|
|
sd.sd_CK = RTW_9346CR_EESK;
|
|
|
|
sd.sd_CS = RTW_9346CR_EECS;
|
|
|
|
sd.sd_DI = RTW_9346CR_EEDO;
|
|
|
|
sd.sd_DO = RTW_9346CR_EEDI;
|
2005-02-27 03:26:58 +03:00
|
|
|
/* make read_seeprom enter EEPROM read/write mode */
|
2004-09-26 06:29:15 +04:00
|
|
|
sd.sd_MS = ecr;
|
|
|
|
sd.sd_RDY = 0;
|
|
|
|
|
2004-12-20 04:13:45 +03:00
|
|
|
/* TBD bus barriers */
|
2004-09-26 06:29:15 +04:00
|
|
|
if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) {
|
2004-12-20 03:28:02 +03:00
|
|
|
printf("%s: could not read SROM\n", dvname);
|
2004-09-26 06:29:15 +04:00
|
|
|
free(sr->sr_content, M_DEVBUF);
|
|
|
|
sr->sr_content = NULL;
|
|
|
|
return -1; /* XXX */
|
|
|
|
}
|
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
/* end EEPROM read/write mode */
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_WRITE8(regs, RTW_9346CR,
|
|
|
|
(ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL);
|
|
|
|
RTW_WBRW(regs, RTW_9346CR, RTW_9346CR);
|
|
|
|
|
|
|
|
if ((rc = rtw_recall_eeprom(regs, dvname)) != 0)
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
{
|
|
|
|
int i;
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH,
|
|
|
|
("\n%s: serial ROM:\n\t", dvname));
|
2004-09-26 06:29:15 +04:00
|
|
|
for (i = 0; i < sr->sr_size/2; i++) {
|
|
|
|
if (((i % 8) == 0) && (i != 0))
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n\t"));
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH,
|
|
|
|
(" %04x", sr->sr_content[i]));
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH, ("\n"));
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
static void
|
|
|
|
rtw_set_rfprog(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
|
|
|
|
const char *dvname)
|
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t cfg4;
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
const char *method;
|
|
|
|
|
|
|
|
cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK;
|
|
|
|
|
|
|
|
switch (rfchipid) {
|
|
|
|
default:
|
|
|
|
cfg4 |= LSHIFT(rtw_rfprog_fallback, RTW_CONFIG4_RFTYPE_MASK);
|
|
|
|
method = "fallback";
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_INTERSIL:
|
|
|
|
cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL;
|
|
|
|
method = "Intersil";
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_PHILIPS:
|
|
|
|
cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS;
|
|
|
|
method = "Philips";
|
|
|
|
break;
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
case RTW_RFCHIPID_GCT: /* XXX a guess */
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
case RTW_RFCHIPID_RFMD:
|
|
|
|
cfg4 |= RTW_CONFIG4_RFTYPE_RFMD;
|
|
|
|
method = "RFMD";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
RTW_WRITE8(regs, RTW_CONFIG4, cfg4);
|
|
|
|
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4);
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_INIT,
|
|
|
|
("%s: %s RF programming method, %#02x\n", dvname, method,
|
2004-12-21 02:05:41 +03:00
|
|
|
RTW_READ8(regs, RTW_CONFIG4)));
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static __inline void
|
|
|
|
rtw_init_channels(enum rtw_locale locale,
|
|
|
|
struct ieee80211_channel (*chans)[IEEE80211_CHAN_MAX+1],
|
2004-12-20 03:28:02 +03:00
|
|
|
const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const char *name = NULL;
|
|
|
|
#define ADD_CHANNEL(_chans, _chan) do { \
|
|
|
|
(*_chans)[_chan].ic_flags = IEEE80211_CHAN_B; \
|
|
|
|
(*_chans)[_chan].ic_freq = \
|
|
|
|
ieee80211_ieee2mhz(_chan, (*_chans)[_chan].ic_flags);\
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
switch (locale) {
|
|
|
|
case RTW_LOCALE_USA: /* 1-11 */
|
|
|
|
name = "USA";
|
|
|
|
for (i = 1; i <= 11; i++)
|
|
|
|
ADD_CHANNEL(chans, i);
|
|
|
|
break;
|
|
|
|
case RTW_LOCALE_JAPAN: /* 1-14 */
|
|
|
|
name = "Japan";
|
|
|
|
ADD_CHANNEL(chans, 14);
|
|
|
|
for (i = 1; i <= 14; i++)
|
|
|
|
ADD_CHANNEL(chans, i);
|
|
|
|
break;
|
|
|
|
case RTW_LOCALE_EUROPE: /* 1-13 */
|
|
|
|
name = "Europe";
|
|
|
|
for (i = 1; i <= 13; i++)
|
|
|
|
ADD_CHANNEL(chans, i);
|
|
|
|
break;
|
|
|
|
default: /* 10-11 allowed by most countries */
|
|
|
|
name = "<unknown>";
|
|
|
|
for (i = 10; i <= 11; i++)
|
|
|
|
ADD_CHANNEL(chans, i);
|
|
|
|
break;
|
|
|
|
}
|
2004-12-20 03:28:02 +03:00
|
|
|
printf("%s: Geographic Location %s\n", dvname, name);
|
2004-09-26 06:29:15 +04:00
|
|
|
#undef ADD_CHANNEL
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale,
|
2004-12-20 03:28:02 +03:00
|
|
|
const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
switch (cfg0 & RTW_CONFIG0_GL_MASK) {
|
|
|
|
case RTW_CONFIG0_GL_USA:
|
|
|
|
*locale = RTW_LOCALE_USA;
|
|
|
|
break;
|
|
|
|
case RTW_CONFIG0_GL_JAPAN:
|
|
|
|
*locale = RTW_LOCALE_JAPAN;
|
|
|
|
break;
|
|
|
|
case RTW_CONFIG0_GL_EUROPE:
|
|
|
|
*locale = RTW_LOCALE_EUROPE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
*locale = RTW_LOCALE_UNKNOWN;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_identify_sta(struct rtw_regs *regs, uint8_t (*addr)[IEEE80211_ADDR_LEN],
|
2004-12-20 03:28:02 +03:00
|
|
|
const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
static const uint8_t empty_macaddr[IEEE80211_ADDR_LEN] = {
|
2004-09-26 06:29:15 +04:00
|
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
|
|
};
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t idr0 = RTW_READ(regs, RTW_IDR0),
|
2004-09-26 06:29:15 +04:00
|
|
|
idr1 = RTW_READ(regs, RTW_IDR1);
|
|
|
|
|
|
|
|
(*addr)[0] = MASK_AND_RSHIFT(idr0, BITS(0, 7));
|
|
|
|
(*addr)[1] = MASK_AND_RSHIFT(idr0, BITS(8, 15));
|
|
|
|
(*addr)[2] = MASK_AND_RSHIFT(idr0, BITS(16, 23));
|
|
|
|
(*addr)[3] = MASK_AND_RSHIFT(idr0, BITS(24 ,31));
|
|
|
|
|
|
|
|
(*addr)[4] = MASK_AND_RSHIFT(idr1, BITS(0, 7));
|
|
|
|
(*addr)[5] = MASK_AND_RSHIFT(idr1, BITS(8, 15));
|
|
|
|
|
|
|
|
if (IEEE80211_ADDR_EQ(addr, empty_macaddr)) {
|
|
|
|
printf("%s: could not get mac address, attach failed\n",
|
2004-12-20 03:28:02 +03:00
|
|
|
dvname);
|
2004-09-26 06:29:15 +04:00
|
|
|
return ENXIO;
|
|
|
|
}
|
|
|
|
|
2004-12-20 03:28:02 +03:00
|
|
|
printf("%s: 802.11 address %s\n", dvname, ether_sprintf(*addr));
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2005-01-02 07:23:03 +03:00
|
|
|
static uint8_t
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic,
|
|
|
|
struct ieee80211_channel *chan)
|
|
|
|
{
|
|
|
|
u_int idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1;
|
|
|
|
KASSERT2(idx >= RTW_SR_TXPOWER1 && idx <= RTW_SR_TXPOWER14,
|
|
|
|
("%s: channel %d out of range", __func__,
|
|
|
|
idx - RTW_SR_TXPOWER1 + 1));
|
|
|
|
return RTW_SR_GET(sr, idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *tdb)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int pri;
|
|
|
|
u_int ndesc[RTW_NTXPRI] =
|
|
|
|
{RTW_NTXDESCLO, RTW_NTXDESCMD, RTW_NTXDESCHI, RTW_NTXDESCBCN};
|
|
|
|
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb[pri].tdb_nfree = ndesc[pri];
|
|
|
|
tdb[pri].tdb_next = 0;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_init(struct rtw_txsoft_blk *tsb)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int i;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft *ts;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
SIMPLEQ_INIT(&tsb->tsb_dirtyq);
|
|
|
|
SIMPLEQ_INIT(&tsb->tsb_freeq);
|
|
|
|
for (i = 0; i < tsb->tsb_ndesc; i++) {
|
|
|
|
ts = &tsb->tsb_desc[i];
|
|
|
|
ts->ts_mbuf = NULL;
|
|
|
|
SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_init_all(struct rtw_txsoft_blk *tsb)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int pri;
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++)
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_init(&tsb[pri]);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdescs_sync(struct rtw_rxdesc_blk *rdb, int desc0, int nsync, int ops)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
KASSERT(nsync <= rdb->rdb_ndesc);
|
2004-09-26 06:29:15 +04:00
|
|
|
/* sync to end of ring */
|
2004-12-29 04:06:52 +03:00
|
|
|
if (desc0 + nsync > rdb->rdb_ndesc) {
|
|
|
|
bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
|
2004-09-26 06:29:15 +04:00
|
|
|
offsetof(struct rtw_descs, hd_rx[desc0]),
|
2004-12-29 04:06:52 +03:00
|
|
|
sizeof(struct rtw_rxdesc) * (rdb->rdb_ndesc - desc0), ops);
|
|
|
|
nsync -= (rdb->rdb_ndesc - desc0);
|
2004-09-26 06:29:15 +04:00
|
|
|
desc0 = 0;
|
|
|
|
}
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
KASSERT(desc0 < rdb->rdb_ndesc);
|
|
|
|
KASSERT(nsync <= rdb->rdb_ndesc);
|
|
|
|
KASSERT(desc0 + nsync <= rdb->rdb_ndesc);
|
2004-12-25 09:58:37 +03:00
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
/* sync what remains */
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
|
2004-09-26 06:29:15 +04:00
|
|
|
offsetof(struct rtw_descs, hd_rx[desc0]),
|
|
|
|
sizeof(struct rtw_rxdesc) * nsync, ops);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdescs_sync(struct rtw_txdesc_blk *tdb, u_int desc0, u_int nsync, int ops)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
/* sync to end of ring */
|
2004-12-29 04:06:52 +03:00
|
|
|
if (desc0 + nsync > tdb->tdb_ndesc) {
|
|
|
|
bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap,
|
|
|
|
tdb->tdb_ofs + sizeof(struct rtw_txdesc) * desc0,
|
|
|
|
sizeof(struct rtw_txdesc) * (tdb->tdb_ndesc - desc0),
|
2004-09-26 06:29:15 +04:00
|
|
|
ops);
|
2004-12-29 04:06:52 +03:00
|
|
|
nsync -= (tdb->tdb_ndesc - desc0);
|
2004-09-26 06:29:15 +04:00
|
|
|
desc0 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* sync what remains */
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_sync(tdb->tdb_dmat, tdb->tdb_dmamap,
|
|
|
|
tdb->tdb_ofs + sizeof(struct rtw_txdesc) * desc0,
|
2004-09-26 06:29:15 +04:00
|
|
|
sizeof(struct rtw_txdesc) * nsync, ops);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdescs_sync_all(struct rtw_txdesc_blk *tdb)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int pri;
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdescs_sync(&tdb[pri], 0, tdb[pri].tdb_ndesc,
|
2004-09-26 06:29:15 +04:00
|
|
|
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxbufs_release(bus_dma_tag_t dmat, struct rtw_rxsoft *desc)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int i;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_rxsoft *rs;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
for (i = 0; i < RTW_RXQLEN; i++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
rs = &desc[i];
|
|
|
|
if (rs->rs_mbuf == NULL)
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
continue;
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_sync(dmat, rs->rs_dmamap, 0,
|
|
|
|
rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
|
|
|
|
bus_dmamap_unload(dmat, rs->rs_dmamap);
|
|
|
|
m_freem(rs->rs_mbuf);
|
|
|
|
rs->rs_mbuf = NULL;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxsoft_alloc(bus_dma_tag_t dmat, struct rtw_rxsoft *rs)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
struct mbuf *m;
|
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
2004-09-26 06:29:15 +04:00
|
|
|
if (m == NULL)
|
2004-12-23 09:03:09 +03:00
|
|
|
return ENOBUFS;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
MCLGET(m, M_DONTWAIT);
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
if ((m->m_flags & M_EXT) == 0) {
|
|
|
|
m_freem(m);
|
2004-12-23 09:03:09 +03:00
|
|
|
return ENOBUFS;
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
m->m_pkthdr.len = m->m_len = m->m_ext.ext_size;
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
if (rs->rs_mbuf != NULL)
|
|
|
|
bus_dmamap_unload(dmat, rs->rs_dmamap);
|
2004-12-23 09:03:09 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rs->rs_mbuf = NULL;
|
2004-12-23 09:03:09 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rc = bus_dmamap_load_mbuf(dmat, rs->rs_dmamap, m, BUS_DMA_NOWAIT);
|
2004-12-23 09:03:09 +03:00
|
|
|
if (rc != 0) {
|
|
|
|
m_freem(m);
|
|
|
|
return -1;
|
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rs->rs_mbuf = m;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxsoft_init_all(bus_dma_tag_t dmat, struct rtw_rxsoft *desc,
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
int *ndesc, const char *dvname)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
int i, rc = 0;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_rxsoft *rs;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
for (i = 0; i < RTW_RXQLEN; i++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
rs = &desc[i];
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
/* we're in rtw_init, so there should be no mbufs allocated */
|
2004-12-29 04:06:52 +03:00
|
|
|
KASSERT(rs->rs_mbuf == NULL);
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
if (i == rtw_rxbufs_limit) {
|
|
|
|
printf("%s: TEST hit %d-buffer limit\n", dvname, i);
|
|
|
|
rc = ENOBUFS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-29 04:06:52 +03:00
|
|
|
if ((rc = rtw_rxsoft_alloc(dmat, rs)) != 0) {
|
|
|
|
printf("%s: rtw_rxsoft_alloc failed, %d buffers, "
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
"rc %d\n", dvname, i, rc);
|
|
|
|
break;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
}
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
*ndesc = i;
|
|
|
|
return rc;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_init(struct rtw_rxdesc_blk *rdb, struct rtw_rxsoft *rs,
|
2004-12-29 03:21:37 +03:00
|
|
|
int idx, int kick)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
int is_last = (idx == rdb->rdb_ndesc - 1);
|
2004-12-25 09:58:37 +03:00
|
|
|
uint32_t ctl, octl, obuf;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_rxdesc *rd = &rdb->rdb_desc[idx];
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
obuf = rd->rd_buf;
|
|
|
|
rd->rd_buf = htole32(rs->rs_dmamap->dm_segs[0].ds_addr);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
ctl = LSHIFT(rs->rs_mbuf->m_len, RTW_RXCTL_LENGTH_MASK) |
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_RXCTL_OWN | RTW_RXCTL_FS | RTW_RXCTL_LS;
|
|
|
|
|
|
|
|
if (is_last)
|
|
|
|
ctl |= RTW_RXCTL_EOR;
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
octl = rd->rd_ctl;
|
|
|
|
rd->rd_ctl = htole32(ctl);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-27 01:59:41 +03:00
|
|
|
RTW_DPRINTF(
|
|
|
|
kick ? (RTW_DEBUG_RECV_DESC | RTW_DEBUG_IO_KICK)
|
|
|
|
: RTW_DEBUG_RECV_DESC,
|
2004-12-29 04:06:52 +03:00
|
|
|
("%s: rd %p buf %08x -> %08x ctl %08x -> %08x\n", __func__, rd,
|
|
|
|
le32toh(obuf), le32toh(rd->rd_buf), le32toh(octl),
|
|
|
|
le32toh(rd->rd_ctl)));
|
2004-12-25 09:58:37 +03:00
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
/* sync the mbuf */
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_sync(rdb->rdb_dmat, rs->rs_dmamap, 0,
|
|
|
|
rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
/* sync the descriptor */
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_sync(rdb->rdb_dmat, rdb->rdb_dmamap,
|
2004-12-29 03:21:37 +03:00
|
|
|
RTW_DESC_OFFSET(hd_rx, idx), sizeof(struct rtw_rxdesc),
|
2004-09-26 06:29:15 +04:00
|
|
|
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_init_all(struct rtw_rxdesc_blk *rdb, struct rtw_rxsoft *ctl, int kick)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int i;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_rxdesc *rd;
|
|
|
|
struct rtw_rxsoft *rs;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
for (i = 0; i < rdb->rdb_ndesc; i++) {
|
|
|
|
rd = &rdb->rdb_desc[i];
|
|
|
|
rs = &ctl[i];
|
|
|
|
rtw_rxdesc_init(rdb, rs, i, kick);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
2004-12-29 04:06:52 +03:00
|
|
|
rdb->rdb_next = 0;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_io_enable(struct rtw_regs *regs, uint8_t flags, int enable)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t cr;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_IOSTATE, ("%s: %s 0x%02x\n", __func__,
|
2004-09-26 06:29:15 +04:00
|
|
|
enable ? "enable" : "disable", flags));
|
|
|
|
|
|
|
|
cr = RTW_READ8(regs, RTW_CR);
|
|
|
|
|
|
|
|
/* XXX reference source does not enable MULRW */
|
|
|
|
#if 0
|
|
|
|
/* enable PCI Read/Write Multiple */
|
|
|
|
cr |= RTW_CR_MULRW;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
RTW_RBW(regs, RTW_CR, RTW_CR); /* XXX paranoia? */
|
|
|
|
if (enable)
|
|
|
|
cr |= flags;
|
|
|
|
else
|
|
|
|
cr &= ~flags;
|
|
|
|
RTW_WRITE8(regs, RTW_CR, cr);
|
|
|
|
RTW_SYNC(regs, RTW_CR, RTW_CR);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_intr_rx(struct rtw_softc *sc, uint16_t isr)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
#define IS_BEACON(__fc0) \
|
|
|
|
((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\
|
|
|
|
(IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON))
|
|
|
|
|
2004-12-27 23:04:45 +03:00
|
|
|
static const int ratetbl[4] = {2, 4, 11, 22}; /* convert rates:
|
|
|
|
* hardware -> net80211
|
|
|
|
*/
|
2004-12-25 09:58:37 +03:00
|
|
|
u_int next, nproc = 0;
|
2004-12-29 01:30:07 +03:00
|
|
|
int hwrate, len, rate, rssi, sq;
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t hrssi, hstat, htsfth, htsftl;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_rxdesc *rd;
|
|
|
|
struct rtw_rxsoft *rs;
|
|
|
|
struct rtw_rxdesc_blk *rdb;
|
2004-09-26 06:29:15 +04:00
|
|
|
struct mbuf *m;
|
|
|
|
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct ieee80211_frame *wh;
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rdb = &sc->sc_rxdesc_blk;
|
2004-12-25 09:58:37 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
KASSERT(rdb->rdb_next < rdb->rdb_ndesc);
|
2004-12-29 03:21:37 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
for (next = rdb->rdb_next; ; next = (next + 1) % rdb->rdb_ndesc) {
|
|
|
|
rtw_rxdescs_sync(rdb, next, 1,
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
|
2004-12-29 04:06:52 +03:00
|
|
|
rd = &rdb->rdb_desc[next];
|
|
|
|
rs = &sc->sc_rxsoft[next];
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
hstat = le32toh(rd->rd_stat);
|
|
|
|
hrssi = le32toh(rd->rd_rssi);
|
|
|
|
htsfth = le32toh(rd->rd_tsfth);
|
|
|
|
htsftl = le32toh(rd->rd_tsftl);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
|
|
|
|
("%s: rxdesc[%d] hstat %08x hrssi %08x htsft %08x%08x\n",
|
|
|
|
__func__, next, hstat, hrssi, htsfth, htsftl));
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
++nproc;
|
|
|
|
|
|
|
|
/* still belongs to NIC */
|
|
|
|
if ((hstat & RTW_RXSTAT_OWN) != 0) {
|
|
|
|
if (nproc > 1)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* sometimes the NIC skips to the 0th descriptor */
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdescs_sync(rdb, 0, 1,
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
|
2004-12-29 04:06:52 +03:00
|
|
|
rd = &rdb->rdb_desc[0];
|
|
|
|
if ((rd->rd_stat & htole32(RTW_RXSTAT_OWN)) != 0)
|
2004-12-25 09:58:37 +03:00
|
|
|
break;
|
2004-12-25 10:45:53 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_BUGS,
|
2005-03-02 08:20:43 +03:00
|
|
|
("%s: NIC skipped from rxdesc[%u] to rxdesc[0]\n",
|
|
|
|
sc->sc_dev.dv_xname, next));
|
|
|
|
next = rdb->rdb_ndesc - 1;
|
2004-12-25 09:58:37 +03:00
|
|
|
continue;
|
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
#define PRINTSTAT(flag) do { \
|
|
|
|
if ((hstat & flag) != 0) { \
|
|
|
|
printf("%s" #flag, delim); \
|
|
|
|
delim = ","; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
if ((rtw_debug & RTW_DEBUG_RECV_DESC) != 0) {
|
|
|
|
const char *delim = "<";
|
|
|
|
printf("%s: ", sc->sc_dev.dv_xname);
|
|
|
|
if ((hstat & RTW_RXSTAT_DEBUG) != 0) {
|
|
|
|
printf("status %08x", hstat);
|
|
|
|
PRINTSTAT(RTW_RXSTAT_SPLCP);
|
|
|
|
PRINTSTAT(RTW_RXSTAT_MAR);
|
|
|
|
PRINTSTAT(RTW_RXSTAT_PAR);
|
|
|
|
PRINTSTAT(RTW_RXSTAT_BAR);
|
|
|
|
PRINTSTAT(RTW_RXSTAT_PWRMGT);
|
|
|
|
PRINTSTAT(RTW_RXSTAT_CRC32);
|
|
|
|
PRINTSTAT(RTW_RXSTAT_ICV);
|
|
|
|
printf(">, ");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
if ((hstat & RTW_RXSTAT_IOERROR) != 0) {
|
|
|
|
printf("%s: DMA error/FIFO overflow %08x, "
|
|
|
|
"rx descriptor %d\n", sc->sc_dev.dv_xname,
|
|
|
|
hstat & RTW_RXSTAT_IOERROR, next);
|
2004-12-27 23:04:45 +03:00
|
|
|
sc->sc_if.if_ierrors++;
|
2004-09-26 06:29:15 +04:00
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
2004-12-25 10:24:17 +03:00
|
|
|
len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK);
|
|
|
|
if (len < IEEE80211_MIN_LEN) {
|
|
|
|
sc->sc_ic.ic_stats.is_rx_tooshort++;
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
2005-01-31 05:51:17 +03:00
|
|
|
/* CRC is included with the packet; trim it off. */
|
|
|
|
len -= IEEE80211_CRC_LEN;
|
|
|
|
|
2004-12-27 23:04:45 +03:00
|
|
|
hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK);
|
|
|
|
if (hwrate >= sizeof(ratetbl) / sizeof(ratetbl[0])) {
|
2004-12-25 10:24:17 +03:00
|
|
|
printf("%s: unknown rate #%d\n", sc->sc_dev.dv_xname,
|
|
|
|
MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK));
|
2004-12-27 23:04:45 +03:00
|
|
|
sc->sc_if.if_ierrors++;
|
2004-12-25 10:24:17 +03:00
|
|
|
goto next;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
2004-12-27 23:04:45 +03:00
|
|
|
rate = ratetbl[hwrate];
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
#ifdef RTW_DEBUG
|
2005-03-02 08:20:43 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
|
|
|
|
("rate %d.%d Mb/s, time %08x%08x\n", (rate * 5) / 10,
|
|
|
|
(rate * 5) % 10, htsfth, htsftl));
|
2004-09-26 06:29:15 +04:00
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
|
|
|
|
if ((hstat & RTW_RXSTAT_RES) != 0 &&
|
|
|
|
sc->sc_ic.ic_opmode != IEEE80211_M_MONITOR)
|
|
|
|
goto next;
|
|
|
|
|
|
|
|
/* if bad flags, skip descriptor */
|
|
|
|
if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) {
|
|
|
|
printf("%s: too many rx segments\n",
|
|
|
|
sc->sc_dev.dv_xname);
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_sync(sc->sc_dmat, rs->rs_dmamap, 0,
|
|
|
|
rs->rs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
|
2004-12-23 09:03:09 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
m = rs->rs_mbuf;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
/* if temporarily out of memory, re-use mbuf */
|
2004-12-29 04:06:52 +03:00
|
|
|
switch (rtw_rxsoft_alloc(sc->sc_dmat, rs)) {
|
2004-12-23 09:03:09 +03:00
|
|
|
case 0:
|
|
|
|
break;
|
|
|
|
case ENOBUFS:
|
2004-12-29 04:06:52 +03:00
|
|
|
printf("%s: rtw_rxsoft_alloc(, %d) failed, "
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
"dropping packet\n", sc->sc_dev.dv_xname, next);
|
2004-09-26 06:29:15 +04:00
|
|
|
goto next;
|
2004-12-23 09:03:09 +03:00
|
|
|
default:
|
|
|
|
/* XXX shorten rx ring, instead? */
|
|
|
|
panic("%s: could not load DMA map\n",
|
|
|
|
sc->sc_dev.dv_xname);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (sc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
|
|
|
|
rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI);
|
|
|
|
else {
|
|
|
|
rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI);
|
|
|
|
/* TBD find out each front-end's LNA gain in the
|
|
|
|
* front-end's units
|
|
|
|
*/
|
|
|
|
if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0)
|
|
|
|
rssi |= 0x80;
|
|
|
|
}
|
2004-12-29 01:30:07 +03:00
|
|
|
sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
/* Note well: now we cannot recycle the rs_mbuf unless
|
2004-12-29 01:30:07 +03:00
|
|
|
* we restore its original length.
|
|
|
|
*/
|
2004-12-25 10:24:17 +03:00
|
|
|
m->m_pkthdr.rcvif = &sc->sc_if;
|
|
|
|
m->m_pkthdr.len = m->m_len = len;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
wh = mtod(m, struct ieee80211_frame *);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
|
|
|
|
if (!IS_BEACON(wh->i_fc[0]))
|
|
|
|
sc->sc_led_state.ls_event |= RTW_LED_S_RX;
|
2004-09-26 06:29:15 +04:00
|
|
|
/* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */
|
|
|
|
ni = ieee80211_find_rxnode(&sc->sc_ic, wh);
|
|
|
|
|
|
|
|
sc->sc_tsfth = htsfth;
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
|
|
|
|
(IFF_DEBUG|IFF_LINK2)) {
|
|
|
|
ieee80211_dump_pkt(mtod(m, uint8_t *), m->m_pkthdr.len,
|
|
|
|
rate, rssi);
|
|
|
|
}
|
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-29 01:30:07 +03:00
|
|
|
|
|
|
|
#if NBPFILTER > 0
|
|
|
|
if (sc->sc_radiobpf != NULL) {
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct rtw_rx_radiotap_header *rr = &sc->sc_rxtap;
|
|
|
|
|
|
|
|
rr->rr_tsft =
|
|
|
|
htole64(((uint64_t)htsfth << 32) | htsftl);
|
|
|
|
|
|
|
|
if ((hstat & RTW_RXSTAT_SPLCP) != 0)
|
|
|
|
rr->rr_flags = IEEE80211_RADIOTAP_F_SHORTPRE;
|
|
|
|
|
|
|
|
rr->rr_flags = 0;
|
|
|
|
rr->rr_rate = rate;
|
|
|
|
rr->rr_chan_freq =
|
|
|
|
htole16(ic->ic_bss->ni_chan->ic_freq);
|
|
|
|
rr->rr_chan_flags =
|
|
|
|
htole16(ic->ic_bss->ni_chan->ic_flags);
|
|
|
|
rr->rr_antsignal = rssi;
|
2004-12-29 22:41:04 +03:00
|
|
|
rr->rr_barker_lock = htole16(sq);
|
2004-12-29 01:30:07 +03:00
|
|
|
|
|
|
|
bpf_mtap2(sc->sc_radiobpf, (caddr_t)rr,
|
|
|
|
sizeof(sc->sc_rxtapu), m);
|
|
|
|
}
|
|
|
|
#endif /* NPBFILTER > 0 */
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
ieee80211_input(&sc->sc_if, m, ni, rssi, htsftl);
|
|
|
|
ieee80211_release_node(&sc->sc_ic, ni);
|
|
|
|
next:
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_init(rdb, rs, next, 0);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
2004-12-29 04:06:52 +03:00
|
|
|
rdb->rdb_next = next;
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
KASSERT(rdb->rdb_next < rdb->rdb_ndesc);
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
return;
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
#undef IS_BEACON
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
2004-12-19 11:19:25 +03:00
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_release(bus_dma_tag_t dmat, struct ieee80211com *ic,
|
|
|
|
struct rtw_txsoft *ts)
|
2004-12-19 11:19:25 +03:00
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
m = ts->ts_mbuf;
|
|
|
|
ni = ts->ts_ni;
|
2004-12-25 09:58:37 +03:00
|
|
|
KASSERT(m != NULL);
|
|
|
|
KASSERT(ni != NULL);
|
2004-12-29 04:06:52 +03:00
|
|
|
ts->ts_mbuf = NULL;
|
|
|
|
ts->ts_ni = NULL;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_sync(dmat, ts->ts_dmamap, 0, ts->ts_dmamap->dm_mapsize,
|
2004-12-19 11:19:25 +03:00
|
|
|
BUS_DMASYNC_POSTWRITE);
|
2004-12-29 04:06:52 +03:00
|
|
|
bus_dmamap_unload(dmat, ts->ts_dmamap);
|
2004-12-19 11:19:25 +03:00
|
|
|
m_freem(m);
|
|
|
|
ieee80211_release_node(ic, ni);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsofts_release(bus_dma_tag_t dmat, struct ieee80211com *ic,
|
|
|
|
struct rtw_txsoft_blk *tsb)
|
2004-12-19 11:19:25 +03:00
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft *ts;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
while ((ts = SIMPLEQ_FIRST(&tsb->tsb_dirtyq)) != NULL) {
|
|
|
|
rtw_txsoft_release(dmat, ic, ts);
|
|
|
|
SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q);
|
|
|
|
SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
|
2004-12-19 11:19:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_collect_txpkt(struct rtw_softc *sc, struct rtw_txdesc_blk *tdb,
|
|
|
|
struct rtw_txsoft *ts, int ndesc)
|
2004-12-19 11:19:25 +03:00
|
|
|
{
|
2004-12-23 08:44:39 +03:00
|
|
|
uint32_t hstat;
|
2004-12-19 11:19:25 +03:00
|
|
|
int data_retry, rts_retry;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txdesc *tdn;
|
2004-12-19 11:19:25 +03:00
|
|
|
const char *condstring;
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_release(sc->sc_dmat, &sc->sc_ic, ts);
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb->tdb_nfree += ndesc;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
tdn = &tdb->tdb_desc[ts->ts_last];
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
hstat = le32toh(tdn->td_stat);
|
2004-12-23 08:44:39 +03:00
|
|
|
rts_retry = MASK_AND_RSHIFT(hstat, RTW_TXSTAT_RTSRETRY_MASK);
|
|
|
|
data_retry = MASK_AND_RSHIFT(hstat, RTW_TXSTAT_DRC_MASK);
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
sc->sc_if.if_collisions += rts_retry + data_retry;
|
|
|
|
|
2004-12-23 08:44:39 +03:00
|
|
|
if ((hstat & RTW_TXSTAT_TOK) != 0)
|
2004-12-19 11:19:25 +03:00
|
|
|
condstring = "ok";
|
|
|
|
else {
|
|
|
|
sc->sc_if.if_oerrors++;
|
|
|
|
condstring = "error";
|
|
|
|
}
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT_DESC,
|
2004-12-29 04:06:52 +03:00
|
|
|
("%s: ts %p txdesc[%d, %d] %s tries rts %u data %u\n",
|
|
|
|
sc->sc_dev.dv_xname, ts, ts->ts_first, ts->ts_last,
|
2004-12-19 11:19:25 +03:00
|
|
|
condstring, rts_retry, data_retry));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Collect transmitted packets. */
|
|
|
|
static __inline void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_collect_txring(struct rtw_softc *sc, struct rtw_txsoft_blk *tsb,
|
|
|
|
struct rtw_txdesc_blk *tdb)
|
2004-12-19 11:19:25 +03:00
|
|
|
{
|
|
|
|
int ndesc;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft *ts;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
while ((ts = SIMPLEQ_FIRST(&tsb->tsb_dirtyq)) != NULL) {
|
|
|
|
ndesc = 1 + ts->ts_last - ts->ts_first;
|
|
|
|
if (ts->ts_last < ts->ts_first)
|
|
|
|
ndesc += tdb->tdb_ndesc;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-20 03:16:21 +03:00
|
|
|
KASSERT(ndesc > 0);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdescs_sync(tdb, ts->ts_first, ndesc,
|
2004-12-19 11:19:25 +03:00
|
|
|
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
if ((tdb->tdb_desc[ts->ts_last].td_stat &
|
2005-02-27 03:26:58 +03:00
|
|
|
htole32(RTW_TXSTAT_OWN)) != 0)
|
2004-12-19 11:19:25 +03:00
|
|
|
break;
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
if (&sc->sc_txdesc_blk[RTW_TXPRIBCN] == tdb) {
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_BEACON,
|
|
|
|
("%s: collected beacon\n", __func__));
|
|
|
|
}
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_collect_txpkt(sc, tdb, ts, ndesc);
|
|
|
|
SIMPLEQ_REMOVE_HEAD(&tsb->tsb_dirtyq, ts_q);
|
|
|
|
SIMPLEQ_INSERT_TAIL(&tsb->tsb_freeq, ts, ts_q);
|
2004-12-19 11:19:25 +03:00
|
|
|
sc->sc_if.if_flags &= ~IFF_OACTIVE;
|
|
|
|
}
|
2004-12-29 04:06:52 +03:00
|
|
|
if (ts == NULL)
|
|
|
|
tsb->tsb_tx_timer = 0;
|
2004-12-19 11:19:25 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static void
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_intr_tx(struct rtw_softc *sc, uint16_t isr)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2004-12-19 11:19:25 +03:00
|
|
|
int pri;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft_blk *tsb;
|
|
|
|
struct rtw_txdesc_blk *tdb;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
tsb = &sc->sc_txsoft_blk[pri];
|
|
|
|
tdb = &sc->sc_txdesc_blk[pri];
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_collect_txring(sc, tsb, tdb);
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
if ((isr & RTW_INTR_TX) != 0)
|
|
|
|
rtw_start(&sc->sc_if);
|
2004-12-19 11:19:25 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
/* TBD */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-01-02 07:23:03 +03:00
|
|
|
rtw_intr_beacon(struct rtw_softc *sc, uint16_t isr)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
/* TBD */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_intr_atim(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
/* TBD */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
static void
|
|
|
|
rtw_dump_rings(struct rtw_softc *sc)
|
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txdesc_blk *tdb;
|
|
|
|
struct rtw_rxdesc *rd;
|
|
|
|
struct rtw_rxdesc_blk *rdb;
|
2004-12-25 09:58:37 +03:00
|
|
|
int desc, pri;
|
|
|
|
|
|
|
|
if ((rtw_debug & RTW_DEBUG_IO_KICK) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb = &sc->sc_txdesc_blk[pri];
|
2004-12-25 09:58:37 +03:00
|
|
|
printf("%s: txpri %d ndesc %d nfree %d\n", __func__, pri,
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb->tdb_ndesc, tdb->tdb_nfree);
|
|
|
|
for (desc = 0; desc < tdb->tdb_ndesc; desc++)
|
|
|
|
rtw_print_txdesc(sc, ".", NULL, tdb, desc);
|
2004-12-25 09:58:37 +03:00
|
|
|
}
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rdb = &sc->sc_rxdesc_blk;
|
2004-12-29 03:21:37 +03:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
for (desc = 0; desc < RTW_RXQLEN; desc++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
rd = &rdb->rdb_desc[desc];
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
printf("%s: %sctl %08x rsvd0/rssi %08x buf/tsftl %08x "
|
2004-12-25 09:58:37 +03:00
|
|
|
"rsvd1/tsfth %08x\n", __func__,
|
2004-12-29 04:06:52 +03:00
|
|
|
(desc >= rdb->rdb_ndesc) ? "UNUSED " : "",
|
|
|
|
le32toh(rd->rd_ctl), le32toh(rd->rd_rssi),
|
|
|
|
le32toh(rd->rd_buf), le32toh(rd->rd_tsfth));
|
2004-12-25 09:58:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
static void
|
|
|
|
rtw_hwring_setup(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
|
|
|
RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(sc, hd_rx));
|
|
|
|
RTW_WRITE(regs, RTW_TLPDA, RTW_RING_BASE(sc, hd_txlo));
|
|
|
|
RTW_WRITE(regs, RTW_TNPDA, RTW_RING_BASE(sc, hd_txmd));
|
|
|
|
RTW_WRITE(regs, RTW_THPDA, RTW_RING_BASE(sc, hd_txhi));
|
|
|
|
RTW_WRITE(regs, RTW_TBDA, RTW_RING_BASE(sc, hd_bcn));
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_TLPDA, RTW_RDSAR);
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_XMIT_DESC,
|
|
|
|
("%s: reg[TLPDA] <- %" PRIxPTR "\n", __func__,
|
|
|
|
(uintptr_t)RTW_RING_BASE(sc, hd_txlo)));
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_XMIT_DESC,
|
|
|
|
("%s: reg[TNPDA] <- %" PRIxPTR "\n", __func__,
|
|
|
|
(uintptr_t)RTW_RING_BASE(sc, hd_txmd)));
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_XMIT_DESC,
|
|
|
|
("%s: reg[THPDA] <- %" PRIxPTR "\n", __func__,
|
|
|
|
(uintptr_t)RTW_RING_BASE(sc, hd_txhi)));
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_XMIT_DESC,
|
|
|
|
("%s: reg[TBDA] <- %" PRIxPTR "\n", __func__,
|
|
|
|
(uintptr_t)RTW_RING_BASE(sc, hd_bcn)));
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_RECV_DESC,
|
|
|
|
("%s: reg[RDSAR] <- %" PRIxPTR "\n", __func__,
|
|
|
|
(uintptr_t)RTW_RING_BASE(sc, hd_rx)));
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
}
|
|
|
|
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
static int
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_swring_setup(struct rtw_softc *sc)
|
|
|
|
{
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
int rc;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_rxdesc_blk *rdb;
|
2004-12-29 03:21:37 +03:00
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_txdesc_blk_init_all(&sc->sc_txdesc_blk[0]);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_init_all(&sc->sc_txsoft_blk[0]);
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rdb = &sc->sc_rxdesc_blk;
|
|
|
|
if ((rc = rtw_rxsoft_init_all(sc->sc_dmat, sc->sc_rxsoft, &rdb->rdb_ndesc,
|
|
|
|
sc->sc_dev.dv_xname)) != 0 && rdb->rdb_ndesc == 0) {
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
printf("%s: could not allocate rx buffers\n",
|
|
|
|
sc->sc_dev.dv_xname);
|
|
|
|
return rc;
|
|
|
|
}
|
2005-02-27 03:26:58 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rdb = &sc->sc_rxdesc_blk;
|
|
|
|
rtw_rxdescs_sync(rdb, 0, rdb->rdb_ndesc,
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_init_all(rdb, sc->sc_rxsoft, 1);
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
|
2004-12-29 03:21:37 +03:00
|
|
|
rtw_txdescs_sync_all(&sc->sc_txdesc_blk[0]);
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
return 0;
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdesc_blk_reset(struct rtw_txdesc_blk *tdb)
|
2004-12-25 09:58:37 +03:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
(void)memset(tdb->tdb_desc, 0,
|
|
|
|
sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc);
|
|
|
|
for (i = 0; i < tdb->tdb_ndesc; i++)
|
|
|
|
tdb->tdb_desc[i].td_next = htole32(RTW_NEXT_DESC(tdb, i));
|
|
|
|
tdb->tdb_nfree = tdb->tdb_ndesc;
|
|
|
|
tdb->tdb_next = 0;
|
2004-12-25 09:58:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_txdescs_reset(struct rtw_softc *sc)
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
{
|
2004-12-19 11:19:25 +03:00
|
|
|
int pri;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txdesc_blk *tdb;
|
2004-12-25 09:58:37 +03:00
|
|
|
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb = &sc->sc_txdesc_blk[pri];
|
|
|
|
rtw_txsofts_release(sc->sc_dmat, &sc->sc_ic,
|
|
|
|
&sc->sc_txsoft_blk[pri]);
|
|
|
|
rtw_txdesc_blk_reset(tdb);
|
|
|
|
rtw_txdescs_sync(tdb, 0, tdb->tdb_ndesc,
|
2004-12-27 22:49:16 +03:00
|
|
|
BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
|
2004-12-25 09:58:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_rxdescs_reset(struct rtw_softc *sc)
|
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_init_all(&sc->sc_rxdesc_blk, &sc->sc_rxsoft[0], 1);
|
2004-12-25 09:58:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_intr_ioerror(struct rtw_softc *sc, uint16_t isr)
|
|
|
|
{
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
if ((isr & RTW_INTR_TXFOVW) != 0)
|
|
|
|
printf("%s: tx fifo overflow\n", sc->sc_dev.dv_xname);
|
|
|
|
|
|
|
|
if ((isr & (RTW_INTR_RDU|RTW_INTR_RXFOVW)) == 0)
|
|
|
|
return;
|
2004-12-23 08:54:54 +03:00
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_BUGS, ("%s: restarting xmit/recv, isr %" PRIx16
|
|
|
|
"\n", sc->sc_dev.dv_xname, isr));
|
2004-12-23 08:54:54 +03:00
|
|
|
|
2004-12-27 01:59:41 +03:00
|
|
|
#ifdef RTW_DEBUG
|
2004-12-25 09:58:37 +03:00
|
|
|
rtw_dump_rings(sc);
|
2004-12-27 01:59:41 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-23 08:54:54 +03:00
|
|
|
|
|
|
|
rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 0);
|
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
/* Collect rx'd packets. Refresh rx buffers. */
|
2004-12-25 09:58:37 +03:00
|
|
|
rtw_intr_rx(sc, 0);
|
2005-02-27 03:26:58 +03:00
|
|
|
/* Collect tx'd packets. */
|
2004-12-25 09:58:37 +03:00
|
|
|
rtw_intr_tx(sc, 0);
|
|
|
|
|
|
|
|
RTW_WRITE16(regs, RTW_IMR, 0);
|
|
|
|
RTW_SYNC(regs, RTW_IMR, RTW_IMR);
|
|
|
|
|
|
|
|
rtw_chip_reset1(regs, sc->sc_dev.dv_xname);
|
|
|
|
|
|
|
|
rtw_rxdescs_reset(sc);
|
|
|
|
rtw_txdescs_reset(sc);
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_hwring_setup(sc);
|
2004-12-25 09:58:37 +03:00
|
|
|
|
2004-12-27 01:59:41 +03:00
|
|
|
#ifdef RTW_DEBUG
|
2004-12-25 09:58:37 +03:00
|
|
|
rtw_dump_rings(sc);
|
2004-12-27 01:59:41 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-25 09:58:37 +03:00
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
RTW_WRITE16(regs, RTW_IMR, sc->sc_inten);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_IMR, RTW_IMR);
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1);
|
2005-03-02 08:20:43 +03:00
|
|
|
sc->sc_if.if_flags &= ~IFF_OACTIVE;
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static __inline void
|
|
|
|
rtw_suspend_ticks(struct rtw_softc *sc)
|
|
|
|
{
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_TIMEOUT,
|
|
|
|
("%s: suspending ticks\n", sc->sc_dev.dv_xname));
|
2004-09-26 06:29:15 +04:00
|
|
|
sc->sc_do_tick = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
rtw_resume_ticks(struct rtw_softc *sc)
|
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t tsftrl0, tsftrl1, next_tick;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
tsftrl0 = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
|
|
|
|
|
|
|
|
tsftrl1 = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
next_tick = tsftrl1 + 1000000;
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_WRITE(&sc->sc_regs, RTW_TINT, next_tick);
|
|
|
|
|
|
|
|
sc->sc_do_tick = 1;
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_TIMEOUT,
|
|
|
|
("%s: resume ticks delta %#08x now %#08x next %#08x\n",
|
2004-12-20 04:13:45 +03:00
|
|
|
sc->sc_dev.dv_xname, tsftrl1 - tsftrl0, tsftrl1, next_tick));
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_intr_timeout(struct rtw_softc *sc)
|
|
|
|
{
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_TIMEOUT, ("%s: timeout\n", sc->sc_dev.dv_xname));
|
2004-09-26 06:29:15 +04:00
|
|
|
if (sc->sc_do_tick)
|
|
|
|
rtw_resume_ticks(sc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rtw_intr(void *arg)
|
|
|
|
{
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
int i;
|
2004-09-26 06:29:15 +04:00
|
|
|
struct rtw_softc *sc = arg;
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
2005-01-02 07:23:03 +03:00
|
|
|
uint16_t isr;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the interface isn't running, the interrupt couldn't
|
|
|
|
* possibly have come from us.
|
|
|
|
*/
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) == 0 ||
|
|
|
|
(sc->sc_if.if_flags & IFF_RUNNING) == 0 ||
|
2004-09-26 06:29:15 +04:00
|
|
|
(sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) {
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_INTR, ("%s: stray interrupt\n", sc->sc_dev.dv_xname));
|
2004-09-26 06:29:15 +04:00
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
for (i = 0; i < 10; i++) {
|
2004-09-26 06:29:15 +04:00
|
|
|
isr = RTW_READ16(regs, RTW_ISR);
|
|
|
|
|
|
|
|
RTW_WRITE16(regs, RTW_ISR, isr);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_WBR(regs, RTW_ISR, RTW_ISR);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
if (sc->sc_intr_ack != NULL)
|
|
|
|
(*sc->sc_intr_ack)(regs);
|
|
|
|
|
|
|
|
if (isr == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
#define PRINTINTR(flag) do { \
|
|
|
|
if ((isr & flag) != 0) { \
|
|
|
|
printf("%s" #flag, delim); \
|
|
|
|
delim = ","; \
|
|
|
|
} \
|
|
|
|
} while (0)
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
if ((rtw_debug & RTW_DEBUG_INTR) != 0 && isr != 0) {
|
2004-09-26 06:29:15 +04:00
|
|
|
const char *delim = "<";
|
|
|
|
|
|
|
|
printf("%s: reg[ISR] = %x", sc->sc_dev.dv_xname, isr);
|
|
|
|
|
|
|
|
PRINTINTR(RTW_INTR_TXFOVW);
|
|
|
|
PRINTINTR(RTW_INTR_TIMEOUT);
|
|
|
|
PRINTINTR(RTW_INTR_BCNINT);
|
|
|
|
PRINTINTR(RTW_INTR_ATIMINT);
|
|
|
|
PRINTINTR(RTW_INTR_TBDER);
|
|
|
|
PRINTINTR(RTW_INTR_TBDOK);
|
|
|
|
PRINTINTR(RTW_INTR_THPDER);
|
|
|
|
PRINTINTR(RTW_INTR_THPDOK);
|
|
|
|
PRINTINTR(RTW_INTR_TNPDER);
|
|
|
|
PRINTINTR(RTW_INTR_TNPDOK);
|
|
|
|
PRINTINTR(RTW_INTR_RXFOVW);
|
|
|
|
PRINTINTR(RTW_INTR_RDU);
|
|
|
|
PRINTINTR(RTW_INTR_TLPDER);
|
|
|
|
PRINTINTR(RTW_INTR_TLPDOK);
|
|
|
|
PRINTINTR(RTW_INTR_RER);
|
|
|
|
PRINTINTR(RTW_INTR_ROK);
|
|
|
|
|
|
|
|
printf(">\n");
|
|
|
|
}
|
|
|
|
#undef PRINTINTR
|
|
|
|
#endif /* RTW_DEBUG */
|
|
|
|
|
|
|
|
if ((isr & RTW_INTR_RX) != 0)
|
|
|
|
rtw_intr_rx(sc, isr & RTW_INTR_RX);
|
|
|
|
if ((isr & RTW_INTR_TX) != 0)
|
|
|
|
rtw_intr_tx(sc, isr & RTW_INTR_TX);
|
|
|
|
if ((isr & RTW_INTR_BEACON) != 0)
|
|
|
|
rtw_intr_beacon(sc, isr & RTW_INTR_BEACON);
|
|
|
|
if ((isr & RTW_INTR_ATIMINT) != 0)
|
|
|
|
rtw_intr_atim(sc);
|
|
|
|
if ((isr & RTW_INTR_IOERROR) != 0)
|
|
|
|
rtw_intr_ioerror(sc, isr & RTW_INTR_IOERROR);
|
|
|
|
if ((isr & RTW_INTR_TIMEOUT) != 0)
|
|
|
|
rtw_intr_timeout(sc);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
/* Must be called at splnet. */
|
2004-09-26 06:29:15 +04:00
|
|
|
static void
|
|
|
|
rtw_stop(struct ifnet *ifp, int disable)
|
|
|
|
{
|
2004-12-25 09:58:37 +03:00
|
|
|
int pri;
|
2004-09-26 06:29:15 +04:00
|
|
|
struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
|
|
|
|
return;
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_suspend_ticks(sc);
|
|
|
|
|
|
|
|
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
if ((sc->sc_flags & RTW_F_INVALID) == 0) {
|
|
|
|
/* Disable interrupts. */
|
|
|
|
RTW_WRITE16(regs, RTW_IMR, 0);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_WBW(regs, RTW_TPPOLL, RTW_IMR);
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
/* Stop the transmit and receive processes. First stop DMA,
|
|
|
|
* then disable receiver and transmitter.
|
|
|
|
*/
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_TPPOLL, RTW_IMR);
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_io_enable(&sc->sc_regs, RTW_CR_RE|RTW_CR_TE, 0);
|
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-19 11:19:25 +03:00
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsofts_release(sc->sc_dmat, &sc->sc_ic,
|
|
|
|
&sc->sc_txsoft_blk[pri]);
|
2004-12-19 11:19:25 +03:00
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxbufs_release(sc->sc_dmat, &sc->sc_rxsoft[0]);
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
|
|
|
|
if (disable)
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_disable(sc);
|
|
|
|
|
|
|
|
/* Mark the interface as not running. Cancel the watchdog timer. */
|
2004-12-25 09:58:37 +03:00
|
|
|
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
|
2004-09-26 06:29:15 +04:00
|
|
|
ifp->if_timer = 0;
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
rtw_pwrstate_string(enum rtw_pwrstate power)
|
|
|
|
{
|
|
|
|
switch (power) {
|
|
|
|
case RTW_ON:
|
|
|
|
return "on";
|
|
|
|
case RTW_SLEEP:
|
|
|
|
return "sleep";
|
|
|
|
case RTW_OFF:
|
|
|
|
return "off";
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
/* XXX For Maxim, I am using the RFMD settings gleaned from the
|
|
|
|
* reference driver, plus a magic Maxim "ON" value that comes from
|
|
|
|
* the Realtek document "Windows PG for Rtl8180."
|
2004-09-26 06:29:15 +04:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
rtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
|
2004-12-21 02:05:41 +03:00
|
|
|
int before_rf, int digphy)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t anaparm;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm = RTW_READ(regs, RTW_ANAPARM);
|
|
|
|
anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
|
|
|
|
|
|
|
|
switch (power) {
|
|
|
|
case RTW_OFF:
|
|
|
|
if (before_rf)
|
|
|
|
return;
|
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF;
|
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
break;
|
|
|
|
case RTW_SLEEP:
|
|
|
|
if (!before_rf)
|
|
|
|
return;
|
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP;
|
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
break;
|
|
|
|
case RTW_ON:
|
|
|
|
if (!before_rf)
|
|
|
|
return;
|
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON;
|
|
|
|
break;
|
|
|
|
}
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_PWR,
|
|
|
|
("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
|
2004-12-21 02:05:41 +03:00
|
|
|
__func__, rtw_pwrstate_string(power),
|
|
|
|
(before_rf) ? "before" : "after", anaparm));
|
|
|
|
|
|
|
|
RTW_WRITE(regs, RTW_ANAPARM, anaparm);
|
|
|
|
RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX I am using the RFMD settings gleaned from the reference
|
2005-02-27 03:26:58 +03:00
|
|
|
* driver. They agree
|
2004-12-21 02:05:41 +03:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
rtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
|
|
|
|
int before_rf, int digphy)
|
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t anaparm;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
anaparm = RTW_READ(regs, RTW_ANAPARM);
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
switch (power) {
|
|
|
|
case RTW_OFF:
|
|
|
|
if (before_rf)
|
|
|
|
return;
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF;
|
2004-09-26 06:29:15 +04:00
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
break;
|
|
|
|
case RTW_SLEEP:
|
|
|
|
if (!before_rf)
|
|
|
|
return;
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP;
|
2004-09-26 06:29:15 +04:00
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
break;
|
|
|
|
case RTW_ON:
|
|
|
|
if (!before_rf)
|
|
|
|
return;
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON;
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
}
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_PWR,
|
|
|
|
("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
|
2004-12-21 02:05:41 +03:00
|
|
|
__func__, rtw_pwrstate_string(power),
|
|
|
|
(before_rf) ? "before" : "after", anaparm));
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_WRITE(regs, RTW_ANAPARM, anaparm);
|
|
|
|
RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
|
2004-12-21 02:05:41 +03:00
|
|
|
int before_rf, int digphy)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t anaparm;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
anaparm = RTW_READ(regs, RTW_ANAPARM);
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
switch (power) {
|
|
|
|
case RTW_OFF:
|
|
|
|
if (before_rf)
|
|
|
|
return;
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF;
|
2004-09-26 06:29:15 +04:00
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
break;
|
|
|
|
case RTW_SLEEP:
|
|
|
|
if (!before_rf)
|
|
|
|
return;
|
2004-12-21 02:05:41 +03:00
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP;
|
2004-09-26 06:29:15 +04:00
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
break;
|
|
|
|
case RTW_ON:
|
|
|
|
if (!before_rf)
|
|
|
|
return;
|
2004-12-21 02:05:41 +03:00
|
|
|
if (digphy) {
|
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON;
|
|
|
|
/* XXX guess */
|
|
|
|
anaparm |= RTW_ANAPARM_TXDACOFF;
|
|
|
|
} else
|
|
|
|
anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON;
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
}
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_PWR,
|
|
|
|
("%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
|
2004-12-21 02:05:41 +03:00
|
|
|
__func__, rtw_pwrstate_string(power),
|
|
|
|
(before_rf) ? "before" : "after", anaparm));
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_WRITE(regs, RTW_ANAPARM, anaparm);
|
|
|
|
RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-21 02:05:41 +03:00
|
|
|
rtw_pwrstate0(struct rtw_softc *sc, enum rtw_pwrstate power, int before_rf,
|
|
|
|
int digphy)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_ANAPARM);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
(*sc->sc_pwrstate_cb)(regs, power, before_rf, digphy);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_NONE);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rtw_pwrstate(struct rtw_softc *sc, enum rtw_pwrstate power)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_PWR,
|
|
|
|
("%s: %s->%s\n", __func__,
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_pwrstate_string(sc->sc_pwrstate), rtw_pwrstate_string(power)));
|
|
|
|
|
|
|
|
if (sc->sc_pwrstate == power)
|
|
|
|
return 0;
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
rtw_pwrstate0(sc, power, 1, sc->sc_flags & RTW_F_DIGPHY);
|
2004-09-26 06:29:15 +04:00
|
|
|
rc = rtw_rf_pwrstate(sc->sc_rf, power);
|
2004-12-21 02:05:41 +03:00
|
|
|
rtw_pwrstate0(sc, power, 0, sc->sc_flags & RTW_F_DIGPHY);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
switch (power) {
|
|
|
|
case RTW_ON:
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
/* TBD set LEDs */
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
case RTW_SLEEP:
|
|
|
|
/* TBD */
|
|
|
|
break;
|
|
|
|
case RTW_OFF:
|
|
|
|
/* TBD */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (rc == 0)
|
|
|
|
sc->sc_pwrstate = power;
|
|
|
|
else
|
|
|
|
sc->sc_pwrstate = RTW_OFF;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rtw_tune(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
u_int chan;
|
|
|
|
int rc;
|
|
|
|
int antdiv = sc->sc_flags & RTW_F_ANTDIV,
|
|
|
|
dflantb = sc->sc_flags & RTW_F_DFLANTB;
|
|
|
|
|
|
|
|
KASSERT(ic->ic_bss->ni_chan != NULL);
|
|
|
|
|
|
|
|
chan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan);
|
|
|
|
if (chan == IEEE80211_CHAN_ANY)
|
|
|
|
panic("%s: chan == IEEE80211_CHAN_ANY\n", __func__);
|
|
|
|
|
|
|
|
if (chan == sc->sc_cur_chan) {
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_TUNE,
|
2005-02-27 03:26:58 +03:00
|
|
|
("%s: already tuned chan #%d\n", __func__, chan));
|
2004-09-26 06:29:15 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
rtw_suspend_ticks(sc);
|
|
|
|
|
|
|
|
rtw_io_enable(&sc->sc_regs, RTW_CR_RE | RTW_CR_TE, 0);
|
|
|
|
|
|
|
|
/* TBD wait for Tx to complete */
|
|
|
|
|
|
|
|
KASSERT((sc->sc_flags & RTW_F_ENABLED) != 0);
|
|
|
|
|
|
|
|
if ((rc = rtw_phy_init(&sc->sc_regs, sc->sc_rf,
|
|
|
|
rtw_chan2txpower(&sc->sc_srom, ic, ic->ic_bss->ni_chan),
|
|
|
|
sc->sc_csthr, ic->ic_bss->ni_chan->ic_freq, antdiv,
|
|
|
|
dflantb, RTW_ON)) != 0) {
|
|
|
|
/* XXX condition on powersaving */
|
|
|
|
printf("%s: phy init failed\n", sc->sc_dev.dv_xname);
|
|
|
|
}
|
|
|
|
|
|
|
|
sc->sc_cur_chan = chan;
|
|
|
|
|
|
|
|
rtw_io_enable(&sc->sc_regs, RTW_CR_RE | RTW_CR_TE, 1);
|
|
|
|
|
|
|
|
rtw_resume_ticks(sc);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rtw_disable(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* turn off PHY */
|
2004-12-29 22:41:04 +03:00
|
|
|
if ((sc->sc_flags & RTW_F_INVALID) == 0 &&
|
|
|
|
(rc = rtw_pwrstate(sc, RTW_OFF)) != 0) {
|
2004-09-26 06:29:15 +04:00
|
|
|
printf("%s: failed to turn off PHY (%d)\n",
|
|
|
|
sc->sc_dev.dv_xname, rc);
|
2004-12-29 22:41:04 +03:00
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
if (sc->sc_disable != NULL)
|
|
|
|
(*sc->sc_disable)(sc);
|
|
|
|
|
|
|
|
sc->sc_flags &= ~RTW_F_ENABLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rtw_enable(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
|
|
|
|
if (sc->sc_enable != NULL && (*sc->sc_enable)(sc) != 0) {
|
|
|
|
printf("%s: device enable failed\n",
|
|
|
|
sc->sc_dev.dv_xname);
|
|
|
|
return (EIO);
|
|
|
|
}
|
|
|
|
sc->sc_flags |= RTW_F_ENABLED;
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_transmit_config(struct rtw_regs *regs)
|
|
|
|
{
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t tcr;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
tcr = RTW_READ(regs, RTW_TCR);
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
tcr |= RTW_TCR_CWMIN;
|
|
|
|
tcr &= ~RTW_TCR_MXDMA_MASK;
|
|
|
|
tcr |= RTW_TCR_MXDMA_256;
|
2004-09-26 06:29:15 +04:00
|
|
|
tcr |= RTW_TCR_SAT; /* send ACK as fast as possible */
|
|
|
|
tcr &= ~RTW_TCR_LBK_MASK;
|
|
|
|
tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */
|
|
|
|
|
|
|
|
/* set short/long retry limits */
|
|
|
|
tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK);
|
2004-12-21 02:05:41 +03:00
|
|
|
tcr |= LSHIFT(4, RTW_TCR_SRL_MASK) | LSHIFT(4, RTW_TCR_LRL_MASK);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-23 08:50:24 +03:00
|
|
|
tcr &= ~RTW_TCR_CRC; /* NIC appends CRC32 */
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
RTW_WRITE(regs, RTW_TCR, tcr);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_TCR, RTW_TCR);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
rtw_enable_interrupts(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
|
|
|
|
|
|
|
sc->sc_inten = RTW_INTR_RX|RTW_INTR_TX|RTW_INTR_BEACON|RTW_INTR_ATIMINT;
|
|
|
|
sc->sc_inten |= RTW_INTR_IOERROR|RTW_INTR_TIMEOUT;
|
|
|
|
|
|
|
|
RTW_WRITE16(regs, RTW_IMR, sc->sc_inten);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_WBW(regs, RTW_IMR, RTW_ISR);
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_WRITE16(regs, RTW_ISR, 0xffff);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_IMR, RTW_ISR);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
/* XXX necessary? */
|
|
|
|
if (sc->sc_intr_ack != NULL)
|
|
|
|
(*sc->sc_intr_ack)(regs);
|
|
|
|
}
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
static void
|
|
|
|
rtw_set_nettype(struct rtw_softc *sc, enum ieee80211_opmode opmode)
|
|
|
|
{
|
|
|
|
uint8_t msr;
|
|
|
|
|
|
|
|
/* I'm guessing that MSR is protected as CONFIG[0123] are. */
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(&sc->sc_regs, RTW_ACCESS_CONFIG);
|
2004-12-21 02:05:41 +03:00
|
|
|
|
|
|
|
msr = RTW_READ8(&sc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK;
|
|
|
|
|
|
|
|
switch (opmode) {
|
|
|
|
case IEEE80211_M_AHDEMO:
|
|
|
|
case IEEE80211_M_IBSS:
|
|
|
|
msr |= RTW_MSR_NETYPE_ADHOC_OK;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_HOSTAP:
|
|
|
|
msr |= RTW_MSR_NETYPE_AP_OK;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_MONITOR:
|
|
|
|
/* XXX */
|
|
|
|
msr |= RTW_MSR_NETYPE_NOLINK;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_STA:
|
|
|
|
msr |= RTW_MSR_NETYPE_INFRA_OK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
RTW_WRITE8(&sc->sc_regs, RTW_MSR, msr);
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(&sc->sc_regs, RTW_ACCESS_NONE);
|
2004-12-21 02:05:41 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
#define rtw_calchash(addr) \
|
2005-01-03 06:07:12 +03:00
|
|
|
(ether_crc32_be((addr), IEEE80211_ADDR_LEN) >> 26)
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_pktfilt_load(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ethercom *ec = &ic->ic_ec;
|
|
|
|
struct ifnet *ifp = &sc->sc_ic.ic_if;
|
|
|
|
int hash;
|
2005-01-02 07:23:03 +03:00
|
|
|
uint32_t hashes[2] = { 0, 0 };
|
2004-09-26 06:29:15 +04:00
|
|
|
struct ether_multi *enm;
|
|
|
|
struct ether_multistep step;
|
|
|
|
|
|
|
|
/* XXX might be necessary to stop Rx/Tx engines while setting filters */
|
|
|
|
|
2005-01-03 06:07:12 +03:00
|
|
|
sc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK;
|
|
|
|
sc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2005-01-03 06:07:12 +03:00
|
|
|
sc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT;
|
|
|
|
/* MAC auto-reset PHY (huh?) */
|
2004-12-21 02:05:41 +03:00
|
|
|
sc->sc_rcr |= RTW_RCR_ENMARP;
|
2005-01-03 06:07:12 +03:00
|
|
|
/* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */
|
|
|
|
sc->sc_rcr |= RTW_RCR_MXDMA_1024 | RTW_RCR_RXFTH_WHOLE;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2005-01-03 06:07:12 +03:00
|
|
|
switch (ic->ic_opmode) {
|
|
|
|
case IEEE80211_M_MONITOR:
|
|
|
|
sc->sc_rcr |= RTW_RCR_MONITOR;
|
|
|
|
break;
|
|
|
|
case IEEE80211_M_AHDEMO:
|
|
|
|
case IEEE80211_M_IBSS:
|
|
|
|
/* receive broadcasts in our BSS */
|
|
|
|
sc->sc_rcr |= RTW_RCR_ADD3;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
ifp->if_flags &= ~IFF_ALLMULTI;
|
|
|
|
|
2005-01-03 06:07:12 +03:00
|
|
|
/* XXX accept all broadcast if scanning */
|
|
|
|
if ((ifp->if_flags & IFF_BROADCAST) != 0)
|
|
|
|
sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
if (ifp->if_flags & IFF_PROMISC) {
|
|
|
|
sc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */
|
|
|
|
allmulti:
|
|
|
|
ifp->if_flags |= IFF_ALLMULTI;
|
|
|
|
goto setit;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Program the 64-bit multicast hash filter.
|
|
|
|
*/
|
|
|
|
ETHER_FIRST_MULTI(step, ec, enm);
|
|
|
|
while (enm != NULL) {
|
|
|
|
/* XXX */
|
|
|
|
if (memcmp(enm->enm_addrlo, enm->enm_addrhi,
|
|
|
|
ETHER_ADDR_LEN) != 0)
|
|
|
|
goto allmulti;
|
|
|
|
|
|
|
|
hash = rtw_calchash(enm->enm_addrlo);
|
2005-01-03 06:07:12 +03:00
|
|
|
hashes[hash >> 5] |= (1 << (hash & 0x1f));
|
|
|
|
sc->sc_rcr |= RTW_RCR_AM;
|
2004-09-26 06:29:15 +04:00
|
|
|
ETHER_NEXT_MULTI(step, enm);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* all bits set => hash is useless */
|
|
|
|
if (~(hashes[0] & hashes[1]) == 0)
|
|
|
|
goto allmulti;
|
|
|
|
|
|
|
|
setit:
|
2005-01-03 06:07:12 +03:00
|
|
|
if (ifp->if_flags & IFF_ALLMULTI) {
|
2004-09-26 06:29:15 +04:00
|
|
|
sc->sc_rcr |= RTW_RCR_AM; /* accept all multicast */
|
2005-01-03 06:07:12 +03:00
|
|
|
hashes[0] = hashes[1] = 0xffffffff;
|
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
RTW_WRITE(regs, RTW_MAR0, hashes[0]);
|
|
|
|
RTW_WRITE(regs, RTW_MAR1, hashes[1]);
|
|
|
|
RTW_WRITE(regs, RTW_RCR, sc->sc_rcr);
|
|
|
|
RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_PKTFILT,
|
|
|
|
("%s: RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n",
|
2004-09-26 06:29:15 +04:00
|
|
|
sc->sc_dev.dv_xname, RTW_READ(regs, RTW_MAR0),
|
|
|
|
RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR)));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
#define IEEE80211_BEACON_TIMESTAMP_LEN 8
|
|
|
|
#define IEEE80211_BEACON_BINTVL_LEN 2
|
|
|
|
#define IEEE80211_BEACON_CAPINFO_LEN 2
|
|
|
|
#define IEEE80211_TLV_SSID_LEN(__esslen) (2 + (__esslen))
|
|
|
|
#define IEEE80211_TLV_SUPRATES_LEN(__nrates) (2 + (__nrates))
|
|
|
|
#define IEEE80211_TLV_XSUPRATES_LEN(__nrates) (2 + (__nrates))
|
|
|
|
#define IEEE80211_TLV_DSPARMS_LEN 3
|
|
|
|
#define IEEE80211_TLV_IBSSPARMS 4
|
|
|
|
#define IEEE80211_TLV_MIN_TIM 6
|
|
|
|
|
|
|
|
#define IEEE80211_TLV_ALLRATES_LEN(__nrates) \
|
|
|
|
(((__nrates) > IEEE80211_RATE_SIZE) ? 4 + (__nrates) : 2 + (__nrates))
|
|
|
|
|
|
|
|
/* TBD factor with ieee80211_getmbuf */
|
|
|
|
static struct mbuf *
|
|
|
|
rtw_getmbuf(int flags, int type, u_int pktlen)
|
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
|
|
|
|
KASSERT2(pktlen <= MCLBYTES, ("802.11 packet too large: %u", pktlen));
|
|
|
|
MGETHDR(m, flags, type);
|
|
|
|
if (m == NULL || pktlen <= MHLEN)
|
|
|
|
return m;
|
|
|
|
MCLGET(m, flags);
|
|
|
|
if ((m->m_flags & M_EXT) != 0)
|
|
|
|
return m;
|
|
|
|
m_free(m);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TBD factor with ath_beacon_alloc */
|
|
|
|
static struct mbuf *
|
|
|
|
rtw_beacon_alloc(struct rtw_softc *sc, struct ieee80211_node *ni)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct ifnet *ifp = &ic->ic_if;
|
|
|
|
struct ieee80211_frame *wh;
|
|
|
|
struct mbuf *m;
|
|
|
|
int pktlen;
|
|
|
|
uint8_t *frm;
|
|
|
|
uint16_t capinfo;
|
|
|
|
struct ieee80211_rateset *rs;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* NB: the beacon data buffer must be 32-bit aligned;
|
|
|
|
* we assume the mbuf routines will return us something
|
|
|
|
* with this alignment (perhaps should assert).
|
|
|
|
*/
|
|
|
|
rs = &ni->ni_rates;
|
|
|
|
pktlen = sizeof(struct ieee80211_frame)
|
|
|
|
+ IEEE80211_BEACON_TIMESTAMP_LEN
|
|
|
|
+ IEEE80211_BEACON_BINTVL_LEN
|
|
|
|
+ IEEE80211_BEACON_CAPINFO_LEN
|
|
|
|
+ IEEE80211_TLV_SSID_LEN(ni->ni_esslen)
|
|
|
|
+ IEEE80211_TLV_ALLRATES_LEN(rs->rs_nrates)
|
|
|
|
+ IEEE80211_TLV_DSPARMS_LEN
|
|
|
|
+ MAX(IEEE80211_TLV_IBSSPARMS, IEEE80211_TLV_MIN_TIM);
|
|
|
|
|
|
|
|
m = rtw_getmbuf(M_DONTWAIT, MT_DATA, pktlen);
|
|
|
|
if (m == NULL) {
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_BEACON,
|
|
|
|
("%s: cannot get mbuf/cluster; size %u\n",
|
|
|
|
__func__, pktlen));
|
|
|
|
#if 0
|
|
|
|
sc->sc_stats.ast_be_nombuf++;
|
|
|
|
#endif
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
wh = mtod(m, struct ieee80211_frame *);
|
|
|
|
wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT |
|
|
|
|
IEEE80211_FC0_SUBTYPE_BEACON;
|
|
|
|
wh->i_fc[1] = IEEE80211_FC1_DIR_NODS;
|
|
|
|
*(u_int16_t *)wh->i_dur = 0;
|
|
|
|
memcpy(wh->i_addr1, ifp->if_broadcastaddr, IEEE80211_ADDR_LEN);
|
|
|
|
memcpy(wh->i_addr2, ic->ic_myaddr, IEEE80211_ADDR_LEN);
|
|
|
|
memcpy(wh->i_addr3, ni->ni_bssid, IEEE80211_ADDR_LEN);
|
|
|
|
*(u_int16_t *)wh->i_seq = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* beacon frame format
|
|
|
|
* [8] time stamp
|
|
|
|
* [2] beacon interval
|
|
|
|
* [2] cabability information
|
|
|
|
* [tlv] ssid
|
|
|
|
* [tlv] supported rates
|
|
|
|
* [tlv] parameter set (IBSS)
|
|
|
|
* [tlv] extended supported rates
|
|
|
|
*/
|
|
|
|
frm = (u_int8_t *)&wh[1];
|
|
|
|
/* timestamp is set by hardware */
|
|
|
|
memset(frm, 0, IEEE80211_BEACON_TIMESTAMP_LEN);
|
|
|
|
frm += IEEE80211_BEACON_TIMESTAMP_LEN;
|
|
|
|
*(u_int16_t *)frm = htole16(ni->ni_intval);
|
|
|
|
frm += IEEE80211_BEACON_BINTVL_LEN;
|
|
|
|
if (ic->ic_opmode == IEEE80211_M_IBSS)
|
|
|
|
capinfo = IEEE80211_CAPINFO_IBSS;
|
|
|
|
else
|
|
|
|
capinfo = IEEE80211_CAPINFO_ESS;
|
|
|
|
if (ic->ic_flags & IEEE80211_F_PRIVACY)
|
|
|
|
capinfo |= IEEE80211_CAPINFO_PRIVACY;
|
|
|
|
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
|
|
|
|
IEEE80211_IS_CHAN_2GHZ(ni->ni_chan))
|
|
|
|
capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE;
|
|
|
|
if (ic->ic_flags & IEEE80211_F_SHSLOT)
|
|
|
|
capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME;
|
|
|
|
*(u_int16_t *)frm = htole16(capinfo);
|
|
|
|
frm += IEEE80211_BEACON_CAPINFO_LEN;
|
|
|
|
*frm++ = IEEE80211_ELEMID_SSID;
|
|
|
|
*frm++ = ni->ni_esslen;
|
|
|
|
memcpy(frm, ni->ni_essid, ni->ni_esslen);
|
|
|
|
frm += ni->ni_esslen;
|
|
|
|
frm = ieee80211_add_rates(frm, rs);
|
|
|
|
*frm++ = IEEE80211_ELEMID_DSPARMS;
|
|
|
|
*frm++ = 1;
|
|
|
|
*frm++ = ieee80211_chan2ieee(ic, ni->ni_chan);
|
|
|
|
if (ic->ic_opmode == IEEE80211_M_IBSS) {
|
|
|
|
*frm++ = IEEE80211_ELEMID_IBSSPARMS;
|
|
|
|
*frm++ = 2;
|
|
|
|
*frm++ = 0; *frm++ = 0; /* TODO: ATIM window */
|
|
|
|
} else {
|
|
|
|
/* TODO: TIM */
|
|
|
|
*frm++ = IEEE80211_ELEMID_TIM;
|
|
|
|
*frm++ = 4; /* length */
|
2005-02-27 03:26:58 +03:00
|
|
|
*frm++ = 0; /* DTIM count */
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
*frm++ = 1; /* DTIM period */
|
|
|
|
*frm++ = 0; /* bitmap control */
|
|
|
|
*frm++ = 0; /* Partial Virtual Bitmap (variable length) */
|
|
|
|
}
|
|
|
|
frm = ieee80211_add_xrates(frm, rs);
|
|
|
|
m->m_pkthdr.len = m->m_len = frm - mtod(m, u_int8_t *);
|
|
|
|
m->m_pkthdr.rcvif = (void *)ni;
|
|
|
|
KASSERT2(m->m_pkthdr.len <= pktlen,
|
|
|
|
("beacon bigger than expected, len %u calculated %u",
|
|
|
|
m->m_pkthdr.len, pktlen));
|
|
|
|
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_BEACON,
|
|
|
|
("%s: m %p len %u\n", __func__, m, m->m_len));
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
/* Must be called at splnet. */
|
2004-09-26 06:29:15 +04:00
|
|
|
static int
|
|
|
|
rtw_init(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
|
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
int rc = 0;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
if ((rc = rtw_enable(sc)) != 0)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
/* Cancel pending I/O and reset. */
|
|
|
|
rtw_stop(ifp, 0);
|
|
|
|
|
|
|
|
ic->ic_bss->ni_chan = ic->ic_ibss_chan;
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_TUNE, ("%s: channel %d freq %d flags 0x%04x\n",
|
2004-09-26 06:29:15 +04:00
|
|
|
__func__, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
|
|
|
|
ic->ic_bss->ni_chan->ic_freq, ic->ic_bss->ni_chan->ic_flags));
|
|
|
|
|
|
|
|
if ((rc = rtw_pwrstate(sc, RTW_OFF)) != 0)
|
|
|
|
goto out;
|
|
|
|
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
if ((rc = rtw_swring_setup(sc)) != 0)
|
|
|
|
goto out;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
rtw_transmit_config(regs);
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_CONFIG);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_WBW(regs, RTW_MSR, RTW_BRSR);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-27 12:40:18 +03:00
|
|
|
/* long PLCP header, 1Mb/2Mb basic rate */
|
|
|
|
RTW_WRITE16(regs, RTW_BRSR, RTW_BRSR_MBR8180_2MBPS);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_BRSR, RTW_BRSR);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_ANAPARM);
|
|
|
|
rtw_set_access(regs, RTW_ACCESS_NONE);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
/* XXX from reference sources */
|
|
|
|
RTW_WRITE(regs, RTW_FEMR, 0xffff);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_FEMR, RTW_FEMR);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
rtw_set_rfprog(regs, sc->sc_rfchipid, sc->sc_dev.dv_xname);
|
|
|
|
|
|
|
|
RTW_WRITE8(regs, RTW_PHYDELAY, sc->sc_phydelay);
|
2004-09-26 06:29:15 +04:00
|
|
|
/* from Linux driver */
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_PHYDELAY, RTW_CRCOUNT);
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_enable_interrupts(sc);
|
|
|
|
|
|
|
|
rtw_pktfilt_load(sc);
|
|
|
|
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_hwring_setup(sc);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_wep_setkeys(sc, ic->ic_nw_keys, ic->ic_wep_txkey);
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_io_enable(regs, RTW_CR_RE|RTW_CR_TE, 1);
|
|
|
|
|
|
|
|
ifp->if_flags |= IFF_RUNNING;
|
|
|
|
ic->ic_state = IEEE80211_S_INIT;
|
|
|
|
|
|
|
|
RTW_WRITE16(regs, RTW_BSSID16, 0x0);
|
|
|
|
RTW_WRITE(regs, RTW_BSSID32, 0x0);
|
|
|
|
|
|
|
|
rtw_resume_ticks(sc);
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
rtw_set_nettype(sc, IEEE80211_M_MONITOR);
|
At last, I have rtw w/ Philips RF receiving packets.
I added some sysctls to aid debugging:
* hw.rtw.debug -- enable debugging
* hw.rtw.flush_rfio -- Linux voodoo: possibly makes the MAC
"flush" bits down the serial bus to the RF
* hw.rtw.host_rfio: force the host to bang bits to the RF, instead
of the MAC banging bits
* hw.rtw.rfio_delay: after telling the MAC to bang bits to the
RF front-end, delay rfio_delay microseconds.
* hw.rtw.rfprog_fallback: there is this notion of the "RF
programming method." I believe the choice influences the
polarity/timing of the serial bus used to program the RF
front-end. I know the correct choice for Intersil/RFMD/Philips
front-ends, only. For all other front-ends, I "fallback" to
rfprog_fallback.
Make rtw_txdac_enable take an rtw_softc argument. I will probably
revert this change.
Add some Linux voodoo to rtw_continuous_tx_enable. I will probably
revert this change.
Important: add rtw_set_rfprog, which sets the correct RF programming
method. This change and the following change are probably responsible
for making the Philips RF work.
Important: RTW_CONFIG1 is an 8-bit register, treat it that way!
Important: RTW_BRSR is 16-bit, RTW_CRCOUNT, RTW_PHYDELAY, and
RTW_MSR are 8-bit: treat them that way!
Vastly simplify rtw_resume_ticks.
Note to self: set the LED state to match the power state.
Hedge against the possibility that RTW_MSR is protected as
RTW_CONFIG[0123] are, meanwhile reworking that section of rtw_init
a little.
Add sc_anaparm, which isn't used, yet....
2004-12-13 03:48:02 +03:00
|
|
|
|
|
|
|
if (ic->ic_opmode == IEEE80211_M_MONITOR)
|
|
|
|
return ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
|
|
|
|
else
|
|
|
|
return ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
out:
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
printf("%s: interface not running\n", sc->sc_dev.dv_xname);
|
2004-09-26 06:29:15 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
static __inline void
|
|
|
|
rtw_led_init(struct rtw_regs *regs)
|
|
|
|
{
|
|
|
|
uint8_t cfg0, cfg1;
|
|
|
|
|
|
|
|
rtw_set_access(regs, RTW_ACCESS_CONFIG);
|
|
|
|
|
|
|
|
cfg0 = RTW_READ8(regs, RTW_CONFIG0);
|
|
|
|
cfg0 |= RTW_CONFIG0_LEDGPOEN;
|
|
|
|
RTW_WRITE8(regs, RTW_CONFIG0, cfg0);
|
|
|
|
|
|
|
|
cfg1 = RTW_READ8(regs, RTW_CONFIG1);
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_LED,
|
|
|
|
("%s: read %" PRIx8 " from reg[CONFIG1]\n", __func__, cfg1));
|
|
|
|
|
|
|
|
cfg1 &= ~RTW_CONFIG1_LEDS_MASK;
|
|
|
|
cfg1 |= RTW_CONFIG1_LEDS_TX_RX;
|
|
|
|
RTW_WRITE8(regs, RTW_CONFIG1, cfg1);
|
|
|
|
|
|
|
|
rtw_set_access(regs, RTW_ACCESS_NONE);
|
|
|
|
}
|
|
|
|
|
2005-02-27 03:26:58 +03:00
|
|
|
/*
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
* IEEE80211_S_INIT: LED1 off
|
|
|
|
*
|
|
|
|
* IEEE80211_S_AUTH,
|
|
|
|
* IEEE80211_S_ASSOC,
|
|
|
|
* IEEE80211_S_SCAN: LED1 blinks @ 1 Hz, blinks at 5Hz for tx/rx
|
|
|
|
*
|
|
|
|
* IEEE80211_S_RUN: LED1 on, blinks @ 5Hz for tx/rx
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate)
|
|
|
|
{
|
|
|
|
struct rtw_led_state *ls;
|
|
|
|
|
|
|
|
ls = &sc->sc_led_state;
|
|
|
|
|
|
|
|
switch (nstate) {
|
|
|
|
case IEEE80211_S_INIT:
|
|
|
|
rtw_led_init(&sc->sc_regs);
|
|
|
|
callout_stop(&ls->ls_slow_ch);
|
|
|
|
callout_stop(&ls->ls_fast_ch);
|
|
|
|
ls->ls_slowblink = 0;
|
|
|
|
ls->ls_actblink = 0;
|
|
|
|
ls->ls_default = 0;
|
|
|
|
break;
|
|
|
|
case IEEE80211_S_SCAN:
|
|
|
|
callout_schedule(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
|
|
|
|
callout_schedule(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case IEEE80211_S_AUTH:
|
|
|
|
case IEEE80211_S_ASSOC:
|
|
|
|
ls->ls_default = RTW_LED1;
|
|
|
|
ls->ls_actblink = RTW_LED1;
|
|
|
|
ls->ls_slowblink = RTW_LED1;
|
|
|
|
break;
|
|
|
|
case IEEE80211_S_RUN:
|
|
|
|
ls->ls_slowblink = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, int hwverid)
|
|
|
|
{
|
|
|
|
uint8_t led_condition;
|
|
|
|
bus_size_t ofs;
|
|
|
|
uint8_t mask, newval, val;
|
|
|
|
|
|
|
|
led_condition = ls->ls_default;
|
|
|
|
|
|
|
|
if (ls->ls_state & RTW_LED_S_SLOW)
|
|
|
|
led_condition ^= ls->ls_slowblink;
|
|
|
|
if (ls->ls_state & (RTW_LED_S_RX|RTW_LED_S_TX))
|
|
|
|
led_condition ^= ls->ls_actblink;
|
|
|
|
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_LED,
|
|
|
|
("%s: LED condition %" PRIx8 "\n", __func__, led_condition));
|
|
|
|
|
|
|
|
switch (hwverid) {
|
|
|
|
default:
|
|
|
|
case 'F':
|
|
|
|
ofs = RTW_PSR;
|
|
|
|
newval = mask = RTW_PSR_LEDGPO0 | RTW_PSR_LEDGPO1;
|
|
|
|
if (led_condition & RTW_LED0)
|
|
|
|
newval &= ~RTW_PSR_LEDGPO0;
|
|
|
|
if (led_condition & RTW_LED1)
|
|
|
|
newval &= ~RTW_PSR_LEDGPO1;
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
ofs = RTW_9346CR;
|
|
|
|
mask = RTW_9346CR_EEM_MASK | RTW_9346CR_EEDI | RTW_9346CR_EECS;
|
|
|
|
newval = RTW_9346CR_EEM_PROGRAM;
|
|
|
|
if (led_condition & RTW_LED0)
|
|
|
|
newval |= RTW_9346CR_EEDI;
|
|
|
|
if (led_condition & RTW_LED1)
|
|
|
|
newval |= RTW_9346CR_EECS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
val = RTW_READ8(regs, ofs);
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_LED,
|
2005-03-02 08:20:43 +03:00
|
|
|
("%s: read %" PRIx8 " from reg[%#02" PRIxPTR "]\n", __func__, val,
|
|
|
|
(uintptr_t)ofs));
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
val &= ~mask;
|
|
|
|
val |= newval;
|
|
|
|
RTW_WRITE8(regs, ofs, val);
|
|
|
|
RTW_DPRINTF(RTW_DEBUG_LED,
|
2005-03-02 08:20:43 +03:00
|
|
|
("%s: wrote %" PRIx8 " to reg[%#02" PRIxPTR "]\n", __func__, val,
|
|
|
|
(uintptr_t)ofs));
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
RTW_SYNC(regs, ofs, ofs);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_led_fastblink(void *arg)
|
|
|
|
{
|
|
|
|
int ostate, s;
|
|
|
|
struct rtw_softc *sc = (struct rtw_softc *)arg;
|
|
|
|
struct rtw_led_state *ls = &sc->sc_led_state;
|
|
|
|
|
|
|
|
s = splnet();
|
|
|
|
ostate = ls->ls_state;
|
|
|
|
ls->ls_state ^= ls->ls_event;
|
|
|
|
|
|
|
|
if ((ls->ls_event & RTW_LED_S_TX) == 0)
|
|
|
|
ls->ls_state &= ~RTW_LED_S_TX;
|
|
|
|
|
|
|
|
if ((ls->ls_event & RTW_LED_S_RX) == 0)
|
|
|
|
ls->ls_state &= ~RTW_LED_S_RX;
|
|
|
|
|
|
|
|
ls->ls_event = 0;
|
|
|
|
|
|
|
|
if (ostate != ls->ls_state)
|
|
|
|
rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
|
|
|
|
splx(s);
|
|
|
|
|
|
|
|
callout_schedule(&ls->ls_fast_ch, RTW_LED_FAST_TICKS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_led_slowblink(void *arg)
|
|
|
|
{
|
|
|
|
int s;
|
|
|
|
struct rtw_softc *sc = (struct rtw_softc *)arg;
|
|
|
|
struct rtw_led_state *ls = &sc->sc_led_state;
|
|
|
|
|
|
|
|
s = splnet();
|
|
|
|
ls->ls_state ^= RTW_LED_S_SLOW;
|
|
|
|
rtw_led_set(ls, &sc->sc_regs, sc->sc_hwverid);
|
|
|
|
splx(s);
|
|
|
|
callout_schedule(&ls->ls_slow_ch, RTW_LED_SLOW_TICKS);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2005-03-02 08:20:43 +03:00
|
|
|
rtw_led_attach(struct rtw_led_state *ls, void *arg)
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
{
|
|
|
|
callout_init(&ls->ls_fast_ch);
|
|
|
|
callout_init(&ls->ls_slow_ch);
|
2005-03-02 08:20:43 +03:00
|
|
|
callout_setfunc(&ls->ls_fast_ch, rtw_led_fastblink, arg);
|
|
|
|
callout_setfunc(&ls->ls_slow_ch, rtw_led_slowblink, arg);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static int
|
|
|
|
rtw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
|
|
|
{
|
2004-12-25 09:58:37 +03:00
|
|
|
int rc = 0, s;
|
2004-09-26 06:29:15 +04:00
|
|
|
struct rtw_softc *sc = ifp->if_softc;
|
|
|
|
struct ifreq *ifr = (struct ifreq *)data;
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
s = splnet();
|
2004-09-26 06:29:15 +04:00
|
|
|
switch (cmd) {
|
|
|
|
case SIOCSIFFLAGS:
|
|
|
|
if ((ifp->if_flags & IFF_UP) != 0) {
|
2005-01-03 06:07:12 +03:00
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) != 0) {
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_pktfilt_load(sc);
|
|
|
|
} else
|
|
|
|
rc = rtw_init(ifp);
|
2005-01-03 06:25:06 +03:00
|
|
|
RTW_PRINT_REGS(&sc->sc_regs, ifp->if_xname, __func__);
|
2004-09-26 06:29:15 +04:00
|
|
|
} else if ((sc->sc_flags & RTW_F_ENABLED) != 0) {
|
2005-01-03 06:25:06 +03:00
|
|
|
RTW_PRINT_REGS(&sc->sc_regs, ifp->if_xname, __func__);
|
2004-09-26 06:29:15 +04:00
|
|
|
rtw_stop(ifp, 1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case SIOCADDMULTI:
|
|
|
|
case SIOCDELMULTI:
|
|
|
|
if (cmd == SIOCADDMULTI)
|
|
|
|
rc = ether_addmulti(ifr, &sc->sc_ic.ic_ec);
|
|
|
|
else
|
|
|
|
rc = ether_delmulti(ifr, &sc->sc_ic.ic_ec);
|
2005-01-03 06:25:06 +03:00
|
|
|
if (rc != ENETRESET)
|
|
|
|
break;
|
|
|
|
if (ifp->if_flags & IFF_RUNNING)
|
|
|
|
rtw_pktfilt_load(sc);
|
|
|
|
rc = 0;
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
case SIOCS80211NWKEY:
|
|
|
|
if ((rc = ieee80211_ioctl(ifp, cmd, data)) != ENETRESET)
|
|
|
|
break;
|
|
|
|
rc = 0;
|
|
|
|
if ((ifp->if_flags & IFF_RUNNING) == 0)
|
|
|
|
break;
|
|
|
|
rtw_wep_setkeys(sc, sc->sc_ic.ic_nw_keys,
|
|
|
|
sc->sc_ic.ic_wep_txkey);
|
|
|
|
break;
|
2004-09-26 06:29:15 +04:00
|
|
|
default:
|
2005-01-03 06:25:06 +03:00
|
|
|
if ((rc = ieee80211_ioctl(ifp, cmd, data)) != ENETRESET)
|
|
|
|
break;
|
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) != 0)
|
|
|
|
rc = rtw_init(ifp);
|
|
|
|
else
|
|
|
|
rc = 0;
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
}
|
2004-12-25 09:58:37 +03:00
|
|
|
splx(s);
|
2004-09-26 06:29:15 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
/* Select a transmit ring with at least one h/w and s/w descriptor free.
|
|
|
|
* Return 0 on success, -1 on failure.
|
|
|
|
*/
|
|
|
|
static __inline int
|
|
|
|
rtw_txring_choose(struct rtw_softc *sc, struct rtw_txsoft_blk **tsbp,
|
|
|
|
struct rtw_txdesc_blk **tdbp, int pri)
|
|
|
|
{
|
|
|
|
struct rtw_txsoft_blk *tsb;
|
|
|
|
struct rtw_txdesc_blk *tdb;
|
|
|
|
|
|
|
|
KASSERT(pri >= 0 && pri < RTW_NTXPRI);
|
|
|
|
|
|
|
|
tsb = &sc->sc_txsoft_blk[pri];
|
|
|
|
tdb = &sc->sc_txdesc_blk[pri];
|
|
|
|
|
|
|
|
if (SIMPLEQ_EMPTY(&tsb->tsb_freeq) || tdb->tdb_nfree == 0) {
|
|
|
|
*tsbp = NULL;
|
|
|
|
*tdbp = NULL;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
*tsbp = tsb;
|
|
|
|
*tdbp = tdb;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline struct mbuf *
|
|
|
|
rtw_80211_dequeue(struct rtw_softc *sc, struct ifqueue *ifq, int pri,
|
|
|
|
struct rtw_txsoft_blk **tsbp, struct rtw_txdesc_blk **tdbp,
|
|
|
|
struct ieee80211_node **nip, short *if_flagsp)
|
|
|
|
{
|
|
|
|
struct mbuf *m;
|
|
|
|
|
|
|
|
if (IF_IS_EMPTY(ifq))
|
|
|
|
return NULL;
|
|
|
|
if (rtw_txring_choose(sc, tsbp, tdbp, pri) == -1) {
|
|
|
|
*if_flagsp |= IFF_OACTIVE;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
IF_DEQUEUE(ifq, m);
|
|
|
|
*nip = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
|
|
|
m->m_pkthdr.rcvif = NULL;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
/* Point *mp at the next 802.11 frame to transmit. Point *tsbp
|
2004-09-26 06:29:15 +04:00
|
|
|
* at the driver's selection of transmit control block for the packet.
|
|
|
|
*/
|
|
|
|
static __inline int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_dequeue(struct ifnet *ifp, struct rtw_txsoft_blk **tsbp,
|
|
|
|
struct rtw_txdesc_blk **tdbp, struct mbuf **mp,
|
2004-09-26 06:29:15 +04:00
|
|
|
struct ieee80211_node **nip)
|
|
|
|
{
|
|
|
|
struct mbuf *m0;
|
|
|
|
struct rtw_softc *sc;
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
short *if_flagsp;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
sc = (struct rtw_softc *)ifp->if_softc;
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT,
|
|
|
|
("%s: enter %s\n", sc->sc_dev.dv_xname, __func__));
|
2004-09-26 06:29:15 +04:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if_flagsp = &ifp->if_flags;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if (sc->sc_ic.ic_state == IEEE80211_S_RUN &&
|
|
|
|
(*mp = rtw_80211_dequeue(sc, &sc->sc_beaconq, RTW_TXPRIBCN, tsbp,
|
|
|
|
tdbp, nip, if_flagsp)) != NULL) {
|
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue beacon frame\n",
|
|
|
|
__func__));
|
2004-12-19 11:19:25 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if ((*mp = rtw_80211_dequeue(sc, &sc->sc_ic.ic_mgtq, RTW_TXPRIMD, tsbp,
|
|
|
|
tdbp, nip, if_flagsp)) != NULL) {
|
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue mgt frame\n",
|
|
|
|
__func__));
|
|
|
|
return 0;
|
|
|
|
}
|
2004-12-19 11:19:25 +03:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if (sc->sc_ic.ic_state != IEEE80211_S_RUN) {
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: not running\n", __func__));
|
2004-09-26 06:29:15 +04:00
|
|
|
return 0;
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((*mp = rtw_80211_dequeue(sc, &sc->sc_ic.ic_pwrsaveq, RTW_TXPRIHI,
|
|
|
|
tsbp, tdbp, nip, if_flagsp)) != NULL) {
|
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue pwrsave frame\n",
|
|
|
|
__func__));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rtw_txring_choose(sc, tsbp, tdbp, RTW_TXPRIMD) == -1) {
|
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no descriptor\n", __func__));
|
|
|
|
*if_flagsp |= IFF_OACTIVE;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*mp = NULL;
|
|
|
|
|
|
|
|
IFQ_DEQUEUE(&ifp->if_snd, m0);
|
|
|
|
if (m0 == NULL) {
|
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: no frame/ring ready\n",
|
|
|
|
__func__));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: dequeue data frame\n", __func__));
|
|
|
|
ifp->if_opackets++;
|
2004-09-26 06:29:15 +04:00
|
|
|
#if NBPFILTER > 0
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if (ifp->if_bpf)
|
|
|
|
bpf_mtap(ifp->if_bpf, m0);
|
2004-09-26 06:29:15 +04:00
|
|
|
#endif
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if ((m0 = ieee80211_encap(ifp, m0, nip)) == NULL) {
|
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT,
|
|
|
|
("%s: encap error\n", __func__));
|
|
|
|
ifp->if_oerrors++;
|
|
|
|
return -1;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: leave\n", __func__));
|
2004-09-26 06:29:15 +04:00
|
|
|
*mp = m0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
static int
|
|
|
|
rtw_seg_too_short(bus_dmamap_t dmamap)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < dmamap->dm_nsegs; i++) {
|
|
|
|
if (dmamap->dm_segs[i].ds_len < 4) {
|
|
|
|
printf("%s: segment too short\n", __func__);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2004-12-19 11:19:25 +03:00
|
|
|
/* TBD factor with atw_start */
|
|
|
|
static struct mbuf *
|
|
|
|
rtw_dmamap_load_txbuf(bus_dma_tag_t dmat, bus_dmamap_t dmam, struct mbuf *chain,
|
|
|
|
u_int ndescfree, short *ifflagsp, const char *dvname)
|
|
|
|
{
|
|
|
|
int first, rc;
|
|
|
|
struct mbuf *m, *m0;
|
|
|
|
|
|
|
|
m0 = chain;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Load the DMA map. Copy and try (once) again if the packet
|
|
|
|
* didn't fit in the alloted number of segments.
|
|
|
|
*/
|
|
|
|
for (first = 1;
|
|
|
|
((rc = bus_dmamap_load_mbuf(dmat, dmam, m0,
|
|
|
|
BUS_DMA_WRITE|BUS_DMA_NOWAIT)) != 0 ||
|
2004-12-25 09:58:37 +03:00
|
|
|
dmam->dm_nsegs > ndescfree || rtw_seg_too_short(dmam)) && first;
|
2004-12-19 11:19:25 +03:00
|
|
|
first = 0) {
|
|
|
|
if (rc == 0)
|
|
|
|
bus_dmamap_unload(dmat, dmam);
|
|
|
|
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
|
|
|
if (m == NULL) {
|
|
|
|
printf("%s: unable to allocate Tx mbuf\n",
|
|
|
|
dvname);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (m0->m_pkthdr.len > MHLEN) {
|
|
|
|
MCLGET(m, M_DONTWAIT);
|
|
|
|
if ((m->m_flags & M_EXT) == 0) {
|
|
|
|
printf("%s: cannot allocate Tx cluster\n",
|
|
|
|
dvname);
|
|
|
|
m_freem(m);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
|
|
|
|
m->m_pkthdr.len = m->m_len = m0->m_pkthdr.len;
|
|
|
|
m_freem(m0);
|
|
|
|
m0 = m;
|
|
|
|
m = NULL;
|
|
|
|
}
|
|
|
|
if (rc != 0) {
|
|
|
|
printf("%s: cannot load Tx buffer, rc = %d\n", dvname, rc);
|
|
|
|
m_freem(m0);
|
|
|
|
return NULL;
|
2004-12-25 09:58:37 +03:00
|
|
|
} else if (rtw_seg_too_short(dmam)) {
|
|
|
|
printf("%s: cannot load Tx buffer, segment too short\n",
|
|
|
|
dvname);
|
|
|
|
bus_dmamap_unload(dmat, dmam);
|
|
|
|
m_freem(m0);
|
|
|
|
return NULL;
|
2004-12-19 11:19:25 +03:00
|
|
|
} else if (dmam->dm_nsegs > ndescfree) {
|
|
|
|
*ifflagsp |= IFF_OACTIVE;
|
|
|
|
bus_dmamap_unload(dmat, dmam);
|
|
|
|
m_freem(m0);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return m0;
|
|
|
|
}
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
#ifdef RTW_DEBUG
|
2004-12-23 08:57:18 +03:00
|
|
|
static void
|
|
|
|
rtw_print_txdesc(struct rtw_softc *sc, const char *action,
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft *ts, struct rtw_txdesc_blk *tdb, int desc)
|
2004-12-23 08:57:18 +03:00
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txdesc *td = &tdb->tdb_desc[desc];
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT_DESC, ("%s: %p %s txdesc[%d] ctl0 %#08x "
|
2004-12-23 08:57:18 +03:00
|
|
|
"ctl1 %#08x buf %#08x len %#08x\n",
|
2004-12-29 04:06:52 +03:00
|
|
|
sc->sc_dev.dv_xname, ts, action, desc,
|
|
|
|
le32toh(td->td_ctl0),
|
|
|
|
le32toh(td->td_ctl1), le32toh(td->td_buf),
|
|
|
|
le32toh(td->td_len)));
|
2004-12-23 08:57:18 +03:00
|
|
|
}
|
2004-12-25 09:58:37 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-23 08:57:18 +03:00
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static void
|
|
|
|
rtw_start(struct ifnet *ifp)
|
|
|
|
{
|
2004-12-21 02:05:41 +03:00
|
|
|
uint8_t tppoll;
|
2004-12-19 11:19:25 +03:00
|
|
|
int desc, i, lastdesc, npkt, rate;
|
2004-12-23 08:52:27 +03:00
|
|
|
uint32_t proto_ctl0, ctl0, ctl1;
|
2004-12-19 11:19:25 +03:00
|
|
|
bus_dmamap_t dmamap;
|
|
|
|
struct ieee80211com *ic;
|
|
|
|
struct ieee80211_duration *d0;
|
|
|
|
struct ieee80211_frame *wh;
|
|
|
|
struct ieee80211_node *ni;
|
|
|
|
struct mbuf *m0;
|
|
|
|
struct rtw_softc *sc;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft_blk *tsb;
|
|
|
|
struct rtw_txdesc_blk *tdb;
|
|
|
|
struct rtw_txsoft *ts;
|
|
|
|
struct rtw_txdesc *td;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
sc = (struct rtw_softc *)ifp->if_softc;
|
2004-12-19 11:19:25 +03:00
|
|
|
ic = &sc->sc_ic;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT,
|
|
|
|
("%s: enter %s\n", sc->sc_dev.dv_xname, __func__));
|
2004-12-19 11:19:25 +03:00
|
|
|
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING)
|
|
|
|
goto out;
|
|
|
|
|
2004-12-19 11:19:25 +03:00
|
|
|
/* XXX do real rate control */
|
2004-12-23 08:52:27 +03:00
|
|
|
proto_ctl0 = RTW_TXCTL0_RTSRATE_1MBPS;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0)
|
2004-12-23 08:52:27 +03:00
|
|
|
proto_ctl0 |= RTW_TXCTL0_SPLCP;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
for (;;) {
|
2004-12-29 04:06:52 +03:00
|
|
|
if (rtw_dequeue(ifp, &tsb, &tdb, &m0, &ni) == -1)
|
2004-09-26 06:29:15 +04:00
|
|
|
continue;
|
|
|
|
if (m0 == NULL)
|
|
|
|
break;
|
2004-12-29 04:06:52 +03:00
|
|
|
ts = SIMPLEQ_FIRST(&tsb->tsb_freeq);
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
dmamap = ts->ts_dmamap;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
m0 = rtw_dmamap_load_txbuf(sc->sc_dmat, dmamap, m0,
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb->tdb_nfree, &ifp->if_flags, sc->sc_dev.dv_xname);
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
if (m0 == NULL || dmamap->dm_nsegs == 0) {
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT,
|
|
|
|
("%s: fail dmamap load\n", __func__));
|
2004-12-19 11:19:25 +03:00
|
|
|
goto post_dequeue_err;
|
|
|
|
}
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
wh = mtod(m0, struct ieee80211_frame *);
|
|
|
|
|
|
|
|
/* XXX do real rate control */
|
|
|
|
if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
|
|
|
|
IEEE80211_FC0_TYPE_MGT)
|
|
|
|
rate = 2;
|
|
|
|
else
|
|
|
|
rate = MAX(2, ieee80211_get_rate(ic));
|
|
|
|
|
2004-12-23 08:57:18 +03:00
|
|
|
#ifdef RTW_DEBUG
|
|
|
|
if ((sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
|
|
|
|
(IFF_DEBUG|IFF_LINK2)) {
|
|
|
|
ieee80211_dump_pkt(mtod(m0, uint8_t *),
|
|
|
|
(dmamap->dm_nsegs == 1) ? m0->m_pkthdr.len
|
|
|
|
: sizeof(wh),
|
|
|
|
rate, 0);
|
|
|
|
}
|
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-23 08:52:27 +03:00
|
|
|
ctl0 = proto_ctl0 |
|
2004-12-19 11:19:25 +03:00
|
|
|
LSHIFT(m0->m_pkthdr.len, RTW_TXCTL0_TPKTSIZE_MASK);
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
switch (rate) {
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
default:
|
|
|
|
case 2:
|
|
|
|
ctl0 |= RTW_TXCTL0_RATE_1MBPS;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
ctl0 |= RTW_TXCTL0_RATE_2MBPS;
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
ctl0 |= RTW_TXCTL0_RATE_5MBPS;
|
|
|
|
break;
|
|
|
|
case 22:
|
|
|
|
ctl0 |= RTW_TXCTL0_RATE_11MBPS;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
/* XXX >= ? Compare after fragmentation? */
|
|
|
|
if (m0->m_pkthdr.len > ic->ic_rtsthreshold)
|
|
|
|
ctl0 |= RTW_TXCTL0_RTSEN;
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0)
|
|
|
|
ctl0 |= LSHIFT(sc->sc_txkey, RTW_TXCTL0_KEYID_MASK);
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
|
|
|
|
IEEE80211_FC0_TYPE_MGT) {
|
|
|
|
ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN);
|
|
|
|
if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
|
|
|
|
IEEE80211_FC0_SUBTYPE_BEACON)
|
|
|
|
ctl0 |= RTW_TXCTL0_BEACON;
|
|
|
|
}
|
|
|
|
|
2004-12-23 09:08:52 +03:00
|
|
|
if (ieee80211_compute_duration(wh, m0->m_pkthdr.len,
|
2004-12-19 11:19:25 +03:00
|
|
|
ic->ic_flags, ic->ic_fragthreshold,
|
2004-12-29 04:06:52 +03:00
|
|
|
rate, &ts->ts_d0, &ts->ts_dn, &npkt,
|
2004-12-23 09:08:52 +03:00
|
|
|
(sc->sc_if.if_flags & (IFF_DEBUG|IFF_LINK2)) ==
|
|
|
|
(IFF_DEBUG|IFF_LINK2)) == -1) {
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT,
|
|
|
|
("%s: fail compute duration\n", __func__));
|
2004-12-19 11:19:25 +03:00
|
|
|
goto post_load_err;
|
|
|
|
}
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
d0 = &ts->ts_d0;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-23 09:12:43 +03:00
|
|
|
*(uint16_t*)wh->i_dur = htole16(d0->d_data_dur);
|
|
|
|
|
2004-12-23 08:52:27 +03:00
|
|
|
ctl1 = LSHIFT(d0->d_plcp_len, RTW_TXCTL1_LENGTH_MASK) |
|
2004-12-19 11:19:25 +03:00
|
|
|
LSHIFT(d0->d_rts_dur, RTW_TXCTL1_RTSDUR_MASK);
|
|
|
|
|
2004-12-27 04:51:49 +03:00
|
|
|
if (d0->d_residue)
|
2004-12-23 08:52:27 +03:00
|
|
|
ctl1 |= RTW_TXCTL1_LENGEXT;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
/* TBD fragmentation */
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
ts->ts_first = tdb->tdb_next;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,
|
2004-12-19 11:19:25 +03:00
|
|
|
BUS_DMASYNC_PREWRITE);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
KASSERT(ts->ts_first < tdb->tdb_ndesc);
|
2004-12-25 09:58:37 +03:00
|
|
|
|
2004-12-29 01:30:07 +03:00
|
|
|
#if NBPFILTER > 0
|
|
|
|
if (ic->ic_rawbpf != NULL)
|
|
|
|
bpf_mtap((caddr_t)ic->ic_rawbpf, m0);
|
|
|
|
|
|
|
|
if (sc->sc_radiobpf != NULL) {
|
|
|
|
struct rtw_tx_radiotap_header *rt = &sc->sc_txtap;
|
|
|
|
|
|
|
|
rt->rt_flags = 0;
|
|
|
|
rt->rt_rate = rate;
|
|
|
|
rt->rt_chan_freq =
|
|
|
|
htole16(ic->ic_bss->ni_chan->ic_freq);
|
|
|
|
rt->rt_chan_flags =
|
|
|
|
htole16(ic->ic_bss->ni_chan->ic_flags);
|
|
|
|
|
|
|
|
bpf_mtap2(sc->sc_radiobpf, (caddr_t)rt,
|
|
|
|
sizeof(sc->sc_txtapu), m0);
|
|
|
|
}
|
|
|
|
#endif /* NPBFILTER > 0 */
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
for (i = 0, lastdesc = desc = ts->ts_first;
|
2004-12-19 11:19:25 +03:00
|
|
|
i < dmamap->dm_nsegs;
|
2004-12-29 04:06:52 +03:00
|
|
|
i++, desc = RTW_NEXT_IDX(tdb, desc)) {
|
2004-12-19 11:19:25 +03:00
|
|
|
if (dmamap->dm_segs[i].ds_len > RTW_TXLEN_LENGTH_MASK) {
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT_DESC,
|
|
|
|
("%s: seg too long\n", __func__));
|
2004-12-19 11:19:25 +03:00
|
|
|
goto post_load_err;
|
|
|
|
}
|
2004-12-29 04:06:52 +03:00
|
|
|
td = &tdb->tdb_desc[desc];
|
|
|
|
td->td_ctl0 = htole32(ctl0);
|
2004-12-19 11:19:25 +03:00
|
|
|
if (i != 0)
|
2004-12-29 04:06:52 +03:00
|
|
|
td->td_ctl0 |= htole32(RTW_TXCTL0_OWN);
|
|
|
|
td->td_ctl1 = htole32(ctl1);
|
|
|
|
td->td_buf = htole32(dmamap->dm_segs[i].ds_addr);
|
|
|
|
td->td_len = htole32(dmamap->dm_segs[i].ds_len);
|
2004-12-19 11:19:25 +03:00
|
|
|
lastdesc = desc;
|
2004-12-23 08:57:18 +03:00
|
|
|
#ifdef RTW_DEBUG
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_print_txdesc(sc, "load", ts, tdb, desc);
|
2004-12-23 08:57:18 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-19 11:19:25 +03:00
|
|
|
}
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
KASSERT(desc < tdb->tdb_ndesc);
|
2004-12-25 09:58:37 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
ts->ts_ni = ni;
|
|
|
|
ts->ts_mbuf = m0;
|
|
|
|
ts->ts_last = lastdesc;
|
|
|
|
tdb->tdb_desc[ts->ts_last].td_ctl0 |= htole32(RTW_TXCTL0_LS);
|
|
|
|
tdb->tdb_desc[ts->ts_first].td_ctl0 |=
|
2004-12-23 08:57:18 +03:00
|
|
|
htole32(RTW_TXCTL0_FS);
|
|
|
|
|
|
|
|
#ifdef RTW_DEBUG
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_print_txdesc(sc, "FS on", ts, tdb, ts->ts_first);
|
|
|
|
rtw_print_txdesc(sc, "LS on", ts, tdb, ts->ts_last);
|
2004-12-23 08:57:18 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb->tdb_nfree -= dmamap->dm_nsegs;
|
|
|
|
tdb->tdb_next = desc;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdescs_sync(tdb, ts->ts_first, dmamap->dm_nsegs,
|
2004-12-19 11:19:25 +03:00
|
|
|
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb->tdb_desc[ts->ts_first].td_ctl0 |=
|
2004-12-19 11:19:25 +03:00
|
|
|
htole32(RTW_TXCTL0_OWN);
|
|
|
|
|
2004-12-23 08:57:18 +03:00
|
|
|
#ifdef RTW_DEBUG
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_print_txdesc(sc, "OWN on", ts, tdb, ts->ts_first);
|
2004-12-23 08:57:18 +03:00
|
|
|
#endif /* RTW_DEBUG */
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdescs_sync(tdb, ts->ts_first, 1,
|
2004-12-19 11:19:25 +03:00
|
|
|
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
SIMPLEQ_REMOVE_HEAD(&tsb->tsb_freeq, ts_q);
|
|
|
|
SIMPLEQ_INSERT_TAIL(&tsb->tsb_dirtyq, ts, ts_q);
|
2004-12-19 11:19:25 +03:00
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
if (tsb != &sc->sc_txsoft_blk[RTW_TXPRIBCN]) {
|
|
|
|
sc->sc_led_state.ls_event |= RTW_LED_S_TX;
|
|
|
|
tsb->tsb_tx_timer = 5;
|
|
|
|
ifp->if_timer = 1;
|
|
|
|
}
|
2004-12-21 02:05:41 +03:00
|
|
|
tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL);
|
2005-03-02 08:20:43 +03:00
|
|
|
tppoll &= ~RTW_TPPOLL_SALL;
|
|
|
|
tppoll |= tsb->tsb_poll & RTW_TPPOLL_ALL;
|
|
|
|
RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, tppoll);
|
2004-12-20 04:28:24 +03:00
|
|
|
RTW_SYNC(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
If defined(RTW_DEBUG), provide a sysctl (hw.rtw.rxbufs_limit) for
limiting the number of rx buffers an rtw may allocate. Use this
sysctl to test the code that copes with buffer exhaustion.
Allocate at most RTW_RXQLEN rx buffers, stopping at the sysctl
limit. Record in sc_nrxdesc how many were allocated, and put the
end-of-ring indication on sc_rxdesc[sc_nrxdesc - 1]. In rtw_init,
if no rx buffers could be allocated, log a complaint, clear
IFF_RUNNING, and exit with an error.
Many changes to accomodate a short rx ring, mainly of the "add a
rx-ring length argument" variety. XXX I really should consolidate
all of the rx ring variables in one struct and pass that to the
rx-ring subroutines.
Bug fix: after calling MCLGET, use the (m->m_flags & M_EXT) idiom
to check for success, instead of m != NULL.
Bug fix: at the top of rtw_start, if IFF_RUNNING is not set, or
IFF_OACTIVE is, get out.
2004-12-29 01:21:15 +03:00
|
|
|
out:
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_XMIT, ("%s: leave\n", __func__));
|
2004-12-19 11:19:25 +03:00
|
|
|
return;
|
|
|
|
post_load_err:
|
|
|
|
bus_dmamap_unload(sc->sc_dmat, dmamap);
|
|
|
|
m_freem(m0);
|
|
|
|
post_dequeue_err:
|
|
|
|
ieee80211_release_node(&sc->sc_ic, ni);
|
2004-09-26 06:29:15 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_watchdog(struct ifnet *ifp)
|
|
|
|
{
|
2004-12-19 11:19:25 +03:00
|
|
|
int pri;
|
|
|
|
struct rtw_softc *sc;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft_blk *tsb;
|
2004-12-19 11:19:25 +03:00
|
|
|
|
|
|
|
sc = ifp->if_softc;
|
|
|
|
|
|
|
|
ifp->if_timer = 0;
|
|
|
|
|
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
tsb = &sc->sc_txsoft_blk[pri];
|
2004-12-19 11:19:25 +03:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
if (tsb->tsb_tx_timer == 0)
|
2004-12-19 11:19:25 +03:00
|
|
|
continue;
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
if (--tsb->tsb_tx_timer == 0) {
|
|
|
|
if (SIMPLEQ_EMPTY(&tsb->tsb_dirtyq))
|
2004-12-19 11:19:25 +03:00
|
|
|
continue;
|
|
|
|
printf("%s: transmit timeout, priority %d\n",
|
|
|
|
ifp->if_xname, pri);
|
|
|
|
ifp->if_oerrors++;
|
2004-12-27 22:49:16 +03:00
|
|
|
/* Stop Tx DMA, disable transmitter, clear
|
|
|
|
* Tx rings, and restart.
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
*
|
|
|
|
* TBD Stop/restart just the broken ring?
|
2004-12-27 22:49:16 +03:00
|
|
|
*/
|
2005-03-02 08:20:43 +03:00
|
|
|
RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
|
2004-12-27 22:49:16 +03:00
|
|
|
RTW_SYNC(&sc->sc_regs, RTW_TPPOLL, RTW_TPPOLL);
|
|
|
|
rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 0);
|
2004-12-25 09:58:37 +03:00
|
|
|
rtw_txdescs_reset(sc);
|
2004-12-27 22:49:16 +03:00
|
|
|
rtw_io_enable(&sc->sc_regs, RTW_CR_TE, 1);
|
2005-03-02 08:20:43 +03:00
|
|
|
sc->sc_if.if_flags &= ~IFF_OACTIVE;
|
2004-12-19 11:19:25 +03:00
|
|
|
rtw_start(ifp);
|
|
|
|
} else
|
|
|
|
ifp->if_timer = 1;
|
|
|
|
}
|
2004-12-21 02:05:41 +03:00
|
|
|
ieee80211_watchdog(ifp);
|
2004-09-26 06:29:15 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_next_scan(void *arg)
|
|
|
|
{
|
|
|
|
struct ieee80211com *ic = arg;
|
|
|
|
int s;
|
|
|
|
|
|
|
|
/* don't call rtw_start w/o network interrupts blocked */
|
|
|
|
s = splnet();
|
|
|
|
if (ic->ic_state == IEEE80211_S_SCAN)
|
|
|
|
ieee80211_next_scan(ic);
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
static void
|
2005-03-02 08:20:43 +03:00
|
|
|
rtw_join_bss(struct rtw_softc *sc, uint8_t *bssid, uint16_t intval0)
|
2004-12-21 02:05:41 +03:00
|
|
|
{
|
|
|
|
uint16_t bcnitv, intval;
|
|
|
|
int i;
|
|
|
|
struct rtw_regs *regs = &sc->sc_regs;
|
|
|
|
|
|
|
|
for (i = 0; i < IEEE80211_ADDR_LEN; i++)
|
|
|
|
RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]);
|
|
|
|
|
|
|
|
RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32);
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_CONFIG);
|
2004-12-21 02:05:41 +03:00
|
|
|
|
|
|
|
intval = MIN(intval0, PRESHIFT(RTW_BCNITV_BCNITV_MASK));
|
|
|
|
|
|
|
|
bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK;
|
|
|
|
bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK);
|
|
|
|
RTW_WRITE16(regs, RTW_BCNITV, bcnitv);
|
|
|
|
/* magic from Linux */
|
|
|
|
RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND));
|
|
|
|
RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV));
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_set_access(regs, RTW_ACCESS_NONE);
|
2004-12-21 02:05:41 +03:00
|
|
|
|
|
|
|
/* TBD WEP */
|
|
|
|
RTW_WRITE8(regs, RTW_SCR, 0);
|
|
|
|
|
|
|
|
rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1);
|
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
/* Synchronize the hardware state with the software state. */
|
|
|
|
static int
|
|
|
|
rtw_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
|
|
|
|
{
|
|
|
|
struct ifnet *ifp = &ic->ic_if;
|
|
|
|
struct rtw_softc *sc = ifp->if_softc;
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
struct mbuf *m;
|
2004-09-26 06:29:15 +04:00
|
|
|
enum ieee80211_state ostate;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
ostate = ic->ic_state;
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_led_newstate(sc, nstate);
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
if (nstate == IEEE80211_S_INIT) {
|
|
|
|
callout_stop(&sc->sc_scan_ch);
|
|
|
|
sc->sc_cur_chan = IEEE80211_CHAN_ANY;
|
|
|
|
return (*sc->sc_mtbl.mt_newstate)(ic, nstate, arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT)
|
|
|
|
rtw_pwrstate(sc, RTW_ON);
|
|
|
|
|
|
|
|
if ((error = rtw_tune(sc)) != 0)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
switch (nstate) {
|
|
|
|
case IEEE80211_S_INIT:
|
|
|
|
panic("%s: unexpected state IEEE80211_S_INIT\n", __func__);
|
|
|
|
break;
|
|
|
|
case IEEE80211_S_SCAN:
|
2004-12-25 09:58:37 +03:00
|
|
|
if (ostate != IEEE80211_S_SCAN) {
|
|
|
|
(void)memset(ic->ic_bss->ni_bssid, 0,
|
|
|
|
IEEE80211_ADDR_LEN);
|
2005-03-02 08:20:43 +03:00
|
|
|
rtw_set_nettype(sc, IEEE80211_M_MONITOR);
|
2004-12-25 09:58:37 +03:00
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
callout_reset(&sc->sc_scan_ch, rtw_dwelltime * hz / 1000,
|
|
|
|
rtw_next_scan, ic);
|
|
|
|
|
|
|
|
break;
|
|
|
|
case IEEE80211_S_RUN:
|
2005-01-03 06:07:12 +03:00
|
|
|
switch (ic->ic_opmode) {
|
|
|
|
case IEEE80211_M_HOSTAP:
|
|
|
|
case IEEE80211_M_IBSS:
|
2005-03-02 08:20:43 +03:00
|
|
|
rtw_set_nettype(sc, IEEE80211_M_MONITOR);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
m = rtw_beacon_alloc(sc, ic->ic_bss);
|
|
|
|
if (m == NULL) {
|
|
|
|
printf("%s: could not allocate beacon\n",
|
|
|
|
sc->sc_dev.dv_xname);
|
|
|
|
} else
|
|
|
|
IF_ENQUEUE(&sc->sc_beaconq, m);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case IEEE80211_M_AHDEMO:
|
2005-03-02 08:20:43 +03:00
|
|
|
case IEEE80211_M_STA:
|
|
|
|
rtw_join_bss(sc, ic->ic_bss->ni_bssid,
|
2005-01-03 06:07:12 +03:00
|
|
|
ic->ic_bss->ni_intval);
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
2005-01-03 06:07:12 +03:00
|
|
|
case IEEE80211_M_MONITOR:
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
2005-01-03 06:07:12 +03:00
|
|
|
}
|
2005-03-02 08:20:43 +03:00
|
|
|
rtw_set_nettype(sc, ic->ic_opmode);
|
2005-01-03 06:07:12 +03:00
|
|
|
break;
|
2005-03-02 08:20:43 +03:00
|
|
|
case IEEE80211_S_ASSOC:
|
2005-01-03 06:07:12 +03:00
|
|
|
case IEEE80211_S_AUTH:
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nstate != IEEE80211_S_SCAN)
|
|
|
|
callout_stop(&sc->sc_scan_ch);
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
/* Start beacon transmission. */
|
2004-09-26 06:29:15 +04:00
|
|
|
if (nstate == IEEE80211_S_RUN &&
|
|
|
|
(ic->ic_opmode == IEEE80211_M_HOSTAP ||
|
|
|
|
ic->ic_opmode == IEEE80211_M_IBSS))
|
2005-03-02 08:20:43 +03:00
|
|
|
rtw_start(&sc->sc_if);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
return (*sc->sc_mtbl.mt_newstate)(ic, nstate, arg);
|
|
|
|
}
|
|
|
|
|
2005-01-04 04:00:30 +03:00
|
|
|
/* Extend a 32-bit TSF timestamp to a 64-bit timestamp. */
|
|
|
|
static uint64_t
|
|
|
|
rtw_tsf_extend(struct rtw_regs *regs, uint32_t rstamp)
|
|
|
|
{
|
|
|
|
uint32_t tsftl, tsfth;
|
|
|
|
|
|
|
|
tsfth = RTW_READ(regs, RTW_TSFTRH);
|
|
|
|
tsftl = RTW_READ(regs, RTW_TSFTRL);
|
|
|
|
if (tsftl < rstamp) /* Compensate for rollover. */
|
|
|
|
tsfth--;
|
|
|
|
return ((uint64_t)tsfth << 32) | rstamp;
|
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
static void
|
2005-01-04 04:00:30 +03:00
|
|
|
rtw_ibss_merge(struct rtw_softc *sc, struct ieee80211_node *ni, uint32_t rstamp)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2005-03-02 08:20:43 +03:00
|
|
|
uint8_t tppoll;
|
2005-01-04 04:00:30 +03:00
|
|
|
struct ieee80211com *ic = &sc->sc_ic;
|
|
|
|
|
|
|
|
if (le64toh(ni->ni_tsf) >= rtw_tsf_extend(&sc->sc_regs, rstamp) &&
|
|
|
|
ieee80211_ibss_merge(ic, ni) == ENETRESET) {
|
2005-03-02 08:20:43 +03:00
|
|
|
/* Stop beacon queue. Kick state machine to synchronize
|
|
|
|
* with the new IBSS.
|
|
|
|
*/
|
|
|
|
tppoll = RTW_READ8(&sc->sc_regs, RTW_TPPOLL);
|
|
|
|
tppoll |= RTW_TPPOLL_SBQ;
|
|
|
|
RTW_WRITE8(&sc->sc_regs, RTW_TPPOLL, tppoll);
|
|
|
|
(void)ieee80211_new_state(&sc->sc_ic, IEEE80211_S_RUN, -1);
|
2005-01-04 04:00:30 +03:00
|
|
|
}
|
2004-09-26 06:29:15 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_recv_mgmt(struct ieee80211com *ic, struct mbuf *m,
|
2005-01-02 07:23:03 +03:00
|
|
|
struct ieee80211_node *ni, int subtype, int rssi, uint32_t rstamp)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
struct rtw_softc *sc = (struct rtw_softc*)ic->ic_softc;
|
|
|
|
|
2005-01-04 04:00:30 +03:00
|
|
|
(*sc->sc_mtbl.mt_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp);
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
switch (subtype) {
|
|
|
|
case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
|
|
|
|
case IEEE80211_FC0_SUBTYPE_BEACON:
|
2005-01-04 04:00:30 +03:00
|
|
|
if (ic->ic_opmode != IEEE80211_M_IBSS ||
|
|
|
|
ic->ic_state != IEEE80211_S_RUN)
|
|
|
|
return;
|
|
|
|
rtw_ibss_merge(sc, ni, rstamp);
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct ieee80211_node *
|
|
|
|
rtw_node_alloc(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
struct rtw_softc *sc = (struct rtw_softc *)ic->ic_if.if_softc;
|
|
|
|
struct ieee80211_node *ni = (*sc->sc_mtbl.mt_node_alloc)(ic);
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_NODE,
|
|
|
|
("%s: alloc node %p\n", sc->sc_dev.dv_xname, ni));
|
2004-09-26 06:29:15 +04:00
|
|
|
return ni;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
|
|
|
|
{
|
|
|
|
struct rtw_softc *sc = (struct rtw_softc *)ic->ic_if.if_softc;
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_NODE,
|
|
|
|
("%s: freeing node %p %s\n", sc->sc_dev.dv_xname, ni,
|
2004-09-26 06:29:15 +04:00
|
|
|
ether_sprintf(ni->ni_bssid)));
|
|
|
|
(*sc->sc_mtbl.mt_node_free)(ic, ni);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
rtw_media_change(struct ifnet *ifp)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = ieee80211_media_change(ifp);
|
|
|
|
if (error == ENETRESET) {
|
|
|
|
if ((ifp->if_flags & (IFF_RUNNING|IFF_UP)) ==
|
|
|
|
(IFF_RUNNING|IFF_UP))
|
|
|
|
rtw_init(ifp); /* XXX lose error */
|
|
|
|
error = 0;
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_media_status(struct ifnet *ifp, struct ifmediareq *imr)
|
|
|
|
{
|
|
|
|
struct rtw_softc *sc = ifp->if_softc;
|
|
|
|
|
|
|
|
if ((sc->sc_flags & RTW_F_ENABLED) == 0) {
|
|
|
|
imr->ifm_active = IFM_IEEE80211 | IFM_NONE;
|
|
|
|
imr->ifm_status = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ieee80211_media_status(ifp, imr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rtw_power(int why, void *arg)
|
|
|
|
{
|
|
|
|
struct rtw_softc *sc = arg;
|
|
|
|
struct ifnet *ifp = &sc->sc_ic.ic_if;
|
|
|
|
int s;
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
DPRINTF(sc, RTW_DEBUG_PWR,
|
|
|
|
("%s: rtw_power(%d,)\n", sc->sc_dev.dv_xname, why));
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
s = splnet();
|
|
|
|
switch (why) {
|
|
|
|
case PWR_STANDBY:
|
|
|
|
/* XXX do nothing. */
|
|
|
|
break;
|
|
|
|
case PWR_SUSPEND:
|
|
|
|
rtw_stop(ifp, 0);
|
|
|
|
if (sc->sc_power != NULL)
|
|
|
|
(*sc->sc_power)(sc, why);
|
|
|
|
break;
|
|
|
|
case PWR_RESUME:
|
|
|
|
if (ifp->if_flags & IFF_UP) {
|
|
|
|
if (sc->sc_power != NULL)
|
|
|
|
(*sc->sc_power)(sc, why);
|
|
|
|
rtw_init(ifp);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PWR_SOFTSUSPEND:
|
|
|
|
case PWR_SOFTSTANDBY:
|
|
|
|
case PWR_SOFTRESUME:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* rtw_shutdown: make sure the interface is stopped at reboot time. */
|
|
|
|
void
|
|
|
|
rtw_shutdown(void *arg)
|
|
|
|
{
|
|
|
|
struct rtw_softc *sc = arg;
|
|
|
|
|
|
|
|
rtw_stop(&sc->sc_ic.ic_if, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_setifprops(struct ifnet *ifp, const char *dvname, void *softc)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2004-12-20 03:28:02 +03:00
|
|
|
(void)memcpy(ifp->if_xname, dvname, IFNAMSIZ);
|
2004-09-26 06:29:15 +04:00
|
|
|
ifp->if_softc = softc;
|
|
|
|
ifp->if_flags = IFF_SIMPLEX | IFF_BROADCAST | IFF_MULTICAST |
|
|
|
|
IFF_NOTRAILERS;
|
|
|
|
ifp->if_ioctl = rtw_ioctl;
|
|
|
|
ifp->if_start = rtw_start;
|
|
|
|
ifp->if_watchdog = rtw_watchdog;
|
|
|
|
ifp->if_init = rtw_init;
|
|
|
|
ifp->if_stop = rtw_stop;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
rtw_set80211props(struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
int nrate;
|
|
|
|
ic->ic_phytype = IEEE80211_T_DS;
|
|
|
|
ic->ic_opmode = IEEE80211_M_STA;
|
|
|
|
ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS |
|
|
|
|
IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP;
|
|
|
|
|
|
|
|
nrate = 0;
|
2004-12-23 08:47:42 +03:00
|
|
|
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[nrate++] =
|
|
|
|
IEEE80211_RATE_BASIC | 2;
|
|
|
|
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[nrate++] =
|
|
|
|
IEEE80211_RATE_BASIC | 4;
|
2004-09-26 06:29:15 +04:00
|
|
|
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[nrate++] = 11;
|
|
|
|
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_rates[nrate++] = 22;
|
|
|
|
ic->ic_sup_rates[IEEE80211_MODE_11B].rs_nrates = nrate;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
rtw_set80211methods(struct rtw_mtbl *mtbl, struct ieee80211com *ic)
|
|
|
|
{
|
|
|
|
mtbl->mt_newstate = ic->ic_newstate;
|
|
|
|
ic->ic_newstate = rtw_newstate;
|
|
|
|
|
|
|
|
mtbl->mt_recv_mgmt = ic->ic_recv_mgmt;
|
|
|
|
ic->ic_recv_mgmt = rtw_recv_mgmt;
|
|
|
|
|
|
|
|
mtbl->mt_node_free = ic->ic_node_free;
|
|
|
|
ic->ic_node_free = rtw_node_free;
|
|
|
|
|
|
|
|
mtbl->mt_node_alloc = ic->ic_node_alloc;
|
|
|
|
ic->ic_node_alloc = rtw_node_alloc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_establish_hooks(struct rtw_hooks *hooks, const char *dvname,
|
2004-09-26 06:29:15 +04:00
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Make sure the interface is shutdown during reboot.
|
|
|
|
*/
|
|
|
|
hooks->rh_shutdown = shutdownhook_establish(rtw_shutdown, arg);
|
|
|
|
if (hooks->rh_shutdown == NULL)
|
|
|
|
printf("%s: WARNING: unable to establish shutdown hook\n",
|
2004-12-20 03:28:02 +03:00
|
|
|
dvname);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add a suspend hook to make sure we come back up after a
|
|
|
|
* resume.
|
|
|
|
*/
|
|
|
|
hooks->rh_power = powerhook_establish(rtw_power, arg);
|
|
|
|
if (hooks->rh_power == NULL)
|
|
|
|
printf("%s: WARNING: unable to establish power hook\n",
|
2004-12-20 03:28:02 +03:00
|
|
|
dvname);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_disestablish_hooks(struct rtw_hooks *hooks, const char *dvname,
|
2004-09-26 06:29:15 +04:00
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
if (hooks->rh_shutdown != NULL)
|
|
|
|
shutdownhook_disestablish(hooks->rh_shutdown);
|
|
|
|
|
|
|
|
if (hooks->rh_power != NULL)
|
|
|
|
powerhook_disestablish(hooks->rh_power);
|
|
|
|
}
|
|
|
|
|
|
|
|
static __inline void
|
|
|
|
rtw_init_radiotap(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
memset(&sc->sc_rxtapu, 0, sizeof(sc->sc_rxtapu));
|
2004-12-29 01:30:07 +03:00
|
|
|
sc->sc_rxtap.rr_ihdr.it_len = htole16(sizeof(sc->sc_rxtapu));
|
|
|
|
sc->sc_rxtap.rr_ihdr.it_present = htole32(RTW_RX_RADIOTAP_PRESENT);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
memset(&sc->sc_txtapu, 0, sizeof(sc->sc_txtapu));
|
2004-12-29 01:30:07 +03:00
|
|
|
sc->sc_txtap.rt_ihdr.it_len = htole16(sizeof(sc->sc_txtapu));
|
|
|
|
sc->sc_txtap.rt_ihdr.it_present = htole32(RTW_TX_RADIOTAP_PRESENT);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_setup(struct rtw_txsoft_blk *tsb, u_int qlen)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
SIMPLEQ_INIT(&tsb->tsb_dirtyq);
|
|
|
|
SIMPLEQ_INIT(&tsb->tsb_freeq);
|
|
|
|
tsb->tsb_ndesc = qlen;
|
|
|
|
tsb->tsb_desc = malloc(qlen * sizeof(*tsb->tsb_desc), M_DEVBUF,
|
2004-09-26 06:29:15 +04:00
|
|
|
M_NOWAIT);
|
2004-12-29 04:06:52 +03:00
|
|
|
if (tsb->tsb_desc == NULL)
|
2004-09-26 06:29:15 +04:00
|
|
|
return ENOMEM;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_cleanup_all(struct rtw_softc *sc)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int pri;
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft_blk *tsb;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
tsb = &sc->sc_txsoft_blk[pri];
|
|
|
|
free(tsb->tsb_desc, M_DEVBUF);
|
|
|
|
tsb->tsb_desc = NULL;
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_setup_all(struct rtw_softc *sc)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
int pri, rc = 0;
|
|
|
|
int qlen[RTW_NTXPRI] =
|
|
|
|
{RTW_TXQLENLO, RTW_TXQLENMD, RTW_TXQLENHI, RTW_TXQLENBCN};
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
struct rtw_txsoft_blk *tsbs;
|
|
|
|
|
|
|
|
tsbs = sc->sc_txsoft_blk;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rc = rtw_txsoft_blk_setup(&tsbs[pri], qlen[pri]);
|
2004-09-26 06:29:15 +04:00
|
|
|
if (rc != 0)
|
|
|
|
break;
|
|
|
|
}
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
tsbs[RTW_TXPRILO].tsb_poll = RTW_TPPOLL_LPQ | RTW_TPPOLL_SLPQ;
|
|
|
|
tsbs[RTW_TXPRIMD].tsb_poll = RTW_TPPOLL_NPQ | RTW_TPPOLL_SNPQ;
|
|
|
|
tsbs[RTW_TXPRIHI].tsb_poll = RTW_TPPOLL_HPQ | RTW_TPPOLL_SHPQ;
|
|
|
|
tsbs[RTW_TXPRIBCN].tsb_poll = RTW_TPPOLL_BQ | RTW_TPPOLL_SBQ;
|
2004-09-26 06:29:15 +04:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdesc_blk_setup(struct rtw_txdesc_blk *tdb, struct rtw_txdesc *desc,
|
2004-09-26 06:29:15 +04:00
|
|
|
u_int ndesc, bus_addr_t ofs, bus_addr_t physbase)
|
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
tdb->tdb_ndesc = ndesc;
|
|
|
|
tdb->tdb_desc = desc;
|
|
|
|
tdb->tdb_physbase = physbase;
|
|
|
|
tdb->tdb_ofs = ofs;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
(void)memset(tdb->tdb_desc, 0,
|
|
|
|
sizeof(tdb->tdb_desc[0]) * tdb->tdb_ndesc);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txdesc_blk_reset(tdb);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
rtw_txdesc_blk_setup_all(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRILO],
|
|
|
|
&sc->sc_descs->hd_txlo[0], RTW_NTXDESCLO,
|
|
|
|
RTW_RING_OFFSET(hd_txlo), RTW_RING_BASE(sc, hd_txlo));
|
|
|
|
|
|
|
|
rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIMD],
|
|
|
|
&sc->sc_descs->hd_txmd[0], RTW_NTXDESCMD,
|
|
|
|
RTW_RING_OFFSET(hd_txmd), RTW_RING_BASE(sc, hd_txmd));
|
|
|
|
|
|
|
|
rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIHI],
|
|
|
|
&sc->sc_descs->hd_txhi[0], RTW_NTXDESCHI,
|
|
|
|
RTW_RING_OFFSET(hd_txhi), RTW_RING_BASE(sc, hd_txhi));
|
|
|
|
|
|
|
|
rtw_txdesc_blk_setup(&sc->sc_txdesc_blk[RTW_TXPRIBCN],
|
|
|
|
&sc->sc_descs->hd_bcn[0], RTW_NTXDESCBCN,
|
|
|
|
RTW_RING_OFFSET(hd_bcn), RTW_RING_BASE(sc, hd_bcn));
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct rtw_rf *
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_rf_attach(struct rtw_softc *sc, enum rtw_rfchipid rfchipid, int digphy)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
rtw_rf_write_t rf_write;
|
2004-09-26 06:29:15 +04:00
|
|
|
struct rtw_rf *rf;
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
switch (rfchipid) {
|
|
|
|
default:
|
|
|
|
rf_write = rtw_rf_hostwrite;
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_INTERSIL:
|
|
|
|
case RTW_RFCHIPID_PHILIPS:
|
|
|
|
case RTW_RFCHIPID_GCT: /* XXX a guess */
|
|
|
|
case RTW_RFCHIPID_RFMD:
|
|
|
|
rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
switch (rfchipid) {
|
|
|
|
case RTW_RFCHIPID_MAXIM:
|
|
|
|
rf = rtw_max2820_create(&sc->sc_regs, rf_write, 0);
|
|
|
|
sc->sc_pwrstate_cb = rtw_maxim_pwrstate;
|
|
|
|
break;
|
|
|
|
case RTW_RFCHIPID_PHILIPS:
|
|
|
|
rf = rtw_sa2400_create(&sc->sc_regs, rf_write, digphy);
|
|
|
|
sc->sc_pwrstate_cb = rtw_philips_pwrstate;
|
|
|
|
break;
|
2004-12-21 02:05:41 +03:00
|
|
|
case RTW_RFCHIPID_RFMD:
|
|
|
|
/* XXX RFMD has no RF constructor */
|
|
|
|
sc->sc_pwrstate_cb = rtw_rfmd_pwrstate;
|
|
|
|
/*FALLTHROUGH*/
|
2004-09-26 06:29:15 +04:00
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
rf->rf_continuous_tx_cb =
|
|
|
|
(rtw_continuous_tx_cb_t)rtw_continuous_tx_enable;
|
|
|
|
rf->rf_continuous_tx_arg = (void *)sc;
|
|
|
|
return rf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Revision C and later use a different PHY delay setting than
|
|
|
|
* revisions A and B.
|
|
|
|
*/
|
2005-01-02 07:23:03 +03:00
|
|
|
static uint8_t
|
2005-06-10 06:35:34 +04:00
|
|
|
rtw_check_phydelay(struct rtw_regs *regs, uint32_t old_rcr)
|
2004-09-26 06:29:15 +04:00
|
|
|
{
|
|
|
|
#define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV)
|
|
|
|
#define REVC (REVAB | RTW_RCR_RXFTH_WHOLE)
|
|
|
|
|
2005-01-02 07:23:03 +03:00
|
|
|
uint8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
RTW_WRITE(regs, RTW_RCR, REVAB);
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_WBW(regs, RTW_RCR, RTW_RCR);
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_WRITE(regs, RTW_RCR, REVC);
|
|
|
|
|
|
|
|
RTW_WBR(regs, RTW_RCR, RTW_RCR);
|
|
|
|
if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC)
|
|
|
|
phydelay |= RTW_PHYDELAY_REVC_MAGIC;
|
|
|
|
|
2005-06-10 06:35:34 +04:00
|
|
|
RTW_WRITE(regs, RTW_RCR, old_rcr); /* restore RCR */
|
2004-12-20 04:13:45 +03:00
|
|
|
RTW_SYNC(regs, RTW_RCR, RTW_RCR);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
return phydelay;
|
|
|
|
#undef REVC
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
rtw_attach(struct rtw_softc *sc)
|
|
|
|
{
|
2004-12-29 04:06:52 +03:00
|
|
|
struct rtw_txsoft_blk *tsb;
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
int pri, rc;
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, DETACHED);
|
|
|
|
|
|
|
|
switch (RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK) {
|
|
|
|
case RTW_TCR_HWVERID_F:
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
sc->sc_hwverid = 'F';
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
case RTW_TCR_HWVERID_D:
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
sc->sc_hwverid = 'D';
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
default:
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
sc->sc_hwverid = '?';
|
2004-09-26 06:29:15 +04:00
|
|
|
break;
|
|
|
|
}
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
printf("%s: hardware version %c\n", sc->sc_dev.dv_xname,
|
|
|
|
sc->sc_hwverid);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
rc = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct rtw_descs),
|
|
|
|
RTW_DESC_ALIGNMENT, 0, &sc->sc_desc_segs, 1, &sc->sc_desc_nsegs,
|
|
|
|
0);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
printf("%s: could not allocate hw descriptors, error %d\n",
|
|
|
|
sc->sc_dev.dv_xname, rc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_DESC_ALLOC);
|
|
|
|
|
|
|
|
rc = bus_dmamem_map(sc->sc_dmat, &sc->sc_desc_segs,
|
|
|
|
sc->sc_desc_nsegs, sizeof(struct rtw_descs),
|
|
|
|
(caddr_t*)&sc->sc_descs, BUS_DMA_COHERENT);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
printf("%s: could not map hw descriptors, error %d\n",
|
|
|
|
sc->sc_dev.dv_xname, rc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_DESC_MAP);
|
|
|
|
|
|
|
|
rc = bus_dmamap_create(sc->sc_dmat, sizeof(struct rtw_descs), 1,
|
|
|
|
sizeof(struct rtw_descs), 0, 0, &sc->sc_desc_dmamap);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
printf("%s: could not create DMA map for hw descriptors, "
|
|
|
|
"error %d\n", sc->sc_dev.dv_xname, rc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_DESCMAP_CREATE);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
sc->sc_rxdesc_blk.rdb_dmat = sc->sc_dmat;
|
|
|
|
sc->sc_rxdesc_blk.rdb_dmamap = sc->sc_desc_dmamap;
|
2004-12-29 03:21:37 +03:00
|
|
|
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
sc->sc_txdesc_blk[pri].tdb_dmat = sc->sc_dmat;
|
|
|
|
sc->sc_txdesc_blk[pri].tdb_dmamap = sc->sc_desc_dmamap;
|
2004-12-29 03:21:37 +03:00
|
|
|
}
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
rc = bus_dmamap_load(sc->sc_dmat, sc->sc_desc_dmamap, sc->sc_descs,
|
|
|
|
sizeof(struct rtw_descs), NULL, 0);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
printf("%s: could not load DMA map for hw descriptors, "
|
|
|
|
"error %d\n", sc->sc_dev.dv_xname, rc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_DESCMAP_LOAD);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
if (rtw_txsoft_blk_setup_all(sc) != 0)
|
2004-09-26 06:29:15 +04:00
|
|
|
goto err;
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_TXCTLBLK_SETUP);
|
|
|
|
|
|
|
|
rtw_txdesc_blk_setup_all(sc);
|
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_TXDESCBLK_SETUP);
|
|
|
|
|
2004-12-29 04:06:52 +03:00
|
|
|
sc->sc_rxdesc_blk.rdb_desc = &sc->sc_descs->hd_rx[0];
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
2004-12-29 04:06:52 +03:00
|
|
|
tsb = &sc->sc_txsoft_blk[pri];
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
if ((rc = rtw_txdesc_dmamaps_create(sc->sc_dmat,
|
2004-12-29 04:06:52 +03:00
|
|
|
&tsb->tsb_desc[0], tsb->tsb_ndesc)) != 0) {
|
2004-09-26 06:29:15 +04:00
|
|
|
printf("%s: could not load DMA map for "
|
|
|
|
"hw tx descriptors, error %d\n",
|
|
|
|
sc->sc_dev.dv_xname, rc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_TXMAPS_CREATE);
|
2004-12-29 04:06:52 +03:00
|
|
|
if ((rc = rtw_rxdesc_dmamaps_create(sc->sc_dmat, &sc->sc_rxsoft[0],
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_RXQLEN)) != 0) {
|
|
|
|
printf("%s: could not load DMA map for hw rx descriptors, "
|
|
|
|
"error %d\n", sc->sc_dev.dv_xname, rc);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_RXMAPS_CREATE);
|
|
|
|
|
|
|
|
/* Reset the chip to a known state. */
|
|
|
|
if (rtw_reset(sc) != 0)
|
|
|
|
goto err;
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_RESET);
|
|
|
|
|
|
|
|
sc->sc_rcr = RTW_READ(&sc->sc_regs, RTW_RCR);
|
|
|
|
|
|
|
|
if ((sc->sc_rcr & RTW_RCR_9356SEL) != 0)
|
|
|
|
sc->sc_flags |= RTW_F_9356SROM;
|
|
|
|
|
|
|
|
if (rtw_srom_read(&sc->sc_regs, sc->sc_flags, &sc->sc_srom,
|
2004-12-20 03:28:02 +03:00
|
|
|
sc->sc_dev.dv_xname) != 0)
|
2004-09-26 06:29:15 +04:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_READ_SROM);
|
|
|
|
|
|
|
|
if (rtw_srom_parse(&sc->sc_srom, &sc->sc_flags, &sc->sc_csthr,
|
|
|
|
&sc->sc_rfchipid, &sc->sc_rcr, &sc->sc_locale,
|
2004-12-20 03:28:02 +03:00
|
|
|
sc->sc_dev.dv_xname) != 0) {
|
2004-09-26 06:29:15 +04:00
|
|
|
printf("%s: attach failed, malformed serial ROM\n",
|
|
|
|
sc->sc_dev.dv_xname);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
2004-12-21 02:05:41 +03:00
|
|
|
printf("%s: %s PHY\n", sc->sc_dev.dv_xname,
|
|
|
|
((sc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog");
|
|
|
|
|
|
|
|
printf("%s: CS threshold %u\n", sc->sc_dev.dv_xname, sc->sc_csthr);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_PARSE_SROM);
|
|
|
|
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
sc->sc_rf = rtw_rf_attach(sc, sc->sc_rfchipid,
|
2004-09-26 06:29:15 +04:00
|
|
|
sc->sc_flags & RTW_F_DIGPHY);
|
|
|
|
|
|
|
|
if (sc->sc_rf == NULL) {
|
|
|
|
printf("%s: attach failed, could not attach RF\n",
|
|
|
|
sc->sc_dev.dv_xname);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_RF_ATTACH);
|
|
|
|
|
|
|
|
sc->sc_phydelay = rtw_check_phydelay(&sc->sc_regs, sc->sc_rcr);
|
|
|
|
|
2004-12-25 09:58:37 +03:00
|
|
|
RTW_DPRINTF(RTW_DEBUG_ATTACH,
|
|
|
|
("%s: PHY delay %d\n", sc->sc_dev.dv_xname, sc->sc_phydelay));
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
if (sc->sc_locale == RTW_LOCALE_UNKNOWN)
|
|
|
|
rtw_identify_country(&sc->sc_regs, &sc->sc_locale,
|
2004-12-20 03:28:02 +03:00
|
|
|
sc->sc_dev.dv_xname);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
rtw_init_channels(sc->sc_locale, &sc->sc_ic.ic_channels,
|
2004-12-20 03:28:02 +03:00
|
|
|
sc->sc_dev.dv_xname);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
if (rtw_identify_sta(&sc->sc_regs, &sc->sc_ic.ic_myaddr,
|
2004-12-20 03:28:02 +03:00
|
|
|
sc->sc_dev.dv_xname) != 0)
|
2004-09-26 06:29:15 +04:00
|
|
|
goto err;
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISH_ID_STA);
|
|
|
|
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_setifprops(&sc->sc_if, sc->sc_dev.dv_xname, (void*)sc);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
IFQ_SET_READY(&sc->sc_if.if_snd);
|
|
|
|
|
|
|
|
rtw_set80211props(&sc->sc_ic);
|
|
|
|
|
2005-03-02 08:20:43 +03:00
|
|
|
rtw_led_attach(&sc->sc_led_state, (void *)sc);
|
Move the register access mode into struct rtw_regs. Change
rtw_set_access, rtw_set_access1 to match.
Add a subroutine for setting WEP keys. WEP isn't quite finished,
because I have to add the WEP header to Tx packets. Implement the
SIOCS80211NWKEY ioctl for setting WEP keys.
Program the LEDs based on operating state and packet activity.
* On a Revision F RTL8180, blink LED1 at 1Hz to indicate
scan/authenticate/associate states. In the run state, turn LED1
on. In every state, blink LED1 at 5Hz to indicate non-beacon
tx/rx activity. I would like to use two LEDs, but in all my
Rev. F instances, LED0 is not wired to an LED; instead, the
first LED is wired to indicate that the card's power is on.
* On a Revision D RTL8180, program the LEDs so that LED0 indicates
Tx, and LED1 indicates Rx. The Rx LED will blink annoyingly if
there are beacons in the air, but at least the Tx LED is useful.
* Store the hardware revision in the softc to support my futile
attempt at programming LEDs for both Rev. D and Rev. F parts;
I never did get Rev. D LEDs to work right.
* Add a debug flag RTW_DEBUG_LED for the LED transitions.
Add RTW_TPPOLL_ALL, RTW_TPPOLL_SALL to start and stop, respectively,
all of the transmit rings.
In ad hoc mode, allocate a beacon and load it into the beacon ring.
Start the ring. In one trial, the card re-transmitted the beacon
ring's contents several times before stopping. More programming
and testing for ad hoc mode is necessary. I'm not setting the
beacon flag in the transmit descriptor.
Revamp the transmit section to make better use of all the transmit
rings: beacon queue, high-, low-, and medium-priority rings. Put
beacon frames on the beacon ring. All other management frames,
and data frames, go on the medium-priority ring. Power-save data
frames go on the high-priority ring. (Note that powersaving is
not implemented!) This is a work in progress.
Send all 802.11 Management frames at 1Mbps.
After we put a packet on a transmit ring, tickle the right bit in
the TPPOLL to tell RTL8180. Stop all rings on error and in rtw_stop.
Use the RF chip type, not the RTL8180 revision, to choose between
host- and MAC-controlled RF serial I/O. Now the Netgear MA521
works.
Remove bogus definition of bit RTW_TPPOLL_FSWINT.
2005-01-16 14:50:43 +03:00
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
/*
|
|
|
|
* Call MI attach routines.
|
|
|
|
*/
|
|
|
|
if_attach(&sc->sc_if);
|
|
|
|
ieee80211_ifattach(&sc->sc_if);
|
|
|
|
|
|
|
|
rtw_set80211methods(&sc->sc_mtbl, &sc->sc_ic);
|
|
|
|
|
|
|
|
/* possibly we should fill in our own sc_send_prresp, since
|
|
|
|
* the RTL8180 is probably sending probe responses in ad hoc
|
|
|
|
* mode.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* complete initialization */
|
|
|
|
ieee80211_media_init(&sc->sc_if, rtw_media_change, rtw_media_status);
|
|
|
|
callout_init(&sc->sc_scan_ch);
|
|
|
|
|
2004-12-29 01:30:07 +03:00
|
|
|
rtw_init_radiotap(sc);
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
#if NBPFILTER > 0
|
|
|
|
bpfattach2(&sc->sc_if, DLT_IEEE802_11_RADIO,
|
|
|
|
sizeof(struct ieee80211_frame) + 64, &sc->sc_radiobpf);
|
|
|
|
#endif
|
|
|
|
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_establish_hooks(&sc->sc_hooks, sc->sc_dev.dv_xname, (void*)sc);
|
2004-09-26 06:29:15 +04:00
|
|
|
|
|
|
|
NEXT_ATTACH_STATE(sc, FINISHED);
|
|
|
|
|
|
|
|
return;
|
|
|
|
err:
|
|
|
|
rtw_detach(sc);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rtw_detach(struct rtw_softc *sc)
|
|
|
|
{
|
|
|
|
int pri;
|
|
|
|
|
2004-12-29 22:41:04 +03:00
|
|
|
sc->sc_flags |= RTW_F_INVALID;
|
|
|
|
|
2004-09-26 06:29:15 +04:00
|
|
|
switch (sc->sc_attach_state) {
|
|
|
|
case FINISHED:
|
Miscellaneous changes. Details below. Important changes flagged
with []. Using the driver with my Linksys WPC11 ver. 4, it seems
to be receiving packets for a change. The WPC11 ver. 4 has a Maxim
RF section. My no-name rtw with Philips RF section still does not
receive any packets.
Keep access-level (analog params > config[0123] registers > none)
in sc_access. Add rtw_set_access for changing the access level.
Make rtw_continuous_tx_enable and other subroutines use rtw_set_access
instead of rtw_config0123_enable and rtw_anaparm_enable.
Factor part of the chip-reset code into rtw_chip_reset1.
Change the 'struct foo (*bar)[N]'-style arguments to
'struct foo *bar'-style arguments.
Consolidate software/hardware Tx/Rx ring setup in rtw_hwring_setup,
rtw_swring_setup.
Add a new constant, SA2400_OPMODE_DEFAULTS, for the bits that we
*always* set in the SA2400 OPMODE register.
Factor some code out into rtw_sa2400_calibrate. (Inspired by the
Linux driver.)
[] When the receiver goes into underrun/overflow state, call a new
subroutine, rtw_kick() that stops the Rx/Tx processes, resets
the chip, reinitializes the Tx/Rx rings, and restarts Rx/Tx
processes. (Inspired by the Linux driver.)
[] In rtw_intr_rx, check for too-short packets before calling
ieee80211_find_rxnode. I believe this will prevent a repeat of
the MCHK exception I saw once on macppc.
[] Use seconds-elapased as well as microseconds-elapsed to set the
next "due date" for the timeout interrupt. This keeps the driver
from programming the timeout to expire too early.
[] In rtw_intr, read RTW_ISR at most 10 times, then get out. If
the interface is not enabled (RTW_F_ENABLED), then get out.
[] In rtw_stop, get out if the interface is not enabled (RTW_F_ENABLED).
Block IPL_NET interrupts. Don't read/write any registers if
the interface is invalid (RTW_F_INVALID).
[] Call rtw_stop in rtw_detach.
2004-12-12 09:37:59 +03:00
|
|
|
rtw_stop(&sc->sc_if, 1);
|
|
|
|
|
2004-12-20 03:28:02 +03:00
|
|
|
rtw_disestablish_hooks(&sc->sc_hooks, sc->sc_dev.dv_xname,
|
2004-09-26 06:29:15 +04:00
|
|
|
(void*)sc);
|
|
|
|
callout_stop(&sc->sc_scan_ch);
|
|
|
|
ieee80211_ifdetach(&sc->sc_if);
|
|
|
|
if_detach(&sc->sc_if);
|
|
|
|
break;
|
|
|
|
case FINISH_ID_STA:
|
|
|
|
case FINISH_RF_ATTACH:
|
|
|
|
rtw_rf_destroy(sc->sc_rf);
|
|
|
|
sc->sc_rf = NULL;
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_PARSE_SROM:
|
|
|
|
case FINISH_READ_SROM:
|
|
|
|
rtw_srom_free(&sc->sc_srom);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_RESET:
|
|
|
|
case FINISH_RXMAPS_CREATE:
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_rxdesc_dmamaps_destroy(sc->sc_dmat, &sc->sc_rxsoft[0],
|
2004-09-26 06:29:15 +04:00
|
|
|
RTW_RXQLEN);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_TXMAPS_CREATE:
|
|
|
|
for (pri = 0; pri < RTW_NTXPRI; pri++) {
|
|
|
|
rtw_txdesc_dmamaps_destroy(sc->sc_dmat,
|
2004-12-29 04:06:52 +03:00
|
|
|
sc->sc_txsoft_blk[pri].tsb_desc,
|
|
|
|
sc->sc_txsoft_blk[pri].tsb_ndesc);
|
2004-09-26 06:29:15 +04:00
|
|
|
}
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_TXDESCBLK_SETUP:
|
|
|
|
case FINISH_TXCTLBLK_SETUP:
|
2004-12-29 04:06:52 +03:00
|
|
|
rtw_txsoft_blk_cleanup_all(sc);
|
2004-09-26 06:29:15 +04:00
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_DESCMAP_LOAD:
|
|
|
|
bus_dmamap_unload(sc->sc_dmat, sc->sc_desc_dmamap);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_DESCMAP_CREATE:
|
|
|
|
bus_dmamap_destroy(sc->sc_dmat, sc->sc_desc_dmamap);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_DESC_MAP:
|
|
|
|
bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_descs,
|
|
|
|
sizeof(struct rtw_descs));
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case FINISH_DESC_ALLOC:
|
|
|
|
bus_dmamem_free(sc->sc_dmat, &sc->sc_desc_segs,
|
|
|
|
sc->sc_desc_nsegs);
|
|
|
|
/*FALLTHROUGH*/
|
|
|
|
case DETACHED:
|
|
|
|
NEXT_ATTACH_STATE(sc, DETACHED);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
rtw_activate(struct device *self, enum devact act)
|
|
|
|
{
|
|
|
|
struct rtw_softc *sc = (struct rtw_softc *)self;
|
|
|
|
int rc = 0, s;
|
|
|
|
|
|
|
|
s = splnet();
|
|
|
|
switch (act) {
|
|
|
|
case DVACT_ACTIVATE:
|
|
|
|
rc = EOPNOTSUPP;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DVACT_DEACTIVATE:
|
|
|
|
if_deactivate(&sc->sc_ic.ic_if);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
splx(s);
|
|
|
|
return rc;
|
|
|
|
}
|