summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorReyk Floeter <reyk@cvs.openbsd.org>2005-05-29 02:54:52 +0000
committerReyk Floeter <reyk@cvs.openbsd.org>2005-05-29 02:54:52 +0000
commitcbfea9d11d88792f68883d3abfd48c7176572d1f (patch)
treeeab0c237b0d1a5a09267b2bbe3772b4e71def479 /sys
parent058ac3249a7c2b4d78bd54d65f4677cb22485125 (diff)
cleanup rtw
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files4
-rw-r--r--sys/dev/ic/rtl8225reg.h28
-rw-r--r--sys/dev/ic/rtw.c1447
-rw-r--r--sys/dev/ic/rtwvar.h32
4 files changed, 1322 insertions, 189 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 11ac6c3546e..3bb57619ba1 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1,4 +1,4 @@
-# $OpenBSD: files,v 1.340 2005/05/26 16:37:37 miod Exp $
+# $OpenBSD: files,v 1.341 2005/05/29 02:54:50 reyk Exp $
# $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
@@ -354,8 +354,6 @@ file dev/ic/atw.c atw
# Realtek RTL8180 802.11
device rtw: ether, ifnet, ifmedia, smc93cx6, wlan
file dev/ic/rtw.c rtw
-file dev/ic/rtwphy.c rtw
-file dev/ic/rtwphyio.c rtw
# Ralink RT2500 802.11
device ral: ether, ifnet, ifmedia, wlan
diff --git a/sys/dev/ic/rtl8225reg.h b/sys/dev/ic/rtl8225reg.h
new file mode 100644
index 00000000000..50ef863ac8c
--- /dev/null
+++ b/sys/dev/ic/rtl8225reg.h
@@ -0,0 +1,28 @@
+/* $OpenBSD: rtl8225reg.h,v 1.1 2005/05/29 02:54:51 reyk Exp $ */
+
+/*
+ * Copyright (c) 2005 Reyk Floeter <reyk@vantronix.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DEV_IC_RTL8225REG_H_
+#define _DEV_IC_RTL8225REG_H_
+
+/*
+ * Serial bus format for the Realtek RTL8225 Single-chip Transceiver.
+ */
+#define RTL8225_TWI_DATA_MASK BITS(31, 4)
+#define RTL8225_TWI_ADDR_MASK BITS(4, 0)
+
+#endif /* _DEV_IC_RTL8225REG_H_ */
diff --git a/sys/dev/ic/rtw.c b/sys/dev/ic/rtw.c
index 609406e2f4b..6b9d7b775f4 100644
--- a/sys/dev/ic/rtw.c
+++ b/sys/dev/ic/rtw.c
@@ -1,5 +1,6 @@
-/* $OpenBSD: rtw.c,v 1.28 2005/05/27 18:57:18 robert Exp $ */
-/* $NetBSD: rtw.c,v 1.29 2004/12/27 19:49:16 dyoung Exp $ */
+/* $OpenBSD: rtw.c,v 1.29 2005/05/29 02:54:51 reyk Exp $ */
+/* $NetBSD: rtw.c,v 1.29 2004/12/27 19:49:16 dyoung Exp $ */
+
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
*
@@ -71,161 +72,198 @@
#include <dev/ic/rtwreg.h>
#include <dev/ic/rtwvar.h>
-#include <dev/ic/rtwphyio.h>
-#include <dev/ic/rtwphy.h>
-
+#include <dev/ic/max2820reg.h>
+#include <dev/ic/sa2400reg.h>
+#include <dev/ic/si4136reg.h>
+#include <dev/ic/rtl8225reg.h>
#include <dev/ic/smc93cx6var.h>
-#define KASSERT2(__cond, __msg) \
- do { \
- if (!(__cond)) \
- panic __msg ; \
- } while (0)
-
int rtw_rfprog_fallback = 0;
int rtw_host_rfio = 0;
+int rtw_macbangbits_timeout = 100;
+int rtw_dwelltime = 200; /* milliseconds per channel */
#ifdef RTW_DEBUG
int rtw_debug = 0;
int rtw_rxbufs_limit = RTW_RXQLEN;
#endif /* RTW_DEBUG */
-#define NEXT_ATTACH_STATE(sc, state) do { \
- DPRINTF(sc, RTW_DEBUG_ATTACH, \
- ("%s: attach state %s\n", __func__, #state)); \
- sc->sc_attach_state = state; \
-} while (0)
-
-int rtw_dwelltime = 200; /* milliseconds per channel */
-
-void rtw_start(struct ifnet *);
-void rtw_srom_defaults(struct rtw_srom *, u_int32_t *, u_int8_t *,
- enum rtw_rfchipid *, u_int32_t *);
-void rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *);
-void rtw_txsoft_blk_init_all(struct rtw_txsoft_blk *);
-void rtw_txdescs_sync(struct rtw_txdesc_blk *, u_int, u_int, int);
-void rtw_txdescs_sync_all(struct rtw_txdesc_blk *);
-void rtw_rxbufs_release(bus_dma_tag_t, struct rtw_rxsoft *);
-void rtw_rxdesc_init(struct rtw_rxdesc_blk *, struct rtw_rxsoft *, int, int);
-void rtw_io_enable(struct rtw_regs *, u_int8_t, int);
-void rtw_intr_rx(struct rtw_softc *, u_int16_t);
-void rtw_intr_beacon(struct rtw_softc *, u_int16_t);
-void rtw_intr_atim(struct rtw_softc *);
-void rtw_transmit_config(struct rtw_regs *);
-void rtw_pktfilt_load(struct rtw_softc *);
-void rtw_start(struct ifnet *);
-void rtw_watchdog(struct ifnet *);
-void rtw_next_scan(void *);
-void rtw_recv_mgmt(struct ieee80211com *, struct mbuf *,
- struct ieee80211_node *, int, int, u_int32_t);
-struct ieee80211_node * rtw_node_alloc(struct ieee80211com *);
-void rtw_node_free(struct ieee80211com *, struct ieee80211_node *);
-void rtw_media_status(struct ifnet *, struct ifmediareq *);
-void rtw_txsoft_blk_cleanup_all(struct rtw_softc *);
-void rtw_txdesc_blk_setup(struct rtw_txdesc_blk *, struct rtw_txdesc *,
- u_int, bus_addr_t, bus_addr_t);
-void rtw_txdesc_blk_setup_all(struct rtw_softc *);
-void rtw_intr_tx(struct rtw_softc *, u_int16_t);
-void rtw_intr_ioerror(struct rtw_softc *, u_int16_t);
-void rtw_intr_timeout(struct rtw_softc *);
-void rtw_stop(struct ifnet *, int);
-void rtw_maxim_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
-void rtw_philips_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
-void rtw_pwrstate0(struct rtw_softc *, enum rtw_pwrstate, int, int);
-void rtw_join_bss(struct rtw_softc *, u_int8_t *, u_int16_t);
-void rtw_set_access1(struct rtw_regs *, enum rtw_access);
-int rtw_srom_parse(struct rtw_srom *, u_int32_t *, u_int8_t *,
- enum rtw_rfchipid *, u_int32_t *, enum rtw_locale *, const char *);
-int rtw_srom_read(struct rtw_regs *, u_int32_t, struct rtw_srom *,
- const char *);
-void rtw_set_rfprog(struct rtw_regs *, enum rtw_rfchipid,
- const char *);
+void rtw_start(struct ifnet *);
+void rtw_srom_defaults(struct rtw_srom *, u_int32_t *, u_int8_t *,
+ enum rtw_rfchipid *, u_int32_t *);
+void rtw_txdesc_blk_init_all(struct rtw_txdesc_blk *);
+void rtw_txsoft_blk_init_all(struct rtw_txsoft_blk *);
+void rtw_txdescs_sync(struct rtw_txdesc_blk *, u_int, u_int, int);
+void rtw_txdescs_sync_all(struct rtw_txdesc_blk *);
+void rtw_rxbufs_release(bus_dma_tag_t, struct rtw_rxsoft *);
+void rtw_rxdesc_init(struct rtw_rxdesc_blk *, struct rtw_rxsoft *, int, int);
+void rtw_io_enable(struct rtw_regs *, u_int8_t, int);
+void rtw_intr_rx(struct rtw_softc *, u_int16_t);
+void rtw_intr_beacon(struct rtw_softc *, u_int16_t);
+void rtw_intr_atim(struct rtw_softc *);
+void rtw_transmit_config(struct rtw_softc *);
+void rtw_pktfilt_load(struct rtw_softc *);
+void rtw_start(struct ifnet *);
+void rtw_watchdog(struct ifnet *);
+void rtw_next_scan(void *);
+void rtw_recv_mgmt(struct ieee80211com *, struct mbuf *,
+ struct ieee80211_node *, int, int, u_int32_t);
+struct ieee80211_node *rtw_node_alloc(struct ieee80211com *);
+void rtw_node_free(struct ieee80211com *, struct ieee80211_node *);
+void rtw_media_status(struct ifnet *, struct ifmediareq *);
+void rtw_txsoft_blk_cleanup_all(struct rtw_softc *);
+void rtw_txdesc_blk_setup(struct rtw_txdesc_blk *, struct rtw_txdesc *,
+ u_int, bus_addr_t, bus_addr_t);
+void rtw_txdesc_blk_setup_all(struct rtw_softc *);
+void rtw_intr_tx(struct rtw_softc *, u_int16_t);
+void rtw_intr_ioerror(struct rtw_softc *, u_int16_t);
+void rtw_intr_timeout(struct rtw_softc *);
+void rtw_stop(struct ifnet *, int);
+void rtw_maxim_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
+void rtw_philips_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
+void rtw_rtl_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
+void rtw_pwrstate0(struct rtw_softc *, enum rtw_pwrstate, int, int);
+void rtw_join_bss(struct rtw_softc *, u_int8_t *, u_int16_t);
+void rtw_set_access1(struct rtw_regs *, enum rtw_access);
+int rtw_srom_parse(struct rtw_softc *);
+int rtw_srom_read(struct rtw_regs *, u_int32_t, struct rtw_srom *,
+ const char *);
+void rtw_set_rfprog(struct rtw_regs *, enum rtw_rfchipid,
+ const char *);
u_int8_t rtw_chan2txpower(struct rtw_srom *, struct ieee80211com *,
- struct ieee80211_channel *);
-int rtw_txsoft_blk_init(struct rtw_txsoft_blk *);
-int rtw_rxsoft_init_all(bus_dma_tag_t, struct rtw_rxsoft *,
- int *, const char *);
-void rtw_txsoft_release(bus_dma_tag_t, struct ieee80211com *,
- struct rtw_txsoft *);
-void rtw_txsofts_release(bus_dma_tag_t, struct ieee80211com *,
- struct rtw_txsoft_blk *);
-void rtw_hwring_setup(struct rtw_softc *);
-int rtw_swring_setup(struct rtw_softc *);
-void rtw_txdesc_blk_reset(struct rtw_txdesc_blk *);
-void rtw_txdescs_reset(struct rtw_softc *);
-void rtw_rxdescs_reset(struct rtw_softc *);
-void rtw_rfmd_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
-int rtw_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
-int rtw_tune(struct rtw_softc *);
-void rtw_set_nettype(struct rtw_softc *, enum ieee80211_opmode);
-int rtw_init(struct ifnet *);
-int rtw_ioctl(struct ifnet *, u_long, caddr_t);
-int rtw_seg_too_short(bus_dmamap_t);
+ struct ieee80211_channel *);
+int rtw_txsoft_blk_init(struct rtw_txsoft_blk *);
+int rtw_rxsoft_init_all(bus_dma_tag_t, struct rtw_rxsoft *,
+ int *, const char *);
+void rtw_txsoft_release(bus_dma_tag_t, struct ieee80211com *,
+ struct rtw_txsoft *);
+void rtw_txsofts_release(bus_dma_tag_t, struct ieee80211com *,
+ struct rtw_txsoft_blk *);
+void rtw_hwring_setup(struct rtw_softc *);
+int rtw_swring_setup(struct rtw_softc *);
+void rtw_txdesc_blk_reset(struct rtw_txdesc_blk *);
+void rtw_txdescs_reset(struct rtw_softc *);
+void rtw_rxdescs_reset(struct rtw_softc *);
+void rtw_rfmd_pwrstate(struct rtw_regs *, enum rtw_pwrstate, int, int);
+int rtw_pwrstate(struct rtw_softc *, enum rtw_pwrstate);
+int rtw_tune(struct rtw_softc *);
+void rtw_set_nettype(struct rtw_softc *, enum ieee80211_opmode);
+int rtw_init(struct ifnet *);
+int rtw_ioctl(struct ifnet *, u_long, caddr_t);
+int rtw_seg_too_short(bus_dmamap_t);
struct mbuf *rtw_dmamap_load_txbuf(bus_dma_tag_t, bus_dmamap_t, struct mbuf *,
- u_int, short *, const char *);
-int rtw_newstate(struct ieee80211com *, enum ieee80211_state, int);
-int rtw_media_change(struct ifnet *);
-int rtw_txsoft_blk_setup_all(struct rtw_softc *);
+ u_int, short *, const char *);
+int rtw_newstate(struct ieee80211com *, enum ieee80211_state, int);
+int rtw_media_change(struct ifnet *);
+int rtw_txsoft_blk_setup_all(struct rtw_softc *);
struct rtw_rf * rtw_rf_attach(struct rtw_softc *, enum rtw_rfchipid, int);
u_int8_t rtw_check_phydelay(struct rtw_regs *, u_int32_t);
-int rtw_chip_reset1(struct rtw_regs *, const char *);
-int rtw_chip_reset(struct rtw_regs *, const char *);
-int rtw_recall_eeprom(struct rtw_regs *, const char *);
-int rtw_reset(struct rtw_softc *);
-int rtw_txdesc_dmamaps_create(bus_dma_tag_t, struct rtw_txsoft *, u_int);
-int rtw_rxdesc_dmamaps_create(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
-void rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
-void rtw_txdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_txsoft *, u_int);
-void rtw_srom_free(struct rtw_srom *);
-void rtw_init_channels(enum rtw_locale, struct ieee80211_channel (*)[],
- const char*);
-void rtw_identify_country(struct rtw_regs *, enum rtw_locale *, const char *);
-int rtw_identify_sta(struct rtw_regs *, u_int8_t (*)[], const char *);
-void rtw_rxdescs_sync(struct rtw_rxdesc_blk *, int, int, int);
-int rtw_rxsoft_alloc(bus_dma_tag_t, struct rtw_rxsoft *);
-void rtw_collect_txpkt(struct rtw_softc *, struct rtw_txdesc_blk *,
- struct rtw_txsoft *, int);
-void rtw_collect_txring(struct rtw_softc *, struct rtw_txsoft_blk *,
- struct rtw_txdesc_blk *);
-void rtw_suspend_ticks(struct rtw_softc *);
-void rtw_resume_ticks(struct rtw_softc *);
-void rtw_enable_interrupts(struct rtw_softc *);
-int rtw_dequeue(struct ifnet *, struct rtw_txsoft_blk **,
- struct rtw_txdesc_blk **, struct mbuf **,
- struct ieee80211_node **);
-void rtw_setifprops(struct ifnet *, const char *, void *);
-void rtw_set80211props(struct ieee80211com *);
-void rtw_set80211methods(struct rtw_mtbl *, struct ieee80211com *);
-void rtw_establish_hooks(struct rtw_hooks *, const char *, void *);
-void rtw_disestablish_hooks(struct rtw_hooks *, const char *, void *);
-int rtw_txsoft_blk_setup(struct rtw_txsoft_blk *, u_int);
-void rtw_rxdesc_init_all(struct rtw_rxdesc_blk *, struct rtw_rxsoft *, int);
-int rtw_txring_choose(struct rtw_softc *, struct rtw_txsoft_blk **,
- struct rtw_txdesc_blk **, int);
+int rtw_chip_reset1(struct rtw_regs *, const char *);
+int rtw_chip_reset(struct rtw_regs *, const char *);
+int rtw_recall_eeprom(struct rtw_regs *, const char *);
+int rtw_reset(struct rtw_softc *);
+int rtw_txdesc_dmamaps_create(bus_dma_tag_t, struct rtw_txsoft *, u_int);
+int rtw_rxdesc_dmamaps_create(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
+void rtw_rxdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_rxsoft *, u_int);
+void rtw_txdesc_dmamaps_destroy(bus_dma_tag_t, struct rtw_txsoft *, u_int);
+void rtw_srom_free(struct rtw_srom *);
+void rtw_init_channels(enum rtw_locale, struct ieee80211_channel (*)[],
+ const char*);
+void rtw_identify_country(struct rtw_regs *, enum rtw_locale *, const char *);
+int rtw_identify_sta(struct rtw_regs *, u_int8_t (*)[], const char *);
+void rtw_rxdescs_sync(struct rtw_rxdesc_blk *, int, int, int);
+int rtw_rxsoft_alloc(bus_dma_tag_t, struct rtw_rxsoft *);
+void rtw_collect_txpkt(struct rtw_softc *, struct rtw_txdesc_blk *,
+ struct rtw_txsoft *, int);
+void rtw_collect_txring(struct rtw_softc *, struct rtw_txsoft_blk *,
+ struct rtw_txdesc_blk *);
+void rtw_suspend_ticks(struct rtw_softc *);
+void rtw_resume_ticks(struct rtw_softc *);
+void rtw_enable_interrupts(struct rtw_softc *);
+int rtw_dequeue(struct ifnet *, struct rtw_txsoft_blk **,
+ struct rtw_txdesc_blk **, struct mbuf **,
+ struct ieee80211_node **);
+void rtw_setifprops(struct ifnet *, const char *, void *);
+void rtw_set80211props(struct ieee80211com *);
+void rtw_set80211methods(struct rtw_mtbl *, struct ieee80211com *);
+void rtw_establish_hooks(struct rtw_hooks *, const char *, void *);
+void rtw_disestablish_hooks(struct rtw_hooks *, const char *, void *);
+int rtw_txsoft_blk_setup(struct rtw_txsoft_blk *, u_int);
+void rtw_rxdesc_init_all(struct rtw_rxdesc_blk *, struct rtw_rxsoft *,
+ int);
+int rtw_txring_choose(struct rtw_softc *, struct rtw_txsoft_blk **,
+ struct rtw_txdesc_blk **, int);
struct mbuf *rtw_80211_dequeue(struct rtw_softc *, struct ifqueue *, int,
- struct rtw_txsoft_blk **, struct rtw_txdesc_blk **,
- struct ieee80211_node **, short *);
+ struct rtw_txsoft_blk **, struct rtw_txdesc_blk **,
+ struct ieee80211_node **, short *);
uint64_t rtw_tsf_extend(struct rtw_regs *, u_int32_t);
-void rtw_ibss_merge(struct rtw_softc *, struct ieee80211_node *, u_int32_t);
-
-void rtw_led_attach(struct rtw_led_state *, void *);
-void rtw_led_init(struct rtw_regs *);
-void rtw_led_slowblink(void *);
-void rtw_led_fastblink(void *);
-void rtw_led_set(struct rtw_led_state *, struct rtw_regs *, int);
-void rtw_led_newstate(struct rtw_softc *, enum ieee80211_state);
+void rtw_ibss_merge(struct rtw_softc *, struct ieee80211_node *,
+ u_int32_t);
+void rtw_led_attach(struct rtw_led_state *, void *);
+void rtw_led_init(struct rtw_regs *);
+void rtw_led_slowblink(void *);
+void rtw_led_fastblink(void *);
+void rtw_led_set(struct rtw_led_state *, struct rtw_regs *, u_int);
+void rtw_led_newstate(struct rtw_softc *, enum ieee80211_state);
+struct rtw_rf *rtw_sa2400_create(struct rtw_regs *, rtw_rf_write_t, int);
+struct rtw_rf *rtw_max2820_create(struct rtw_regs *, rtw_rf_write_t, int);
+struct rtw_rf *rtw_rtl8225_create(struct rtw_regs *, rtw_rf_write_t);
+int rtw_phy_init(struct rtw_regs *, struct rtw_rf *, u_int8_t, u_int8_t,
+ u_int, int, int, enum rtw_pwrstate);
+int rtw_bbp_preinit(struct rtw_regs *, u_int, int, u_int);
+int rtw_bbp_init(struct rtw_regs *, struct rtw_bbpset *, int,
+ int, u_int8_t, u_int);
+void rtw_verify_syna(u_int, u_int32_t);
+int rtw_sa2400_pwrstate(struct rtw_rf *, enum rtw_pwrstate);
+int rtw_sa2400_txpower(struct rtw_rf *, u_int8_t);
+int rtw_sa2400_tune(struct rtw_rf *, u_int);
+int rtw_sa2400_manrx_init(struct rtw_sa2400 *);
+int rtw_sa2400_vcocal_start(struct rtw_sa2400 *, int);
+int rtw_sa2400_vco_calibration(struct rtw_sa2400 *);
+int rtw_sa2400_filter_calibration(struct rtw_sa2400 *);
+int rtw_sa2400_dc_calibration(struct rtw_sa2400 *);
+int rtw_sa2400_agc_init(struct rtw_sa2400 *);
+void rtw_sa2400_destroy(struct rtw_rf *);
+int rtw_sa2400_calibrate(struct rtw_rf *, u_int);
+int rtw_sa2400_init(struct rtw_rf *, u_int, u_int8_t,
+ enum rtw_pwrstate);
+int rtw_max2820_pwrstate(struct rtw_rf *, enum rtw_pwrstate);
+void rtw_max2820_destroy(struct rtw_rf *);
+int rtw_max2820_init(struct rtw_rf *, u_int, u_int8_t,
+ enum rtw_pwrstate);
+int rtw_max2820_txpower(struct rtw_rf *, u_int8_t);
+int rtw_max2820_tune(struct rtw_rf *, u_int);
+int rtw_rtl8225_pwrstate(struct rtw_rf *, enum rtw_pwrstate);
+void rtw_rtl8225_destroy(struct rtw_rf *);
+int rtw_rtl8225_init(struct rtw_rf *, u_int, u_int8_t,
+ enum rtw_pwrstate);
+int rtw_rtl8225_txpower(struct rtw_rf *, u_int8_t);
+int rtw_rtl8225_tune(struct rtw_rf *, u_int);
+int rtw_rf_hostwrite(struct rtw_regs *, enum rtw_rfchipid, u_int,
+ u_int32_t);
+int rtw_rf_macwrite(struct rtw_regs *, enum rtw_rfchipid, u_int,
+ u_int32_t);
+u_int8_t rtw_bbp_read(struct rtw_regs *, u_int);
+int rtw_bbp_write(struct rtw_regs *, u_int, u_int);
+u_int32_t rtw_grf5101_host_crypt(u_int, u_int32_t);
+u_int32_t rtw_maxim_swizzle(u_int, uint32_t);
+u_int32_t rtw_grf5101_mac_crypt(u_int, u_int32_t);
+void rtw_rf_hostbangbits(struct rtw_regs *, u_int32_t, int, u_int);
+void rtw_rf_rtl8225_hostbangbits(struct rtw_regs *, u_int32_t, int, u_int);
+int rtw_rf_macbangbits(struct rtw_regs *, u_int32_t);
+const char *rtw_rfchipid_string(enum rtw_rfchipid);
#ifdef RTW_DEBUG
-void rtw_print_txdesc(struct rtw_softc *, const char *,
- struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
-const char * rtw_access_string(enum rtw_access);
-void rtw_dump_rings(struct rtw_softc *);
-void rtw_print_txdesc(struct rtw_softc *, const char *,
- struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
+void rtw_print_txdesc(struct rtw_softc *, const char *,
+ struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
+const char *rtw_access_string(enum rtw_access);
+void rtw_dump_rings(struct rtw_softc *);
+void rtw_print_txdesc(struct rtw_softc *, const char *,
+ struct rtw_txsoft *, struct rtw_txdesc_blk *, int);
#endif
struct cfdriver rtw_cd = {
- NULL, "rtw", DV_IFNET
+ NULL, "rtw", DV_IFNET
};
void
@@ -536,12 +574,16 @@ rtw_srom_defaults(struct rtw_srom *sr, u_int32_t *flags, u_int8_t *cs_threshold,
}
int
-rtw_srom_parse(struct rtw_srom *sr, u_int32_t *flags, u_int8_t *cs_threshold,
- enum rtw_rfchipid *rfchipid, u_int32_t *rcr, enum rtw_locale *locale,
- const char *dvname)
+rtw_srom_parse(struct rtw_softc *sc)
{
int i;
- const char *rfname, *paname;
+ struct rtw_srom *sr = &sc->sc_srom;
+ u_int32_t *flags = &sc->sc_flags;
+ u_int8_t *cs_threshold = &sc->sc_csthr;
+ enum rtw_rfchipid *rfchipid = &sc->sc_rfchipid;
+ u_int32_t *rcr = &sc->sc_rcr;
+ enum rtw_locale *locale = &sc->sc_locale;
+ const char *rfname, *paname = NULL;
char scratch[sizeof("unknown 0xXX")];
u_int16_t version;
u_int8_t mac[IEEE80211_ADDR_LEN];
@@ -551,7 +593,8 @@ rtw_srom_parse(struct rtw_srom *sr, u_int32_t *flags, u_int8_t *cs_threshold,
version = RTW_SR_GET16(sr, RTW_SR_VERSION);
RTW_DPRINTF(RTW_DEBUG_ATTACH,
- ("%s: SROM %d.%d\n", dvname, version >> 8, version & 0xff));
+ ("%s: SROM %d.%d\n", sc->sc_dev.dv_xname, version >> 8,
+ version & 0xff));
if (version <= 0x0101) {
printf(" is not understood, limping along with defaults ");
@@ -563,11 +606,11 @@ rtw_srom_parse(struct rtw_srom *sr, u_int32_t *flags, u_int8_t *cs_threshold,
mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i);
RTW_DPRINTF(RTW_DEBUG_ATTACH,
- ("%s: EEPROM MAC %s\n", dvname, ether_sprintf(mac)));
+ ("%s: EEPROM MAC %s\n", sc->sc_dev.dv_xname, ether_sprintf(mac)));
*cs_threshold = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR);
- if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW_CONFIG2_ANT) != 0)
+ if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW8180_CONFIG2_ANT) != 0)
*flags |= RTW_F_ANTDIV;
/* Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems
@@ -583,11 +626,14 @@ rtw_srom_parse(struct rtw_srom *sr, u_int32_t *flags, u_int8_t *cs_threshold,
*rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID);
switch (*rfchipid) {
+ case RTW_RFCHIPID_RTL8225:
+ rfname = "RTL8225";
+ break;
case RTW_RFCHIPID_GCT: /* this combo seen in the wild */
rfname = "GRF5101";
paname = "WS9901";
break;
- case RTW_RFCHIPID_MAXIM:
+ case RTW_RFCHIPID_MAXIM2820:
rfname = "MAX2820"; /* guess */
paname = "MAX2422"; /* guess */
break;
@@ -599,7 +645,7 @@ rtw_srom_parse(struct rtw_srom *sr, u_int32_t *flags, u_int8_t *cs_threshold,
rfname = "SA2400A";
paname = "SA2411";
break;
- case RTW_RFCHIPID_RFMD:
+ case RTW_RFCHIPID_RFMD2948:
/* this is the same front-end as an atw(4)! */
rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */
"LNA: RFMD RF2494, " /* mentioned in Realtek docs */
@@ -613,18 +659,25 @@ rtw_srom_parse(struct rtw_srom *sr, u_int32_t *flags, u_int8_t *cs_threshold,
break;
default:
snprintf(scratch, sizeof(scratch), "unknown 0x%02x", *rfchipid);
- rfname = paname = scratch;
+ rfname = scratch;
}
- printf("radio %s, amp %s, ", rfname, paname);
+ printf("radio %s, ", rfname);
+ if (paname != NULL)
+ printf("amp %s, ", paname);
- switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_GL_MASK) {
- case RTW_CONFIG0_GL_USA:
+ if (sc->sc_flags & RTW_F_RTL8185) {
+ *locale = RTW_LOCALE_UNKNOWN;
+ return (0);
+ }
+
+ switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW8180_CONFIG0_GL_MASK) {
+ case RTW8180_CONFIG0_GL_USA:
*locale = RTW_LOCALE_USA;
break;
- case RTW_CONFIG0_GL_EUROPE:
+ case RTW8180_CONFIG0_GL_EUROPE:
*locale = RTW_LOCALE_EUROPE;
break;
- case RTW_CONFIG0_GL_JAPAN:
+ case RTW8180_CONFIG0_GL_JAPAN:
*locale = RTW_LOCALE_JAPAN;
break;
default:
@@ -745,7 +798,7 @@ rtw_set_rfprog(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS;
method = "Philips";
break;
- case RTW_RFCHIPID_RFMD:
+ case RTW_RFCHIPID_RFMD2948:
cfg4 |= RTW_CONFIG4_RFTYPE_RFMD;
method = "RFMD";
break;
@@ -807,14 +860,14 @@ rtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale,
{
u_int8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0);
- switch (cfg0 & RTW_CONFIG0_GL_MASK) {
- case RTW_CONFIG0_GL_USA:
+ switch (cfg0 & RTW8180_CONFIG0_GL_MASK) {
+ case RTW8180_CONFIG0_GL_USA:
*locale = RTW_LOCALE_USA;
break;
- case RTW_CONFIG0_GL_JAPAN:
+ case RTW8180_CONFIG0_GL_JAPAN:
*locale = RTW_LOCALE_JAPAN;
break;
- case RTW_CONFIG0_GL_EUROPE:
+ case RTW8180_CONFIG0_GL_EUROPE:
*locale = RTW_LOCALE_EUROPE;
break;
default:
@@ -1955,6 +2008,13 @@ rtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
}
void
+rtw_rtl_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
+ int before_rf, int digphy)
+{
+ /* empty */
+}
+
+void
rtw_pwrstate0(struct rtw_softc *sc, enum rtw_pwrstate power, int before_rf,
int digphy)
{
@@ -2085,8 +2145,9 @@ rtw_enable(struct rtw_softc *sc)
}
void
-rtw_transmit_config(struct rtw_regs *regs)
+rtw_transmit_config(struct rtw_softc *sc)
{
+ struct rtw_regs *regs = &sc->sc_regs;
u_int32_t tcr;
tcr = RTW_READ(regs, RTW_TCR);
@@ -2094,7 +2155,8 @@ rtw_transmit_config(struct rtw_regs *regs)
tcr |= RTW_TCR_CWMIN;
tcr &= ~RTW_TCR_MXDMA_MASK;
tcr |= RTW_TCR_MXDMA_256;
- tcr |= RTW_TCR_SAT; /* send ACK as fast as possible */
+ if ((sc->sc_flags & RTW_F_RTL8185) == 0)
+ tcr |= RTW8180_TCR_SAT; /* send ACK as fast as possible */
tcr &= ~RTW_TCR_LBK_MASK;
tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */
@@ -2175,13 +2237,13 @@ rtw_pktfilt_load(struct rtw_softc *sc)
/* XXX might be necessary to stop Rx/Tx engines while setting filters */
sc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK;
- sc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK);
+ sc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW8180_RCR_RXFTH_MASK);
sc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT;
/* MAC auto-reset PHY (huh?) */
sc->sc_rcr |= RTW_RCR_ENMARP;
/* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */
- sc->sc_rcr |= RTW_RCR_MXDMA_1024 | RTW_RCR_RXFTH_WHOLE;
+ sc->sc_rcr |= RTW_RCR_MXDMA_1024 | RTW8180_RCR_RXFTH_WHOLE;
switch (ic->ic_opmode) {
case IEEE80211_M_MONITOR:
@@ -2274,7 +2336,7 @@ rtw_init(struct ifnet *ifp)
if ((rc = rtw_swring_setup(sc)) != 0)
goto out;
- rtw_transmit_config(regs);
+ rtw_transmit_config(sc);
rtw_set_access(regs, RTW_ACCESS_CONFIG);
@@ -2282,7 +2344,10 @@ rtw_init(struct ifnet *ifp)
RTW_WBW(regs, RTW_MSR, RTW_BRSR);
/* long PLCP header, 1Mb/2Mb basic rate */
- RTW_WRITE16(regs, RTW_BRSR, RTW_BRSR_MBR8180_2MBPS);
+ if (sc->sc_flags & RTW_F_RTL8185)
+ RTW_WRITE16(regs, RTW_BRSR, RTW8185_BRSR_MBR_2MBPS);
+ else
+ RTW_WRITE16(regs, RTW_BRSR, RTW8180_BRSR_MBR_2MBPS);
RTW_SYNC(regs, RTW_BRSR, RTW_BRSR);
rtw_set_access(regs, RTW_ACCESS_ANAPARM);
@@ -2336,7 +2401,7 @@ rtw_led_init(struct rtw_regs *regs)
rtw_set_access(regs, RTW_ACCESS_CONFIG);
cfg0 = RTW_READ8(regs, RTW_CONFIG0);
- cfg0 |= RTW_CONFIG0_LEDGPOEN;
+ cfg0 |= RTW8180_CONFIG0_LEDGPOEN;
RTW_WRITE8(regs, RTW_CONFIG0, cfg0);
cfg1 = RTW_READ8(regs, RTW_CONFIG1);
@@ -2393,7 +2458,7 @@ rtw_led_newstate(struct rtw_softc *sc, enum ieee80211_state nstate)
}
void
-rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, int hwverid)
+rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, u_int hwverid)
{
u_int8_t led_condition;
bus_size_t ofs;
@@ -2411,7 +2476,7 @@ rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, int hwverid)
switch (hwverid) {
default:
- case 'F':
+ case RTW_TCR_HWVERID_RTL8180F:
ofs = RTW_PSR;
newval = mask = RTW_PSR_LEDGPO0 | RTW_PSR_LEDGPO1;
if (led_condition & RTW_LED0)
@@ -2419,7 +2484,7 @@ rtw_led_set(struct rtw_led_state *ls, struct rtw_regs *regs, int hwverid)
if (led_condition & RTW_LED1)
newval &= ~RTW_PSR_LEDGPO1;
break;
- case 'D':
+ case RTW_TCR_HWVERID_RTL8180D:
ofs = RTW_9346CR;
mask = RTW_9346CR_EEM_MASK | RTW_9346CR_EEDI | RTW_9346CR_EECS;
newval = RTW_9346CR_EEM_PROGRAM;
@@ -3084,7 +3149,7 @@ rtw_join_bss(struct rtw_softc *sc, u_int8_t *bssid, u_int16_t intval0)
rtw_set_access(regs, RTW_ACCESS_NONE);
/* TBD WEP */
- RTW_WRITE8(regs, RTW_SCR, 0);
+ RTW_WRITE8(regs, RTW8180_SCR, 0);
rtw_io_enable(regs, RTW_CR_RE | RTW_CR_TE, 1);
}
@@ -3483,20 +3548,25 @@ rtw_rf_attach(struct rtw_softc *sc, enum rtw_rfchipid rfchipid, int digphy)
struct rtw_rf *rf;
switch (rfchipid) {
+ case RTW_RFCHIPID_RTL8225:
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:
+ case RTW_RFCHIPID_RFMD2948:
rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite;
break;
}
switch (rfchipid) {
- case RTW_RFCHIPID_MAXIM:
+ case RTW_RFCHIPID_RTL8225:
+ rf = rtw_rtl8225_create(&sc->sc_regs, rf_write);
+ sc->sc_pwrstate_cb = rtw_rtl_pwrstate;
+ break;
+ case RTW_RFCHIPID_MAXIM2820:
rf = rtw_max2820_create(&sc->sc_regs, rf_write, 0);
sc->sc_pwrstate_cb = rtw_maxim_pwrstate;
break;
@@ -3504,7 +3574,7 @@ rtw_rf_attach(struct rtw_softc *sc, enum rtw_rfchipid rfchipid, int digphy)
rf = rtw_sa2400_create(&sc->sc_regs, rf_write, digphy);
sc->sc_pwrstate_cb = rtw_philips_pwrstate;
break;
- case RTW_RFCHIPID_RFMD:
+ case RTW_RFCHIPID_RFMD2948:
/* XXX RFMD has no RF constructor */
sc->sc_pwrstate_cb = rtw_rfmd_pwrstate;
/*FALLTHROUGH*/
@@ -3524,7 +3594,7 @@ u_int8_t
rtw_check_phydelay(struct rtw_regs *regs, u_int32_t rcr0)
{
#define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV)
-#define REVC (REVAB | RTW_RCR_RXFTH_WHOLE)
+#define REVC (REVAB | RTW8180_RCR_RXFTH_WHOLE)
u_int8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY);
@@ -3547,22 +3617,32 @@ void
rtw_attach(struct rtw_softc *sc)
{
struct rtw_txsoft_blk *tsb;
+ const char *vername;
+ char scratch[sizeof("unknown 0xXXXXXXXX")];
int pri, rc;
NEXT_ATTACH_STATE(sc, DETACHED);
- switch (RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK) {
- case RTW_TCR_HWVERID_F:
- sc->sc_hwverid = 'F';
+ sc->sc_hwverid = RTW_READ(&sc->sc_regs, RTW_TCR) & RTW_TCR_HWVERID_MASK;
+ switch (sc->sc_hwverid) {
+ case RTW_TCR_HWVERID_RTL8185:
+ vername = "RTL8185";
+ sc->sc_flags |= RTW_F_RTL8185;
+ break;
+ case RTW_TCR_HWVERID_RTL8180F:
+ vername = "RTL8180F";
break;
- case RTW_TCR_HWVERID_D:
- sc->sc_hwverid = 'D';
+ case RTW_TCR_HWVERID_RTL8180D:
+ vername = "RTL8180D";
break;
default:
- sc->sc_hwverid = '?';
+ snprintf(scratch, sizeof(scratch), "unknown 0x%08x",
+ sc->sc_hwverid);
+ vername = scratch;
break;
}
- printf("%s: ver %c, ", sc->sc_dev.dv_xname, sc->sc_hwverid);
+
+ printf("%s: ver %s, ", sc->sc_dev.dv_xname, vername);
rc = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct rtw_descs),
RTW_DESC_ALIGNMENT, 0, &sc->sc_desc_segs, 1, &sc->sc_desc_nsegs,
@@ -3662,9 +3742,7 @@ rtw_attach(struct rtw_softc *sc)
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,
- sc->sc_dev.dv_xname) != 0) {
+ if (rtw_srom_parse(sc) != 0) {
printf("\n%s: attach failed, malformed serial ROM\n",
sc->sc_dev.dv_xname);
goto err;
@@ -3854,3 +3932,1010 @@ rtw_rfbus_write(struct rtw_rfbus *bus, enum rtw_rfchipid rfchipid, u_int addr,
{
return (*bus->b_write)(bus->b_regs, rfchipid, addr, val);
}
+
+/*
+ * PHY specific functions
+ */
+
+int
+rtw_bbp_preinit(struct rtw_regs *regs, u_int antatten0, int dflantb,
+ u_int freq)
+{
+ u_int antatten = antatten0;
+ if (dflantb)
+ antatten |= RTW_BBP_ANTATTEN_DFLANTB;
+ if (freq == 2484) /* channel 14 */
+ antatten |= RTW_BBP_ANTATTEN_CHAN14;
+ return rtw_bbp_write(regs, RTW_BBP_ANTATTEN, antatten);
+}
+
+int
+rtw_bbp_init(struct rtw_regs *regs, struct rtw_bbpset *bb, int antdiv,
+ int dflantb, u_int8_t cs_threshold, u_int freq)
+{
+ int rc;
+ u_int32_t sys2, sys3;
+
+ sys2 = bb->bb_sys2;
+ if (antdiv)
+ sys2 |= RTW_BBP_SYS2_ANTDIV;
+ sys3 = bb->bb_sys3 |
+ LSHIFT(cs_threshold, RTW_BBP_SYS3_CSTHRESH_MASK);
+
+#define RTW_BBP_WRITE_OR_RETURN(reg, val) \
+ if ((rc = rtw_bbp_write(regs, reg, val)) != 0) \
+ return rc;
+
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS1, bb->bb_sys1);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TXAGC, bb->bb_txagc);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_LNADET, bb->bb_lnadet);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCINI, bb->bb_ifagcini);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCLIMIT, bb->bb_ifagclimit);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_IFAGCDET, bb->bb_ifagcdet);
+
+ if ((rc = rtw_bbp_preinit(regs, bb->bb_antatten, dflantb, freq)) != 0)
+ return rc;
+
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_TRL, bb->bb_trl);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS2, sys2);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_SYS3, sys3);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHESTLIM, bb->bb_chestlim);
+ RTW_BBP_WRITE_OR_RETURN(RTW_BBP_CHSQLIM, bb->bb_chsqlim);
+ return 0;
+}
+
+int
+rtw_sa2400_txpower(struct rtw_rf *rf, u_int8_t opaque_txpower)
+{
+ struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
+ struct rtw_rfbus *bus = &sa->sa_bus;
+
+ return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_TX,
+ opaque_txpower);
+}
+
+/* make sure we're using the same settings as the reference driver */
+void
+rtw_verify_syna(u_int freq, u_int32_t val)
+{
+ u_int32_t expected_val = ~val;
+
+ switch (freq) {
+ case 2412:
+ expected_val = 0x0000096c; /* ch 1 */
+ break;
+ case 2417:
+ expected_val = 0x00080970; /* ch 2 */
+ break;
+ case 2422:
+ expected_val = 0x00100974; /* ch 3 */
+ break;
+ case 2427:
+ expected_val = 0x00180978; /* ch 4 */
+ break;
+ case 2432:
+ expected_val = 0x00000980; /* ch 5 */
+ break;
+ case 2437:
+ expected_val = 0x00080984; /* ch 6 */
+ break;
+ case 2442:
+ expected_val = 0x00100988; /* ch 7 */
+ break;
+ case 2447:
+ expected_val = 0x0018098c; /* ch 8 */
+ break;
+ case 2452:
+ expected_val = 0x00000994; /* ch 9 */
+ break;
+ case 2457:
+ expected_val = 0x00080998; /* ch 10 */
+ break;
+ case 2462:
+ expected_val = 0x0010099c; /* ch 11 */
+ break;
+ case 2467:
+ expected_val = 0x001809a0; /* ch 12 */
+ break;
+ case 2472:
+ expected_val = 0x000009a8; /* ch 13 */
+ break;
+ case 2484:
+ expected_val = 0x000009b4; /* ch 14 */
+ break;
+ }
+ KASSERT(val == expected_val);
+}
+
+/* freq is in MHz */
+int
+rtw_sa2400_tune(struct rtw_rf *rf, u_int freq)
+{
+ struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
+ struct rtw_rfbus *bus = &sa->sa_bus;
+ int rc;
+ u_int32_t syna, synb, sync;
+
+ /* XO = 44MHz, R = 11, hence N is in units of XO / R = 4MHz.
+ *
+ * The channel spacing (5MHz) is not divisible by 4MHz, so
+ * we set the fractional part of N to compensate.
+ */
+ int n = freq / 4, nf = (freq % 4) * 2;
+
+ syna = LSHIFT(nf, SA2400_SYNA_NF_MASK) | LSHIFT(n, SA2400_SYNA_N_MASK);
+ rtw_verify_syna(freq, syna);
+
+ /* Divide the 44MHz crystal down to 4MHz. Set the fractional
+ * compensation charge pump value to agree with the fractional
+ * modulus.
+ */
+ synb = LSHIFT(11, SA2400_SYNB_R_MASK) | SA2400_SYNB_L_NORMAL |
+ SA2400_SYNB_ON | SA2400_SYNB_ONE |
+ LSHIFT(80, SA2400_SYNB_FC_MASK); /* agrees w/ SA2400_SYNA_FM = 0 */
+
+ sync = SA2400_SYNC_CP_NORMAL;
+
+ if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNA,
+ syna)) != 0)
+ return rc;
+ if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNB,
+ synb)) != 0)
+ return rc;
+ if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYNC,
+ sync)) != 0)
+ return rc;
+ return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_SYND, 0x0);
+}
+
+int
+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_DEFAULTS;
+ switch (power) {
+ case RTW_ON:
+ opmode |= SA2400_OPMODE_MODE_TXRX;
+ break;
+ case RTW_SLEEP:
+ opmode |= SA2400_OPMODE_MODE_WAIT;
+ break;
+ case RTW_OFF:
+ opmode |= SA2400_OPMODE_MODE_SLEEP;
+ break;
+ }
+
+ if (sa->sa_digphy)
+ opmode |= SA2400_OPMODE_DIGIN;
+
+ return rtw_rfbus_write(bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
+ opmode);
+}
+
+int
+rtw_sa2400_manrx_init(struct rtw_sa2400 *sa)
+{
+ u_int32_t manrx;
+
+ /* XXX we are not supposed to be in RXMGC mode when we do
+ * this?
+ */
+ manrx = SA2400_MANRX_AHSN;
+ manrx |= SA2400_MANRX_TEN;
+ manrx |= LSHIFT(1023, SA2400_MANRX_RXGAIN_MASK);
+
+ return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_MANRX,
+ manrx);
+}
+
+int
+rtw_sa2400_vcocal_start(struct rtw_sa2400 *sa, int start)
+{
+ u_int32_t opmode;
+
+ opmode = SA2400_OPMODE_DEFAULTS;
+ if (start)
+ opmode |= SA2400_OPMODE_MODE_VCOCALIB;
+ else
+ opmode |= SA2400_OPMODE_MODE_SLEEP;
+
+ if (sa->sa_digphy)
+ opmode |= SA2400_OPMODE_DIGIN;
+
+ return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
+ opmode);
+}
+
+int
+rtw_sa2400_vco_calibration(struct rtw_sa2400 *sa)
+{
+ int rc;
+ /* calibrate VCO */
+ if ((rc = rtw_sa2400_vcocal_start(sa, 1)) != 0)
+ return rc;
+ DELAY(2200); /* 2.2 milliseconds */
+ /* XXX superfluous: SA2400 automatically entered SLEEP mode. */
+ return rtw_sa2400_vcocal_start(sa, 0);
+}
+
+int
+rtw_sa2400_filter_calibration(struct rtw_sa2400 *sa)
+{
+ u_int32_t opmode;
+
+ opmode = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_FCALIB;
+ if (sa->sa_digphy)
+ opmode |= SA2400_OPMODE_DIGIN;
+
+ return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
+ opmode);
+}
+
+int
+rtw_sa2400_dc_calibration(struct rtw_sa2400 *sa)
+{
+ struct rtw_rf *rf = &sa->sa_rf;
+ int rc;
+ u_int32_t dccal;
+
+ (*rf->rf_continuous_tx_cb)(rf->rf_continuous_tx_arg, 1);
+
+ dccal = SA2400_OPMODE_DEFAULTS | SA2400_OPMODE_MODE_TXRX;
+
+ rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
+ dccal);
+ if (rc != 0)
+ return rc;
+
+ DELAY(5); /* DCALIB after being in Tx mode for 5
+ * microseconds
+ */
+
+ dccal &= ~SA2400_OPMODE_MODE_MASK;
+ dccal |= SA2400_OPMODE_MODE_DCALIB;
+
+ rc = rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_OPMODE,
+ dccal);
+ if (rc != 0)
+ return rc;
+
+ DELAY(20); /* calibration takes at most 20 microseconds */
+
+ (*rf->rf_continuous_tx_cb)(rf->rf_continuous_tx_arg, 0);
+
+ return 0;
+}
+
+int
+rtw_sa2400_agc_init(struct rtw_sa2400 *sa)
+{
+ u_int32_t agc;
+
+ agc = LSHIFT(25, SA2400_AGC_MAXGAIN_MASK);
+ agc |= LSHIFT(7, SA2400_AGC_BBPDELAY_MASK);
+ agc |= LSHIFT(15, SA2400_AGC_LNADELAY_MASK);
+ agc |= LSHIFT(27, SA2400_AGC_RXONDELAY_MASK);
+
+ return rtw_rfbus_write(&sa->sa_bus, RTW_RFCHIPID_PHILIPS, SA2400_AGC,
+ agc);
+}
+
+void
+rtw_sa2400_destroy(struct rtw_rf *rf)
+{
+ struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
+ memset(sa, 0, sizeof(*sa));
+ free(sa, M_DEVBUF);
+}
+
+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;
+}
+
+int
+rtw_sa2400_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
+ enum rtw_pwrstate power)
+{
+ struct rtw_sa2400 *sa = (struct rtw_sa2400 *)rf;
+ int rc;
+
+ if ((rc = rtw_sa2400_txpower(rf, opaque_txpower)) != 0)
+ return rc;
+
+ /* skip configuration if it's time to sleep or to power-down. */
+ if (power == RTW_SLEEP || power == RTW_OFF)
+ return rtw_sa2400_pwrstate(rf, power);
+
+ /* go to sleep for configuration */
+ 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;
+
+ /* enter Tx/Rx mode */
+ return rtw_sa2400_pwrstate(rf, power);
+}
+
+struct rtw_rf *
+rtw_sa2400_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int digphy)
+{
+ struct rtw_sa2400 *sa;
+ struct rtw_rfbus *bus;
+ struct rtw_rf *rf;
+ struct rtw_bbpset *bb;
+
+ sa = malloc(sizeof(*sa), M_DEVBUF, M_NOWAIT);
+ if (sa == NULL)
+ return NULL;
+ bzero(sa, sizeof(struct rtw_sa2400));
+
+ sa->sa_digphy = digphy;
+
+ rf = &sa->sa_rf;
+ bus = &sa->sa_bus;
+
+ rf->rf_init = rtw_sa2400_init;
+ rf->rf_destroy = rtw_sa2400_destroy;
+ rf->rf_txpower = rtw_sa2400_txpower;
+ rf->rf_tune = rtw_sa2400_tune;
+ rf->rf_pwrstate = rtw_sa2400_pwrstate;
+ bb = &rf->rf_bbpset;
+
+ /* XXX magic */
+ bb->bb_antatten = RTW_BBP_ANTATTEN_PHILIPS_MAGIC;
+ bb->bb_chestlim = 0x00;
+ bb->bb_chsqlim = 0xa0;
+ bb->bb_ifagcdet = 0x64;
+ bb->bb_ifagcini = 0x90;
+ bb->bb_ifagclimit = 0x1a;
+ bb->bb_lnadet = 0xe0;
+ bb->bb_sys1 = 0x98;
+ bb->bb_sys2 = 0x47;
+ bb->bb_sys3 = 0x90;
+ bb->bb_trl = 0x88;
+ bb->bb_txagc = 0x38;
+
+ bus->b_regs = regs;
+ bus->b_write = rf_write;
+
+ return &sa->sa_rf;
+}
+
+/* freq is in MHz */
+int
+rtw_max2820_tune(struct rtw_rf *rf, u_int freq)
+{
+ struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
+ struct rtw_rfbus *bus = &mx->mx_bus;
+
+ if (freq < 2400 || freq > 2499)
+ return -1;
+
+ return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM2820, MAX2820_CHANNEL,
+ LSHIFT(freq - 2400, MAX2820_CHANNEL_CF_MASK));
+}
+
+void
+rtw_max2820_destroy(struct rtw_rf *rf)
+{
+ struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
+ memset(mx, 0, sizeof(*mx));
+ free(mx, M_DEVBUF);
+}
+
+int
+rtw_max2820_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
+ enum rtw_pwrstate power)
+{
+ struct rtw_max2820 *mx = (struct rtw_max2820 *)rf;
+ struct rtw_rfbus *bus = &mx->mx_bus;
+ int rc;
+
+ if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM2820, MAX2820_TEST,
+ MAX2820_TEST_DEFAULT)) != 0)
+ return rc;
+
+ if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM2820, MAX2820_ENABLE,
+ MAX2820_ENABLE_DEFAULT)) != 0)
+ return rc;
+
+ /* skip configuration if it's time to sleep or to power-down. */
+ if ((rc = rtw_max2820_pwrstate(rf, power)) != 0)
+ return rc;
+ else if (power == RTW_OFF || power == RTW_SLEEP)
+ return 0;
+
+ if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM2820, MAX2820_SYNTH,
+ MAX2820_SYNTH_R_44MHZ)) != 0)
+ return rc;
+
+ if ((rc = rtw_max2820_tune(rf, freq)) != 0)
+ return rc;
+
+ /* XXX The MAX2820 datasheet indicates that 1C and 2C should not
+ * be changed from 7, however, the reference driver sets them
+ * to 4 and 1, respectively.
+ */
+ if ((rc = rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM2820, MAX2820_RECEIVE,
+ MAX2820_RECEIVE_DL_DEFAULT |
+ LSHIFT(4, MAX2820A_RECEIVE_1C_MASK) |
+ LSHIFT(1, MAX2820A_RECEIVE_2C_MASK))) != 0)
+ return rc;
+
+ return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM2820, MAX2820_TRANSMIT,
+ MAX2820_TRANSMIT_PA_DEFAULT);
+}
+
+int
+rtw_max2820_txpower(struct rtw_rf *rf, u_int8_t opaque_txpower)
+{
+ /* TBD */
+ return 0;
+}
+
+int
+rtw_max2820_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
+{
+ uint32_t enable;
+ struct rtw_max2820 *mx;
+ struct rtw_rfbus *bus;
+
+ mx = (struct rtw_max2820 *)rf;
+ bus = &mx->mx_bus;
+
+ switch (power) {
+ case RTW_OFF:
+ case RTW_SLEEP:
+ default:
+ enable = 0x0;
+ break;
+ case RTW_ON:
+ enable = MAX2820_ENABLE_DEFAULT;
+ break;
+ }
+ return rtw_rfbus_write(bus, RTW_RFCHIPID_MAXIM2820, MAX2820_ENABLE, enable);
+}
+
+struct rtw_rf *
+rtw_max2820_create(struct rtw_regs *regs, rtw_rf_write_t rf_write, int is_a)
+{
+ struct rtw_max2820 *mx;
+ struct rtw_rfbus *bus;
+ struct rtw_rf *rf;
+ struct rtw_bbpset *bb;
+
+ mx = malloc(sizeof(*mx), M_DEVBUF, M_NOWAIT);
+ if (mx == NULL)
+ return NULL;
+ bzero(mx, sizeof(struct rtw_max2820));
+
+ mx->mx_is_a = is_a;
+
+ rf = &mx->mx_rf;
+ bus = &mx->mx_bus;
+
+ rf->rf_init = rtw_max2820_init;
+ rf->rf_destroy = rtw_max2820_destroy;
+ rf->rf_txpower = rtw_max2820_txpower;
+ rf->rf_tune = rtw_max2820_tune;
+ rf->rf_pwrstate = rtw_max2820_pwrstate;
+ bb = &rf->rf_bbpset;
+
+ /* XXX magic */
+ bb->bb_antatten = RTW_BBP_ANTATTEN_MAXIM_MAGIC;
+ bb->bb_chestlim = 0;
+ bb->bb_chsqlim = 159;
+ bb->bb_ifagcdet = 100;
+ bb->bb_ifagcini = 144;
+ bb->bb_ifagclimit = 26;
+ bb->bb_lnadet = 248;
+ bb->bb_sys1 = 136;
+ bb->bb_sys2 = 71;
+ bb->bb_sys3 = 155;
+ bb->bb_trl = 136;
+ bb->bb_txagc = 8;
+
+ bus->b_regs = regs;
+ bus->b_write = rf_write;
+
+ return &mx->mx_rf;
+}
+
+int
+rtw_rtl8225_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
+{
+ return (0);
+}
+
+void
+rtw_rtl8225_destroy(struct rtw_rf *rf)
+{
+ struct rtw_rtl8225 *rt = (struct rtw_rtl8225 *)rf;
+ bzero(rt, sizeof(*rt));
+ free(rt, M_DEVBUF);
+}
+
+int
+rtw_rtl8225_init(struct rtw_rf *rf, u_int freq, u_int8_t opaque_txpower,
+ enum rtw_pwrstate power)
+{
+ return (0);
+}
+
+int
+rtw_rtl8225_txpower(struct rtw_rf *rf, u_int8_t opaque_txpower)
+{
+ return (0);
+}
+
+int
+rtw_rtl8225_tune(struct rtw_rf *rf, u_int freq)
+{
+ return (0);
+}
+
+struct rtw_rf *
+rtw_rtl8225_create(struct rtw_regs *regs, rtw_rf_write_t rf_write)
+{
+ struct rtw_rtl8225 *rt;
+ struct rtw_rfbus *bus;
+ struct rtw_rf *rf;
+ struct rtw_bbpset *bb;
+
+ rt = malloc(sizeof(*rt), M_DEVBUF, M_NOWAIT);
+ if (rt == NULL)
+ return NULL;
+ bzero(rt, sizeof(struct rtw_rtl8225));
+
+ rf = &rt->rt_rf;
+ bus = &rt->rt_bus;
+
+ rf->rf_init = rtw_rtl8225_init;
+ rf->rf_destroy = rtw_rtl8225_destroy;
+ rf->rf_txpower = rtw_rtl8225_txpower;
+ rf->rf_tune = rtw_rtl8225_tune;
+ rf->rf_pwrstate = rtw_rtl8225_pwrstate;
+ bb = &rf->rf_bbpset;
+
+ bus->b_regs = regs;
+ bus->b_write = rf_write;
+
+ return (&rt->rt_rf);
+}
+
+/* freq is in MHz */
+int
+rtw_phy_init(struct rtw_regs *regs, struct rtw_rf *rf, u_int8_t opaque_txpower,
+ u_int8_t cs_threshold, u_int freq, int antdiv, int dflantb,
+ enum rtw_pwrstate power)
+{
+ int rc;
+ RTW_DPRINTF(RTW_DEBUG_PHY,
+ ("%s: txpower %u csthresh %u freq %u antdiv %u dflantb %u "
+ "pwrstate %s\n", __func__, opaque_txpower, cs_threshold, freq,
+ antdiv, dflantb, rtw_pwrstate_string(power)));
+
+ /* XXX is this really necessary? */
+ if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0)
+ return rc;
+ if ((rc = rtw_bbp_preinit(regs, rf->rf_bbpset.bb_antatten, dflantb,
+ freq)) != 0)
+ return rc;
+ if ((rc = rtw_rf_tune(rf, freq)) != 0)
+ return rc;
+ /* initialize RF */
+ if ((rc = rtw_rf_init(rf, freq, opaque_txpower, power)) != 0)
+ return rc;
+#if 0 /* what is this redundant tx power setting here for? */
+ if ((rc = rtw_rf_txpower(rf, opaque_txpower)) != 0)
+ return rc;
+#endif
+ return rtw_bbp_init(regs, &rf->rf_bbpset, antdiv, dflantb,
+ cs_threshold, freq);
+}
+
+/*
+ * Generic PHY I/O functions
+ */
+
+
+u_int8_t
+rtw_bbp_read(struct rtw_regs *regs, u_int addr)
+{
+ KASSERT((addr & ~PRESHIFT(RTW_BB_ADDR_MASK)) == 0);
+ RTW_WRITE(regs, RTW_BB,
+ LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_RD_MASK | RTW_BB_WR_MASK);
+ delay(10); /* XXX */
+ RTW_WBR(regs, RTW_BB, RTW_BB);
+ return MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB), RTW_BB_RD_MASK);
+}
+
+int
+rtw_bbp_write(struct rtw_regs *regs, u_int addr, u_int val)
+{
+#define BBP_WRITE_ITERS 50
+#define BBP_WRITE_DELAY 1
+ int i;
+ u_int32_t wrbbp, rdbbp;
+
+ RTW_DPRINTF(RTW_DEBUG_PHYIO,
+ ("%s: bbp[%u] <- %u\n", __func__, addr, val));
+
+ KASSERT((addr & ~PRESHIFT(RTW_BB_ADDR_MASK)) == 0);
+ KASSERT((val & ~PRESHIFT(RTW_BB_WR_MASK)) == 0);
+
+ wrbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) | RTW_BB_WREN |
+ LSHIFT(val, RTW_BB_WR_MASK) | RTW_BB_RD_MASK,
+
+ rdbbp = LSHIFT(addr, RTW_BB_ADDR_MASK) |
+ RTW_BB_WR_MASK | RTW_BB_RD_MASK;
+
+ RTW_DPRINTF(RTW_DEBUG_PHYIO,
+ ("%s: rdbbp = %#08x, wrbbp = %#08x\n", __func__, rdbbp, wrbbp));
+
+ for (i = BBP_WRITE_ITERS; --i >= 0; ) {
+ RTW_RBW(regs, RTW_BB, RTW_BB);
+ RTW_WRITE(regs, RTW_BB, wrbbp);
+ RTW_SYNC(regs, RTW_BB, RTW_BB);
+ RTW_WRITE(regs, RTW_BB, rdbbp);
+ RTW_SYNC(regs, RTW_BB, RTW_BB);
+ delay(BBP_WRITE_DELAY); /* 1 microsecond */
+ if (MASK_AND_RSHIFT(RTW_READ(regs, RTW_BB),
+ RTW_BB_RD_MASK) == val) {
+ RTW_DPRINTF(RTW_DEBUG_PHYIO,
+ ("%s: finished in %dus\n", __func__,
+ BBP_WRITE_DELAY * (BBP_WRITE_ITERS - i)));
+ return 0;
+ }
+ delay(BBP_WRITE_DELAY); /* again */
+ }
+ printf("%s: timeout\n", __func__);
+ return -1;
+}
+
+/* Help rtw_rf_hostwrite bang bits to RF over 3-wire interface. */
+void
+rtw_rf_hostbangbits(struct rtw_regs *regs, u_int32_t bits, int lo_to_hi,
+ u_int nbits)
+{
+ int i;
+ u_int32_t mask, reg;
+
+ KASSERT(nbits <= 32);
+
+ RTW_DPRINTF(RTW_DEBUG_PHYIO,
+ ("%s: %u bits, %#08x, %s\n", __func__, nbits, bits,
+ (lo_to_hi) ? "lo to hi" : "hi to lo"));
+
+ reg = RTW8180_PHYCFG_HST;
+ RTW_WRITE(regs, RTW8180_PHYCFG, reg);
+ RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
+
+ if (lo_to_hi)
+ mask = 0x1;
+ else
+ mask = 1 << (nbits - 1);
+
+ for (i = 0; i < nbits; i++) {
+ RTW_DPRINTF(RTW_DEBUG_PHYBITIO,
+ ("%s: bits %#08x mask %#08x -> bit %#08x\n",
+ __func__, bits, mask, bits & mask));
+
+ if ((bits & mask) != 0)
+ reg |= RTW8180_PHYCFG_HST_DATA;
+ else
+ reg &= ~RTW8180_PHYCFG_HST_DATA;
+
+ reg |= RTW8180_PHYCFG_HST_CLK;
+ RTW_WRITE(regs, RTW8180_PHYCFG, reg);
+ RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
+
+ DELAY(2); /* arbitrary delay */
+
+ reg &= ~RTW8180_PHYCFG_HST_CLK;
+ RTW_WRITE(regs, RTW8180_PHYCFG, reg);
+ RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
+
+ if (lo_to_hi)
+ mask <<= 1;
+ else
+ mask >>= 1;
+ }
+
+ reg |= RTW8180_PHYCFG_HST_EN;
+ KASSERT((reg & RTW8180_PHYCFG_HST_CLK) == 0);
+ RTW_WRITE(regs, RTW8180_PHYCFG, reg);
+ RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
+}
+
+#if 0
+void
+rtw_rf_rtl8225_hostbangbits(struct rtw_regs *regs, u_int32_t bits, int lo_to_hi,
+ u_int nbits)
+{
+ int i;
+ u_int8_t page;
+ u_int16_t reg0, reg1, reg2;
+ u_int32_t mask;
+
+ /* enable page 0 */
+ page = RTW_READ8(regs, RTW_PSR);
+ RTW_WRITE8(regs, RTW_PSR, page & ~RTW_PSR_PSEN);
+
+ /* enable RF access */
+ reg0 = RTW_READ16(regs, RTW8185_RFPINSOUTPUT) &
+ RTW8185_RFPINSOUTPUT_MASK;
+ reg1 = RTW_READ16(regs, RTW8185_RFPINSENABLE);
+ RTW_WRITE16(regs, RTW8185_RFPINSENABLE,
+ RTW8185_RFPINSENABLE_ENABLE | reg0);
+ reg2 = RTW_READ16(regs, RTW8185_RFPINSSELECT);
+ RTW_WRITE16(regs, RTW8185_RFPINSSELECT,
+ RTW8185_RFPINSSELECT_ENABLE | reg1 /* XXX | SW_GPIO_CTL */);
+ DELAY(10);
+
+ RTW_WRITE16(regs, RTW8185_RFPINSOUTPUT, reg0);
+ DELAY(10);
+
+ if (lo_to_hi)
+ mask = 0x1;
+ else
+ mask = 1 << (nbits - 1);
+
+ for (i = 0; i < nbits; i++) {
+ RTW_DPRINTF(RTW_DEBUG_PHYBITIO,
+ ("%s: bits %#08x mask %#08x -> bit %#08x\n",
+ __func__, bits, mask, bits & mask));
+
+ if ((bits & mask) != 0)
+ reg |= RTW8180_PHYCFG_HST_DATA;
+ else
+ reg &= ~RTW8180_PHYCFG_HST_DATA;
+
+ reg |= RTW8180_PHYCFG_HST_CLK;
+ RTW_WRITE(regs, RTW8180_PHYCFG, reg);
+ RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
+
+ DELAY(2); /* arbitrary delay */
+
+ reg &= ~RTW8180_PHYCFG_HST_CLK;
+ RTW_WRITE(regs, RTW8180_PHYCFG, reg);
+ RTW_SYNC(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
+
+ if (lo_to_hi)
+ mask <<= 1;
+ else
+ mask >>= 1;
+ }
+
+ /* reset the page */
+ RTW_WRITE8(regs, RTW_PSR, page);
+}
+#endif
+
+/* Help rtw_rf_macwrite: tell MAC to bang bits to RF over the 3-wire
+ * interface.
+ */
+int
+rtw_rf_macbangbits(struct rtw_regs *regs, u_int32_t reg)
+{
+ int i;
+
+ RTW_DPRINTF(RTW_DEBUG_PHY, ("%s: %#08x\n", __func__, reg));
+
+ RTW_WRITE(regs, RTW8180_PHYCFG, RTW8180_PHYCFG_MAC_POLL | reg);
+
+ RTW_WBR(regs, RTW8180_PHYCFG, RTW8180_PHYCFG);
+
+ for (i = rtw_macbangbits_timeout; --i >= 0; delay(1)) {
+ if ((RTW_READ(regs, RTW8180_PHYCFG) & RTW8180_PHYCFG_MAC_POLL) == 0) {
+ RTW_DPRINTF(RTW_DEBUG_PHY,
+ ("%s: finished in %dus\n", __func__,
+ rtw_macbangbits_timeout - i));
+ return 0;
+ }
+ RTW_RBR(regs, RTW8180_PHYCFG, RTW8180_PHYCFG); /* XXX paranoia? */
+ }
+
+ printf("%s: RTW8180_PHYCFG_MAC_POLL still set.\n", __func__);
+ return -1;
+}
+
+u_int32_t
+rtw_grf5101_host_crypt(u_int addr, u_int32_t val)
+{
+ /* TBD */
+ return 0;
+}
+
+u_int32_t
+rtw_grf5101_mac_crypt(u_int addr, u_int32_t val)
+{
+ u_int32_t data_and_addr;
+#define EXTRACT_NIBBLE(d, which) (((d) >> (4 * (which))) & 0xf)
+ static u_int8_t caesar[16] = {0x0, 0x8, 0x4, 0xc,
+ 0x2, 0xa, 0x6, 0xe,
+ 0x1, 0x9, 0x5, 0xd,
+ 0x3, 0xb, 0x7, 0xf};
+
+ data_and_addr = caesar[EXTRACT_NIBBLE(val, 2)] |
+ (caesar[EXTRACT_NIBBLE(val, 1)] << 4) |
+ (caesar[EXTRACT_NIBBLE(val, 0)] << 8) |
+ (caesar[(addr >> 1) & 0xf] << 12) |
+ ((addr & 0x1) << 16) |
+ (caesar[EXTRACT_NIBBLE(val, 3)] << 24);
+ return LSHIFT(data_and_addr,
+ RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK|RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK);
+#undef EXTRACT_NIBBLE
+}
+
+const char *
+rtw_rfchipid_string(enum rtw_rfchipid rfchipid)
+{
+ switch (rfchipid) {
+ case RTW_RFCHIPID_MAXIM2820:
+ return "Maxim 2820";
+ case RTW_RFCHIPID_PHILIPS:
+ return "Philips SA2400";
+ case RTW_RFCHIPID_GCT:
+ return "GCT";
+ case RTW_RFCHIPID_RFMD2948:
+ return "RFMD 2948";
+ case RTW_RFCHIPID_INTERSIL:
+ return "Intersil";
+ case RTW_RFCHIPID_RTL8225:
+ return "Realtek RTL8225";
+ default:
+ return "unknown";
+ }
+}
+
+/* Bang bits over the 3-wire interface. */
+int
+rtw_rf_hostwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
+ u_int addr, u_int32_t val)
+{
+ u_int nbits;
+ int lo_to_hi;
+ u_int32_t bits;
+ void (*rf_bangbits)(struct rtw_regs *, u_int32_t, int, u_int) =
+ rtw_rf_hostbangbits;
+
+ RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__,
+ rtw_rfchipid_string(rfchipid), addr, val));
+
+ switch (rfchipid) {
+ case RTW_RFCHIPID_MAXIM2820:
+ nbits = 16;
+ lo_to_hi = 0;
+ bits = LSHIFT(val, MAX2820_TWI_DATA_MASK) |
+ LSHIFT(addr, MAX2820_TWI_ADDR_MASK);
+ break;
+ case RTW_RFCHIPID_PHILIPS:
+ KASSERT((addr & ~PRESHIFT(SA2400_TWI_ADDR_MASK)) == 0);
+ KASSERT((val & ~PRESHIFT(SA2400_TWI_DATA_MASK)) == 0);
+ bits = LSHIFT(val, SA2400_TWI_DATA_MASK) |
+ LSHIFT(addr, SA2400_TWI_ADDR_MASK) | SA2400_TWI_WREN;
+ nbits = 32;
+ lo_to_hi = 1;
+ break;
+ case RTW_RFCHIPID_GCT:
+ case RTW_RFCHIPID_RFMD2948:
+ KASSERT((addr & ~PRESHIFT(SI4126_TWI_ADDR_MASK)) == 0);
+ KASSERT((val & ~PRESHIFT(SI4126_TWI_DATA_MASK)) == 0);
+ if (rfchipid == RTW_RFCHIPID_GCT)
+ bits = rtw_grf5101_host_crypt(addr, val);
+ else {
+ bits = LSHIFT(val, SI4126_TWI_DATA_MASK) |
+ LSHIFT(addr, SI4126_TWI_ADDR_MASK);
+ }
+ nbits = 22;
+ lo_to_hi = 0;
+ break;
+ case RTW_RFCHIPID_RTL8225:
+ nbits = 16;
+ lo_to_hi = 0;
+ bits = LSHIFT(val, RTL8225_TWI_DATA_MASK) |
+ LSHIFT(addr, RTL8225_TWI_ADDR_MASK);
+
+ /* the RTL8225 uses a slightly modified RF interface */
+ rf_bangbits = rtw_rf_hostbangbits;
+ break;
+ case RTW_RFCHIPID_INTERSIL:
+ default:
+ printf("%s: unknown rfchipid %d\n", __func__, rfchipid);
+ return -1;
+ }
+
+ (*rf_bangbits)(regs, bits, lo_to_hi, nbits);
+
+ return 0;
+}
+
+u_int32_t
+rtw_maxim_swizzle(u_int addr, u_int32_t val)
+{
+ u_int32_t hidata, lodata;
+
+ KASSERT((val & ~(RTW_MAXIM_LODATA_MASK|RTW_MAXIM_HIDATA_MASK)) == 0);
+ lodata = MASK_AND_RSHIFT(val, RTW_MAXIM_LODATA_MASK);
+ hidata = MASK_AND_RSHIFT(val, RTW_MAXIM_HIDATA_MASK);
+ return LSHIFT(lodata, RTW8180_PHYCFG_MAC_MAXIM_LODATA_MASK) |
+ LSHIFT(hidata, RTW8180_PHYCFG_MAC_MAXIM_HIDATA_MASK) |
+ LSHIFT(addr, RTW8180_PHYCFG_MAC_MAXIM_ADDR_MASK);
+}
+
+/* Tell the MAC what to bang over the 3-wire interface. */
+int
+rtw_rf_macwrite(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
+ u_int addr, u_int32_t val)
+{
+ u_int32_t reg;
+
+ RTW_DPRINTF(RTW_DEBUG_PHYIO, ("%s: %s[%u] <- %#08x\n", __func__,
+ rtw_rfchipid_string(rfchipid), addr, val));
+
+ switch (rfchipid) {
+ case RTW_RFCHIPID_GCT:
+ reg = rtw_grf5101_mac_crypt(addr, val);
+ break;
+ case RTW_RFCHIPID_MAXIM2820:
+ reg = rtw_maxim_swizzle(addr, val);
+ break;
+ default: /* XXX */
+ case RTW_RFCHIPID_PHILIPS:
+ KASSERT(
+ (addr & ~PRESHIFT(RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK)) == 0);
+ KASSERT(
+ (val & ~PRESHIFT(RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK)) == 0);
+
+ reg = LSHIFT(addr, RTW8180_PHYCFG_MAC_PHILIPS_ADDR_MASK) |
+ LSHIFT(val, RTW8180_PHYCFG_MAC_PHILIPS_DATA_MASK);
+ }
+
+ switch (rfchipid) {
+ case RTW_RFCHIPID_GCT:
+ case RTW_RFCHIPID_MAXIM2820:
+ case RTW_RFCHIPID_RFMD2948:
+ reg |= RTW8180_PHYCFG_MAC_RFTYPE_RFMD;
+ break;
+ case RTW_RFCHIPID_INTERSIL:
+ reg |= RTW8180_PHYCFG_MAC_RFTYPE_INTERSIL;
+ break;
+ case RTW_RFCHIPID_PHILIPS:
+ reg |= RTW8180_PHYCFG_MAC_RFTYPE_PHILIPS;
+ break;
+ default:
+ printf("%s: unknown rfchipid %d\n", __func__, rfchipid);
+ return -1;
+ }
+
+ return rtw_rf_macbangbits(regs, reg);
+}
diff --git a/sys/dev/ic/rtwvar.h b/sys/dev/ic/rtwvar.h
index cb3b6e62385..ba2a507d824 100644
--- a/sys/dev/ic/rtwvar.h
+++ b/sys/dev/ic/rtwvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtwvar.h,v 1.9 2005/05/26 05:41:45 jsg Exp $ */
+/* $OpenBSD: rtwvar.h,v 1.10 2005/05/29 02:54:51 reyk Exp $ */
/* $NetBSD: rtwvar.h,v 1.10 2004/12/26 22:37:57 mycroft Exp $ */
/*-
* Copyright (c) 2004, 2005 David Young. All rights reserved.
@@ -75,6 +75,18 @@ extern int rtw_debug;
#define DPRINTF(__sc, __flags, __x)
#endif /* RTW_DEBUG */
+#define KASSERT2(__cond, __msg) \
+ do { \
+ if (!(__cond)) \
+ panic __msg ; \
+ } while (0)
+
+#define NEXT_ATTACH_STATE(sc, state) do { \
+ DPRINTF(sc, RTW_DEBUG_ATTACH, \
+ ("%s: attach state %s\n", __func__, #state)); \
+ sc->sc_attach_state = state; \
+} while (0)
+
enum rtw_locale {
RTW_LOCALE_USA = 0,
RTW_LOCALE_EUROPE,
@@ -85,10 +97,14 @@ enum rtw_locale {
enum rtw_rfchipid {
RTW_RFCHIPID_RESERVED = 0,
RTW_RFCHIPID_INTERSIL = 1,
- RTW_RFCHIPID_RFMD = 2,
+ RTW_RFCHIPID_RFMD2948 = 2,
RTW_RFCHIPID_PHILIPS = 3,
- RTW_RFCHIPID_MAXIM = 4,
- RTW_RFCHIPID_GCT = 5
+ RTW_RFCHIPID_MAXIM2820 = 4,
+ RTW_RFCHIPID_GCT = 5,
+ RTW_RFCHIPID_RFMD2958 = 6,
+ RTW_RFCHIPID_MAXIM2822 = 7,
+ RTW_RFCHIPID_MAXIM2825 = 8,
+ RTW_RFCHIPID_RTL8225 = 9
};
/* sc_flags */
@@ -99,6 +115,7 @@ enum rtw_rfchipid {
#define RTW_F_9356SROM 0x00000020 /* 93c56 SROM */
#define RTW_F_SLEEP 0x00000040 /* chip is asleep */
#define RTW_F_INVALID 0x00000080 /* chip is absent */
+#define RTW_F_RTL8185 0x00000100 /* RTL8185 or newer */
/* all PHY flags */
#define RTW_F_ALLPHY (RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV)
@@ -344,6 +361,11 @@ struct rtw_sa2400 {
int sa_digphy; /* 1: digital PHY */
};
+struct rtw_rtl8225 {
+ struct rtw_rf rt_rf;
+ struct rtw_rfbus rt_bus;
+};
+
typedef void (*rtw_pwrstate_t)(struct rtw_regs *, enum rtw_pwrstate, int, int);
union rtw_keys {
@@ -443,7 +465,7 @@ struct rtw_softc {
int sc_txkey;
struct ifqueue sc_beaconq;
struct rtw_led_state sc_led_state;
- int sc_hwverid;
+ u_int sc_hwverid;
};
#define sc_if sc_ic.ic_if