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:
parent
a2078b09d1
commit
a534631ee7
293
sys/dev/ic/rtw.c
293
sys/dev/ic/rtw.c
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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 ... */
|
||||
|
Loading…
Reference in New Issue
Block a user