diff options
author | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-05-29 02:54:52 +0000 |
---|---|---|
committer | Reyk Floeter <reyk@cvs.openbsd.org> | 2005-05-29 02:54:52 +0000 |
commit | cbfea9d11d88792f68883d3abfd48c7176572d1f (patch) | |
tree | eab0c237b0d1a5a09267b2bbe3772b4e71def479 /sys/dev/ic | |
parent | 058ac3249a7c2b4d78bd54d65f4677cb22485125 (diff) |
cleanup rtw
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/rtl8225reg.h | 28 | ||||
-rw-r--r-- | sys/dev/ic/rtw.c | 1447 | ||||
-rw-r--r-- | sys/dev/ic/rtwvar.h | 32 |
3 files changed, 1321 insertions, 186 deletions
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 |