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.
This commit is contained in:
dyoung 2004-12-12 06:37:59 +00:00
parent a2078b09d1
commit a534631ee7
4 changed files with 252 additions and 127 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtw.c,v 1.2 2004/10/30 18:08:38 thorpej Exp $ */
/* $NetBSD: rtw.c,v 1.3 2004/12/12 06:37:59 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.2 2004/10/30 18:08:38 thorpej Exp $");
__KERNEL_RCSID(0, "$NetBSD: rtw.c,v 1.3 2004/12/12 06:37:59 dyoung Exp $");
#include "bpfilter.h"
@ -201,8 +201,10 @@ rtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where)
#endif /* RTW_DEBUG */
void
rtw_continuous_tx_enable(struct rtw_regs *regs, int enable)
rtw_continuous_tx_enable(struct rtw_softc *sc, int enable)
{
struct rtw_regs *regs = &sc->sc_regs;
u_int32_t tcr;
tcr = RTW_READ(regs, RTW_TCR);
tcr &= ~RTW_TCR_LBK_MASK;
@ -212,17 +214,91 @@ rtw_continuous_tx_enable(struct rtw_regs *regs, int enable)
tcr |= RTW_TCR_LBK_NORMAL;
RTW_WRITE(regs, RTW_TCR, tcr);
RTW_SYNC(regs, RTW_TCR, RTW_TCR);
if (enable) {
rtw_config0123_enable(regs, 1);
rtw_anaparm_enable(regs, 1);
rtw_txdac_enable(regs, 0);
} else {
rtw_txdac_enable(regs, 1);
rtw_anaparm_enable(regs, 0);
rtw_config0123_enable(regs, 0);
rtw_set_access(sc, RTW_ACCESS_ANAPARM);
rtw_txdac_enable(regs, !enable);
#if 0
/* XXX voodoo. from linux. */
rtw_anaparm_enable(regs, 1);
rtw_anaparm_enable(regs, 0);
#endif
rtw_set_access(sc, RTW_ACCESS_NONE);
}
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";
}
}
static void
rtw_set_access1(struct rtw_regs *regs,
enum rtw_access oaccess, enum rtw_access naccess)
{
KASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM);
KASSERT(oaccess >= RTW_ACCESS_NONE && oaccess <= RTW_ACCESS_ANAPARM);
if (naccess == oaccess)
return;
switch (naccess) {
case RTW_ACCESS_NONE:
switch (oaccess) {
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:
switch (oaccess) {
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:
switch (oaccess) {
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;
}
}
void
rtw_set_access(struct rtw_softc *sc, enum rtw_access access)
{
rtw_set_access1(&sc->sc_regs, sc->sc_access, access);
RTW_DPRINTF(("%s: access %s -> %s\n", sc->sc_dev.dv_xname,
rtw_access_string(sc->sc_access),
rtw_access_string(access)));
sc->sc_access = access;
}
/*
* Enable registers, switch register banks.
*/
@ -247,8 +323,10 @@ rtw_anaparm_enable(struct rtw_regs *regs, int enable)
u_int8_t cfg3;
cfg3 = RTW_READ8(regs, RTW_CONFIG3);
cfg3 |= RTW_CONFIG3_PARMEN | RTW_CONFIG3_CLKRUNEN;
if (!enable)
cfg3 |= RTW_CONFIG3_CLKRUNEN;
if (enable)
cfg3 |= RTW_CONFIG3_PARMEN;
else
cfg3 &= ~RTW_CONFIG3_PARMEN;
RTW_WRITE8(regs, RTW_CONFIG3, cfg3);
RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3);
@ -270,19 +348,10 @@ rtw_txdac_enable(struct rtw_regs *regs, int enable)
}
static __inline int
rtw_chip_reset(struct rtw_regs *regs, char (*dvname)[IFNAMSIZ])
rtw_chip_reset1(struct rtw_regs *regs, char (*dvname)[IFNAMSIZ])
{
int i;
u_int8_t cr;
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);
int i;
RTW_WRITE8(regs, RTW_CR, RTW_CR_RST);
@ -301,6 +370,22 @@ rtw_chip_reset(struct rtw_regs *regs, char (*dvname)[IFNAMSIZ])
return ETIMEDOUT;
}
static __inline int
rtw_chip_reset(struct rtw_regs *regs, char (*dvname)[IFNAMSIZ])
{
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);
}
static __inline int
rtw_recall_eeprom(struct rtw_regs *regs, char (*dvname)[IFNAMSIZ])
{
@ -376,11 +461,11 @@ rtw_rxdesc_dmamaps_create(bus_dma_tag_t dmat, struct rtw_rxctl *descs,
}
static __inline void
rtw_rxctls_setup(struct rtw_rxctl (*descs)[RTW_RXQLEN])
rtw_rxctls_setup(struct rtw_rxctl *descs)
{
int i;
for (i = 0; i < RTW_RXQLEN; i++)
(*descs)[i].srx_mbuf = NULL;
descs[i].srx_mbuf = NULL;
}
static __inline void
@ -746,15 +831,15 @@ rtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic,
}
static void
rtw_txdesc_blk_init_all(struct rtw_txdesc_blk (*htcs)[RTW_NTXPRI])
rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *htcs)
{
int pri;
u_int ndesc[RTW_NTXPRI] =
{RTW_NTXDESCLO, RTW_NTXDESCMD, RTW_NTXDESCHI, RTW_NTXDESCBCN};
for (pri = 0; pri < RTW_NTXPRI; pri++) {
(*htcs)[pri].htc_nfree = ndesc[pri];
(*htcs)[pri].htc_next = 0;
htcs[pri].htc_nfree = ndesc[pri];
htcs[pri].htc_next = 0;
}
}
@ -775,12 +860,11 @@ rtw_txctl_blk_init(struct rtw_txctl_blk *stc)
}
static void
rtw_txctl_blk_init_all(struct rtw_txctl_blk (*stcs)[RTW_NTXPRI])
rtw_txctl_blk_init_all(struct rtw_txctl_blk *stcs)
{
int pri;
for (pri = 0; pri < RTW_NTXPRI; pri++) {
rtw_txctl_blk_init(&(*stcs)[pri]);
}
for (pri = 0; pri < RTW_NTXPRI; pri++)
rtw_txctl_blk_init(&stcs[pri]);
}
static __inline void
@ -824,12 +908,12 @@ rtw_txdescs_sync(bus_dma_tag_t dmat, bus_dmamap_t dmap,
static void
rtw_txdescs_sync_all(bus_dma_tag_t dmat, bus_dmamap_t dmap,
struct rtw_txdesc_blk (*htcs)[RTW_NTXPRI])
struct rtw_txdesc_blk *htcs)
{
int pri;
for (pri = 0; pri < RTW_NTXPRI; pri++) {
rtw_txdescs_sync(dmat, dmap,
&(*htcs)[pri], 0, (*htcs)[pri].htc_ndesc,
&htcs[pri], 0, htcs[pri].htc_ndesc,
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
}
}
@ -1088,6 +1172,10 @@ rtw_intr_rx(struct rtw_softc *sc, u_int16_t isr)
MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK);
m->m_flags |= M_HASFCS;
if (m->m_pkthdr.len < IEEE80211_MIN_LEN) {
sc->sc_ic.ic_stats.is_rx_tooshort++;
goto next;
}
wh = mtod(m, struct ieee80211_frame *);
/* TBD use _MAR, _BAR, _PAR flags as hints to _find_rxnode? */
ni = ieee80211_find_rxnode(&sc->sc_ic, wh);
@ -1101,6 +1189,7 @@ next:
hrx, srx, next);
}
sc->sc_rxnext = next;
return;
}
@ -1125,17 +1214,56 @@ rtw_intr_atim(struct rtw_softc *sc)
return;
}
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));
}
static void
rtw_swring_setup(struct rtw_softc *sc)
{
rtw_txdesc_blk_init_all(&sc->sc_txdesc_blk[0]);
rtw_txctl_blk_init_all(&sc->sc_txctl_blk[0]);
rtw_rxctl_init_all(sc->sc_dmat, sc->sc_rxctl, &sc->sc_rxnext,
&sc->sc_dev.dv_xname);
rtw_rxdesc_init_all(sc->sc_dmat, sc->sc_desc_dmamap,
sc->sc_rxdesc, sc->sc_rxctl);
rtw_txdescs_sync_all(sc->sc_dmat, sc->sc_desc_dmamap,
&sc->sc_txdesc_blk[0]);
#if 0 /* redundant with rtw_rxdesc_init_all */
rtw_rxdescs_sync(sc->sc_dmat, sc->sc_desc_dmamap,
0, RTW_NRXDESC, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
#endif
}
static void
rtw_kick(struct rtw_softc *sc)
{
struct rtw_regs *regs = &sc->sc_regs;
rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 0);
RTW_WRITE16(regs, RTW_IMR, 0);
rtw_rxbufs_release(sc->sc_dmat, &sc->sc_rxctl[0]);
/* TBD free tx bufs */
rtw_swring_setup(sc);
rtw_hwring_setup(sc);
RTW_WRITE16(regs, RTW_IMR, sc->sc_inten);
rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1);
}
static void
rtw_intr_ioerror(struct rtw_softc *sc, u_int16_t isr)
{
if ((isr & (RTW_INTR_RDU|RTW_INTR_RXFOVW)) != 0) {
#if 0
rtw_rxctl_init_all(sc->sc_dmat, sc->sc_rxctl, &sc->sc_rxnext,
&sc->sc_dev.dv_xname);
rtw_rxdesc_init_all(sc->sc_dmat, sc->sc_desc_dmamap,
sc->sc_rxdesc, sc->sc_rxctl);
#endif
rtw_io_enable(&sc->sc_regs, RTW_CR_RE, 1);
rtw_kick(sc);
}
if ((isr & RTW_INTR_TXFOVW) != 0)
; /* TBD restart transmit engine */
@ -1163,7 +1291,7 @@ rtw_resume_ticks(struct rtw_softc *sc)
splx(s);
tsftrl1 = RTW_READ(&sc->sc_regs, RTW_TSFTRL);
next_tick = tsftrl1 + 1000000 - tv.tv_usec;
next_tick = tsftrl1 + 1000000 * (1 + tv.tv_sec) - tv.tv_usec;
RTW_WRITE(&sc->sc_regs, RTW_TINT, next_tick);
sc->sc_do_tick = 1;
@ -1184,26 +1312,23 @@ rtw_intr_timeout(struct rtw_softc *sc)
int
rtw_intr(void *arg)
{
int i;
struct rtw_softc *sc = arg;
struct rtw_regs *regs = &sc->sc_regs;
u_int16_t isr;
#ifdef RTW_DEBUG
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
panic("%s: rtw_intr: not enabled", sc->sc_dev.dv_xname);
#endif /* RTW_DEBUG */
/*
* If the interface isn't running, the interrupt couldn't
* possibly have come from us.
*/
if ((sc->sc_if.if_flags & IFF_RUNNING) == 0 ||
if ((sc->sc_flags & RTW_F_ENABLED) == 0 ||
(sc->sc_if.if_flags & IFF_RUNNING) == 0 ||
(sc->sc_dev.dv_flags & DVF_ACTIVE) == 0) {
RTW_DPRINTF2(("%s: stray interrupt\n", sc->sc_dev.dv_xname));
return (0);
}
for (;;) {
for (i = 0; i < 10; i++) {
isr = RTW_READ16(regs, RTW_ISR);
RTW_WRITE16(regs, RTW_ISR, isr);
@ -1269,24 +1394,33 @@ rtw_intr(void *arg)
static void
rtw_stop(struct ifnet *ifp, int disable)
{
int s;
struct rtw_softc *sc = (struct rtw_softc *)ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
struct rtw_regs *regs = &sc->sc_regs;
if ((sc->sc_flags & RTW_F_ENABLED) == 0)
return;
rtw_suspend_ticks(sc);
s = splnet();
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
/* Disable interrupts. */
RTW_WRITE16(regs, RTW_IMR, 0);
if ((sc->sc_flags & RTW_F_INVALID) == 0) {
/* Disable interrupts. */
RTW_WRITE16(regs, RTW_IMR, 0);
/* Stop the transmit and receive processes. First stop DMA,
* then disable receiver and transmitter.
*/
RTW_WRITE8(regs, RTW_TPPOLL,
RTW_TPPOLL_SBQ|RTW_TPPOLL_SHPQ|RTW_TPPOLL_SNPQ|RTW_TPPOLL_SLPQ);
/* Stop the transmit and receive processes. First stop DMA,
* then disable receiver and transmitter.
*/
RTW_WRITE8(regs, RTW_TPPOLL,
RTW_TPPOLL_SBQ|RTW_TPPOLL_SHPQ|RTW_TPPOLL_SNPQ|
RTW_TPPOLL_SLPQ);
rtw_io_enable(&sc->sc_regs, RTW_CR_RE|RTW_CR_TE, 0);
rtw_io_enable(&sc->sc_regs, RTW_CR_RE|RTW_CR_TE, 0);
}
/* TBD Release transmit buffers. */
@ -1298,6 +1432,9 @@ rtw_stop(struct ifnet *ifp, int disable)
/* Mark the interface as not running. Cancel the watchdog timer. */
ifp->if_flags &= ~IFF_RUNNING;
ifp->if_timer = 0;
splx(s);
return;
}
@ -1402,13 +1539,11 @@ rtw_pwrstate0(struct rtw_softc *sc, enum rtw_pwrstate power, int before_rf)
{
struct rtw_regs *regs = &sc->sc_regs;
rtw_config0123_enable(regs, 1);
rtw_anaparm_enable(regs, 1);
rtw_set_access(sc, RTW_ACCESS_ANAPARM);
(*sc->sc_pwrstate_cb)(regs, power, before_rf);
rtw_anaparm_enable(regs, 0);
rtw_config0123_enable(regs, 0);
rtw_set_access(sc, RTW_ACCESS_NONE);
return;
}
@ -1677,35 +1812,18 @@ rtw_init(struct ifnet *ifp)
if ((rc = rtw_pwrstate(sc, RTW_OFF)) != 0)
goto out;
rtw_txdesc_blk_init_all(&sc->sc_txdesc_blk);
rtw_txctl_blk_init_all(&sc->sc_txctl_blk);
rtw_rxctl_init_all(sc->sc_dmat, sc->sc_rxctl, &sc->sc_rxnext,
&sc->sc_dev.dv_xname);
rtw_rxdesc_init_all(sc->sc_dmat, sc->sc_desc_dmamap,
sc->sc_rxdesc, sc->sc_rxctl);
rtw_txdescs_sync_all(sc->sc_dmat, sc->sc_desc_dmamap,
&sc->sc_txdesc_blk);
#if 0 /* redundant with rtw_rxdesc_init_all */
rtw_rxdescs_sync(sc->sc_dmat, sc->sc_desc_dmamap,
0, RTW_NRXDESC, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
#endif
RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(sc, hd_rx));
rtw_swring_setup(sc);
rtw_transmit_config(regs);
rtw_config0123_enable(regs, 1);
rtw_set_access(sc, RTW_ACCESS_CONFIG);
RTW_WRITE(regs, RTW_MSR, 0x0); /* no link */
RTW_WRITE(regs, RTW_BRSR, 0x0); /* long PLCP header, 1Mbps basic rate */
rtw_anaparm_enable(regs, 0);
rtw_config0123_enable(regs, 0);
rtw_set_access(sc, RTW_ACCESS_ANAPARM);
rtw_set_access(sc, RTW_ACCESS_NONE);
#if 0
RTW_WRITE(regs, RTW_FEMR, RTW_FEMR_GWAKE|RTW_FEMR_WKUP|RTW_FEMR_INTR);
@ -1721,10 +1839,7 @@ rtw_init(struct ifnet *ifp)
rtw_pktfilt_load(sc);
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));
rtw_hwring_setup(sc);
rtw_io_enable(regs, RTW_CR_RE|RTW_CR_TE, 1);
@ -2421,7 +2536,7 @@ rtw_attach(struct rtw_softc *sc)
sc->sc_rxdesc = &sc->sc_descs->hd_rx[0];
rtw_rxctls_setup(&sc->sc_rxctl);
rtw_rxctls_setup(&sc->sc_rxctl[0]);
for (pri = 0; pri < RTW_NTXPRI; pri++) {
stc = &sc->sc_txctl_blk[pri];
@ -2557,6 +2672,8 @@ rtw_detach(struct rtw_softc *sc)
switch (sc->sc_attach_state) {
case FINISHED:
rtw_stop(&sc->sc_if, 1);
rtw_disestablish_hooks(&sc->sc_hooks, &sc->sc_dev.dv_xname,
(void*)sc);
callout_stop(&sc->sc_scan_ch);

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtwphy.c,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/* $NetBSD: rtwphy.c,v 1.2 2004/12/12 06:37:59 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: rtwphy.c,v 1.1 2004/09/26 02:29:15 dyoung Exp $");
__KERNEL_RCSID(0, "$NetBSD: rtwphy.c,v 1.2 2004/12/12 06:37:59 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -218,11 +218,7 @@ rtw_sa2400_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
struct rtw_rfbus *bus = &sa->sa_bus;
u_int32_t opmode;
opmode = SA2400_OPMODE_XO;
opmode |= SA2400_OPMODE_RXLV;
opmode |= SA2400_OPMODE_CLK;
opmode |= SA2400_OPMODE_I0P3;
opmode |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
opmode = SA2400_OPMODE_DEFAULTS;
switch (power) {
case RTW_ON:
opmode |= SA2400_OPMODE_MODE_TXRX;
@ -263,11 +259,7 @@ rtw_sa2400_vcocal_start(struct rtw_sa2400 *sa, int start)
{
u_int32_t opmode;
opmode = SA2400_OPMODE_XO;
opmode |= SA2400_OPMODE_RXLV;
opmode |= SA2400_OPMODE_CLK;
opmode |= SA2400_OPMODE_I0P3;
opmode |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
opmode = SA2400_OPMODE_DEFAULTS;
if (start)
opmode |= SA2400_OPMODE_MODE_VCOCALIB;
else
@ -297,12 +289,7 @@ rtw_sa2400_filter_calibration(struct rtw_sa2400 *sa)
{
u_int32_t opmode;
opmode = SA2400_OPMODE_XO;
opmode |= SA2400_OPMODE_RXLV;
opmode |= SA2400_OPMODE_CLK;
opmode |= SA2400_OPMODE_I0P3;
opmode |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
opmode |= SA2400_OPMODE_MODE_FCALIB;
opmode = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_FCALIB;
if (sa->sa_digphy)
opmode |= SA2400_OPMODE_DIGIN;
@ -319,12 +306,7 @@ rtw_sa2400_dc_calibration(struct rtw_sa2400 *sa)
(*rf->rf_continuous_tx_cb)(rf->rf_continuous_tx_arg, 1);
dccal = SA2400_OPMODE_XO;
dccal |= SA2400_OPMODE_RXLV;
dccal |= SA2400_OPMODE_CLK;
dccal |= SA2400_OPMODE_I0P3;
dccal |= LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK);
dccal |= SA2400_OPMODE_MODE_TXRX;
dccal = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_TXRX;
rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
dccal);
@ -372,6 +354,28 @@ rtw_sa2400_destroy(struct rtw_rf *rf)
free(sa, M_DEVBUF);
}
static int
rtw_sa2400_calibrate(struct rtw_rf *rf, u_int freq)
{
struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
int i, rc;
/* XXX reference driver calibrates VCO twice. Is it a bug? */
for (i = 0; i < 2; i++) {
if ((rc = rtw_sa2400_vco_calibration(sa)) != 0)
return rc;
}
/* VCO calibration erases synthesizer registers, so re-tune */
if ((rc = rtw_sa2400_tune(rf, freq)) != 0)
return rc;
if ((rc = rtw_sa2400_filter_calibration(sa)) != 0)
return rc;
/* analog PHY needs DC calibration */
if (!sa->sa_digphy)
return rtw_sa2400_dc_calibration(sa);
return 0;
}
static int
rtw_sa2400_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
enum rtw_pwrstate power)
@ -390,22 +394,15 @@ rtw_sa2400_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
if ((rc = rtw_sa2400_pwrstate(rf, RTW_SLEEP)) != 0)
return rc;
if ((rc = rtw_sa2400_tune(rf, freq)) != 0)
return rc;
if ((rc = rtw_sa2400_agc_init(sa)) != 0)
return rc;
if ((rc = rtw_sa2400_manrx_init(sa)) != 0)
return rc;
if ((rc = rtw_sa2400_calibrate(rf, freq)) != 0)
return rc;
/* XXX reference driver calibrates VCO twice. Is it a bug? */
if ((rc = rtw_sa2400_vco_calibration(sa)) != 0)
return rc;
/* VCO calibration erases synthesizer registers */
if ((rc = rtw_sa2400_tune(rf, freq)) != 0)
return rc;
if ((rc = rtw_sa2400_filter_calibration(sa)) != 0)
return rc;
/* analog PHY needs DC calibration */
if (!sa->sa_digphy && (rc = rtw_sa2400_dc_calibration(sa)) != 0)
return rc;
/* enter Tx/Rx mode */
return rtw_sa2400_pwrstate(rf, power);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: rtwvar.h,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/* $NetBSD: rtwvar.h,v 1.2 2004/12/12 06:37:59 dyoung Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
@ -84,7 +84,8 @@ enum rtw_rfchipid {
#define RTW_F_DFLANTB 0x00000004 /* B antenna is default */
#define RTW_F_ANTDIV 0x00000010 /* h/w antenna diversity */
#define RTW_F_9356SROM 0x00000020 /* 93c56 SROM */
#define RTW_F_SLEEP 0x00000040 /* chip is enabled */
#define RTW_F_SLEEP 0x00000040 /* chip is asleep */
#define RTW_F_INVALID 0x00000080 /* chip is absent */
/* all PHY flags */
#define RTW_F_ALLPHY (RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV)
@ -341,6 +342,10 @@ struct rtw_sa2400 {
typedef void (*rtw_pwrstate_t)(struct rtw_regs *, enum rtw_pwrstate, int);
enum rtw_access {RTW_ACCESS_NONE = 0,
RTW_ACCESS_CONFIG = 1,
RTW_ACCESS_ANAPARM = 2};
struct rtw_softc {
struct device sc_dev;
struct ieee80211com sc_ic;
@ -414,6 +419,7 @@ struct rtw_softc {
struct rtw_tx_radiotap_header tap;
u_int8_t pad[64];
} sc_txtapu;
enum rtw_access sc_access;
};
#define sc_if sc_ic.ic_if
@ -423,7 +429,8 @@ struct rtw_softc {
void rtw_txdac_enable(struct rtw_regs *, int);
void rtw_anaparm_enable(struct rtw_regs *, int);
void rtw_config0123_enable(struct rtw_regs *, int);
void rtw_continuous_tx_enable(struct rtw_regs *, int);
void rtw_continuous_tx_enable(struct rtw_softc *, int);
void rtw_set_access(struct rtw_softc *, enum rtw_access);
void rtw_attach(struct rtw_softc *);
int rtw_detach(struct rtw_softc *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: sa2400reg.h,v 1.1 2004/09/26 02:29:15 dyoung Exp $ */
/* $NetBSD: sa2400reg.h,v 1.2 2004/12/12 06:37:59 dyoung Exp $ */
/*
* Copyright (c) 2005 David Young. All rights reserved.
@ -149,6 +149,10 @@
#define SA2400_OPMODE_MODE_RESET LSHIFT(7, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_MODE_VCOCALIB LSHIFT(8, SA2400_OPMODE_MODE_MASK)
#define SA2400_OPMODE_DEFAULTS \
(SA2400_OPMODE_XO | SA2400_OPMODE_RXLV | SA2400_OPMODE_CLK | \
SA2400_OPMODE_I0P3 | LSHIFT(3, SA2400_OPMODE_FILTTUNE_MASK))
#define SA2400_AGC 5 /* AGC adjustment */
#define SA2400_AGC_TARGETSIGN BIT(23) /* fine-tune AGC target:
* -7dB to 7dB, sign bit ... */