rtw.c revision 0dc2366f7b9f9f36e10909b1e95edbf2a261c2ac
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Use is subject to license terms.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Copyright (c) 2004 David Young. All rights reserved.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * This code was written by David Young.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Redistribution and use in source and binary forms, with or without
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * modification, are permitted provided that the following conditions
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * are met:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * 1. Redistributions of source code must retain the above copyright
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * notice, this list of conditions and the following disclaimer.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * 2. Redistributions in binary form must reproduce the above copyright
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * notice, this list of conditions and the following disclaimer in the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * documentation and/or other materials provided with the distribution.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * 3. Neither the name of the author nor the names of any co-contributors
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * may be used to endorse or promote products derived from this software
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * without specific prior written permission.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * THIS SOFTWARE IS PROVIDED BY David Young ``AS IS'' AND ANY
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL David
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Young BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * OF SUCH DAMAGE.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * PIO access attributes for registers
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * DMA access attributes for descriptors and bufs: NOT to be byte swapped.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Describes the chip's DMA engine
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0 /* dma_attr_flags */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0 /* dma_attr_flags */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0 /* dma_attr_flags */
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Listatic void rtw_stop(void *);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Listatic int rtw_attach(dev_info_t *, ddi_attach_cmd_t);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Listatic int rtw_detach(dev_info_t *, ddi_detach_cmd_t);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int rtw_m_start(void *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void rtw_m_stop(void *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int rtw_m_multicst(void *, boolean_t, const uint8_t *);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Listatic int rtw_m_setprop(void *, const char *, mac_prop_id_t,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li uint_t, const void *);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Listatic int rtw_m_getprop(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void rtw_m_propinfo(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
a72f7ea693101cc48bafbb4db6bb437d828011c4qlDDI_DEFINE_STREAM_OPS(rtw_dev_ops, nulldev, nulldev, rtw_attach, rtw_detach,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &mod_driverops, /* Type of module. This one is a driver */
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li "realtek 8180L driver 1.7", /* short description */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * RTW_DEBUG_ATTACH | RTW_DEBUG_TUNE |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * RTW_DEBUG_ACCESS | RTW_DEBUG_INIT | RTW_DEBUG_PKTFILT |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * RTW_DEBUG_RECV | RTW_DEBUG_XMIT | RTW_DEBUG_80211 | RTW_DEBUG_INTR |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * RTW_DEBUG_PKTDUMP;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * Supported rates for 802.11b modes (in 500Kbps unit).
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Listatic const struct ieee80211_rateset rtw_rateset_11b =
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (status != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (status == 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_REGDUMP, "%s: %s\n", dvname, where);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 16-bit registers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 8-bit registers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif /* DEBUG */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic const char *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (access) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("none");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("config");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("anaparm");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("unknown");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Enable registers, switch register banks.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * requires rtw_config0123_enable(, 1)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * requires rtw_anaparm_enable(, 1)
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_access(struct rtw_regs *regs, enum rtw_access access)
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_chip_reset1(struct rtw_regs *regs, const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < 1000; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_inten = RTW_INTR_RX | RTW_INTR_TX | RTW_INTR_IOERROR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX necessary? */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_recall_eeprom(struct rtw_regs *regs, const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* wait 25ms for completion */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < 250; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rc != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql command = command | (mode<<RTW_EPROM_CMD_OPERATING_MODE_SHIFT);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_srom_defaults(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold,
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_srom_parse(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql enum rtw_rfchipid *rfchipid, uint32_t *rcr, enum rtw_locale *locale,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: SROM version %d.%d", dvname,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "with defaults\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_srom_defaults(sr, flags, cs_threshold, rfchipid, rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < IEEE80211_ADDR_LEN; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW_CONFIG2_ANT) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * to be reversed.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (*rfchipid) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_PHILIPS: /* this combo seen in the wild */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * this is the same front-end as an atw(4)!
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "SYN: Silicon Labs Si4126";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_GL_MASK) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Returns -1 on failure.
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_srom_read(struct rtw_regs *regs, uint32_t flags, struct rtw_srom *sr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c56 SROM\n", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c46 SROM\n", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * RTL8180 has a single 8-bit register for controlling the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * 93cx6 SROM. There is no "ready" bit. The RTL8180
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * input/output sense is the reverse of read_seeprom's.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * make read_seeprom enter EEPROM read/write mode
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * TBD bus barriers
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * end EEPROM read/write mode
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif /* DEBUG */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_rfprog(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *method;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (*_chans)[_chan].ich_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK;\
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (locale) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default: /* 10-11 allowed by most countries */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: Geographic Location %s\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li /* IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP */
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li ic->ic_sup_rates[IEEE80211_MODE_11B] = rtw_rateset_11b;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *addr, *(addr+1), *(addr+2), *(addr+3), *(addr+4), *(addr+5));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rxdesc_init(rtw_softc_t *rsc, struct rtw_rxbuf *rbf, int idx, int is_last)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync the mbuf */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync the descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* request stop DMA; wait for packets to stop transmitting. */
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ALL) != 0; active++)
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: %s 0x%02x\n", __func__,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* The receive engine will always start at RDSAR. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Allocate an area of memory and a DMA handle for accessing it
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_alloc_dma_mem(dev_info_t *devinfo, ddi_dma_attr_t *dma_attr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql size_t memsize, ddi_device_acc_attr_t *attr_p, uint_t alloc_flags,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Allocate handle
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Allocate memory
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Bind the two together
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Free one allocated area of DMAable memory
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Free TX DMA buffer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Free RX DMA buffer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < RTW_RXQLEN; j++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i, j, err;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* DMA buffer size for each TX/RX packet */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_dmabuf_size = roundup(sizeof (struct ieee80211_frame) + 0x100 +
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_MTU + IEEE80211_CRC_LEN + sizeof (struct ieee80211_llc) +
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_DMA, "p[%d]=%x, v[%d]=%x", i, ptx[i],
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txbuf),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txbuf),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* virtual address of the first descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* allocate data structures to describe TX DMA buffers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = (struct rtw_txbuf *)kmem_zalloc(buflen, KM_SLEEP);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* alloc DMA memory */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* virtual address of the first descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* allocate data structures to describe RX DMA buffers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxbf = (struct rtw_rxbuf *)kmem_zalloc(buflen, KM_SLEEP);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* alloc DMA memory */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RDSAR, RTW_RING_BASE(phybaseaddr, hd_rx));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_TLPDA, RTW_RING_BASE(phybaseaddr, hd_txlo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_TNPDA, RTW_RING_BASE(phybaseaddr, hd_txmd));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_THPDA, RTW_RING_BASE(phybaseaddr, hd_txhi));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_TBDA, RTW_RING_BASE(phybaseaddr, hd_bcn));
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t phybaseaddr, ptx[RTW_NTXPRI], baddr_desc, taddr_desc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync tx desc and tx buf */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < rtw_qlen[i]; j++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync rx desc and rx buf */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < RTW_RXQLEN; j++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlconst char *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("on");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("sleep");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("off");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("unknown");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * XXX For Maxim, I am using the RFMD settings gleaned from the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * reference driver, plus a magic Maxim "ON" value that comes from
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * the Realtek document "Windows PG for Rtl8180."
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * XXX I am using the RFMD settings gleaned from the reference
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * driver. They agree
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX guess */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_pwrstate0(rtw_softc_t *rsc, enum rtw_pwrstate power, int before_rf,
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_pwrstate_string(rsc->sc_pwrstate), rtw_pwrstate_string(power));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_pwrstate0(rsc, power, 1, rsc->sc_flags & RTW_F_DIGPHY);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_pwrstate0(rsc, power, 0, rsc->sc_flags & RTW_F_DIGPHY);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD set LEDs */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rc == 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* turn off PHY */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_enable != NULL && (*rsc->sc_enable)(rsc) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_nettype(rtw_softc_t *rsc, enum ieee80211_opmode opmode)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* I'm guessing that MSR is protected as CONFIG[0123] are. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql msr = RTW_READ8(&rsc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (opmode) {
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX might be necessary to stop Rx/Tx engines while setting filters */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* MAC auto-reset PHY (huh?) */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* receive broadcasts in our BSS */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX accept all broadcast if scanning */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* set short/long retry limits */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= LSHIFT(0x4, RTW_TCR_SRL_MASK) | LSHIFT(0x4, RTW_TCR_LRL_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rc != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: chan == IEEE80211_CHAN_ANY\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX condition on powersaving */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_TUNE, "%s: channel %d freq %d flags 0x%04x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic struct rtw_rf *
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rf_attach(rtw_softc_t *rsc, enum rtw_rfchipid rfchipid, int digphy)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX RFMD has no RF constructor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Revision C and later use a different PHY delay setting than
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * revisions A and B.
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments in:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * paylen: payload length (no FCS, no WEP header)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * hdrlen: header length
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * rate: MSDU speed, units 500kb/s
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * flags: IEEE80211_F_SHPREAMBLE (use short preamble),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * IEEE80211_F_SHSLOT (use short slot length)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments out:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * d: 802.11 Duration field for RTS,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * 802.11 Duration field for data frame,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * PLCP Length for data frame,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * residual octets at end of data slot
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_compute_duration1(int len, int use_ack, uint32_t flags, int rate,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * DATA reserves medium for SIFS | ACK
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * XXXMYC: no ACK on multicast/broadcast or control packets
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (remainder != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (rate) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments in:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * wh: 802.11 header
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * paylen: payload length (no FCS, no WEP header)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * rate: MSDU speed, units 500kb/s
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * fraglen: fragment length, set to maximum (or higher) for no
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * fragmentation
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * flags: IEEE80211_F_PRIVACY (hardware adds WEP),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * IEEE80211_F_SHPREAMBLE (use short preamble),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * IEEE80211_F_SHSLOT (use short slot length)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments out:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * of first/only fragment
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * of first/only fragment
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t flags, int fraglen, int rate, struct rtw_ieee80211_duration *d0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* don't think about addr4 here */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else /* full-length "tail" fragment */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rtw_compute_duration1(lastlen + hdrlen, ack, flags,
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_assembly_80211(rtw_softc_t *rsc, struct rtw_txbuf *bf,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* ieee80211_crypto_encap() needs a single mblk */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (k == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------begin--------");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211_dump_pkt((uint8_t *)(mp0->b_rptr), pktlen, 0, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "-----------send------end--------");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV); */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* setup descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (ic->ic_bss->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX do real rate control */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: rate = %d", __func__, rate);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (rate) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX >= ? Compare after fragmentation? */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: duration=%x, ctl1=%x", __func__,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_ctl0 |= RTW_TXCTL0_OWN | RTW_TXCTL0_LS | RTW_TXCTL0_FS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "descriptor: order = %d, phy_addr=%x, ctl0=%x,"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: no tx buf\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* assemble 802.11 frame here */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ret != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_join_bss(rtw_softc_t *rsc, uint8_t *bssid, uint16_t intval0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < IEEE80211_ADDR_LEN; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD WEP */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* RTW_WRITE8(regs, RTW_SCR, 0); */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Set the starting transmit rate for a node.
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rate_ctl_start(rtw_softc_t *rsc, struct ieee80211_node *in)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * No fixed rate is requested. For 11b start with
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * the highest negotiated rate; otherwise, for 11g
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * and 11a, we start "in the middle" at 24Mb or 36Mb.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Scan the negotiated rate set to find the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * closest rate.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* NB: the rate set is assumed sorted */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * A fixed rate is to be used; We know the rate is
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * there because the rate set is checked when the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * station associates.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* NB: the rate set is assumed sorted */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Reset the rate control state for each 802.11 state transition.
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rate_ctl_reset(rtw_softc_t *rsc, enum ieee80211_state state)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Reset local xmit state; this is really only
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * meaningful when operating in station mode.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Examine and potentially adjust the transmit rate.
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li enough = (rsc->sc_tx_ok + rsc->sc_tx_err) >= 600? 1 : 0;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li /* err ratio is high -> down */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (mod) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (nrate > 0) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_tx_ok = rsc->sc_tx_err = rsc->sc_tx_retr = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_new_state(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw_new_state: ostate:0x%x, nstate:0x%x, opmode:0x%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (nstate) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_INIT\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_SCAN\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw_new_state: sta\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Invoke the parent method to complete the work.
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * ratetbl[4] = {2, 4, 11, 22};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV, "%s rtw_intr_rx: enter ic_state=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_RXQLEN; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* htsfth = ds->rd_tsfth; */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV, "%s: stat=%x\n", __func__, hstat);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* still belongs to NIC */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (n > 1) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw: DMA error/FIFO overflow %08x, "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rx descriptor %d\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* CRC is included with the packet; trim it off. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* len -= IEEE80211_CRC_LEN; */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* if bad flags, skip descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw too many rx segments\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * TBD find out each front-end's LNA gain in the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * front-end's units
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ); */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* deal with the frame itself here */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) ieee80211_input(ic, mp, ic->ic_bss, rssi, htsftl);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV, "%s: next = %d\n", __func__, next);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "rtw_ring_recycling: enter ic_state=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql idx = (rsc->hw_go - rsc->hw_start) / sizeof (struct rtw_txdesc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s rtw_ring_recycling: stat=%x, pri=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "TX err @%d, o %d, retry[%d], isr[0x%x], cnt %d\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw_ring_recycling: nfree[%d]=%d\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
020c47705d28102a8df83a43ddf08e34dde21f22ql /* LINTED E_BAD_PTR_CAST_ALIGN */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (isr == 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif /* DEBUG */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * quiesce(9E) entry point.
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * This function is called when the system is single-threaded at high
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * PIL with preemption disabled. Therefore, this function must not be
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * DDI_FAILURE indicates an error condition and should almost never happen.
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(dip));
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * callback functions for /get/set properties
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Lirtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (ic->ic_des_esslen && (rsc->sc_invalid == 0)) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Lirtw_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li err = ieee80211_getprop(&rsc->sc_ic, pr_name, wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerrtw_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ieee80211_propinfo(&rsc->sc_ic, pr_name, wldp_pr_num, prh);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Lirtw_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (ic->ic_des_esslen && (rsc->sc_invalid == 0)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (stat) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_destroy(&rsc->sc_txq[RTW_NTXPRI - 1 - i].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (cmd) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "Unable to alloc softstate\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_regs_map_setup(devinfo, 0, (caddr_t *)&rsc->sc_cfg_base, 0, 0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "ddi_regs_map_setup() failed");
020c47705d28102a8df83a43ddf08e34dde21f22ql (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_VENID));
020c47705d28102a8df83a43ddf08e34dde21f22ql (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_DEVID));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): vendor 0x%x, "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "device id 0x%x, cache size %d\n", vendor_id, device_id, csz);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Enable response to memory space accesses,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * and enabe bus master.
020c47705d28102a8df83a43ddf08e34dde21f22ql (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_COMM), command);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_regs_map_setup(devinfo, 2, (caddr_t *)&rsc->sc_regs.r_base,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "ddi_regs_map_setup() failed");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: r_base=%x, r_handle=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Stop the transmit and receive processes. First stop DMA,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * then disable receiver and transmitter.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Reset the chip to a known state. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "failed to reset\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_srom_read(&rsc->sc_regs, rsc->sc_flags, &rsc->sc_srom,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw") != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "failed to read srom\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_srom_parse(&rsc->sc_srom, &rsc->sc_flags, &rsc->sc_csthr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw") != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql " malformed serial ROM\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ((rsc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "rtw: rtw_attach(): could not attach RF\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_phydelay = rtw_check_phydelay(&rsc->sc_regs, rsc->sc_rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_init_channels(rsc->sc_locale, &rsc->sc_ic.ic_sup_channels,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw") != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "Can not get iblock cookie for INT\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_init(&rsc->sc_genlock, NULL, MUTEX_DRIVER, rsc->sc_iblock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_init(&rsc->sc_txq[i].txbuf_lock, NULL, MUTEX_DRIVER,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_init(&rsc->rxbuf_lock, NULL, MUTEX_DRIVER, rsc->sc_iblock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_init(&rsc->sc_txlock, NULL, MUTEX_DRIVER, rsc->sc_iblock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ddi_add_intr(devinfo, 0, &rsc->sc_iblock, NULL, rtw_intr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "Can not add intr for rtw driver\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Provide initial settings for the WiFi plugin; whenever this
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * information changes, we need to call mac_plugindata_update()
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "MAC version mismatch\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Create minor node of type DDI_NT_NET_WIFI */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "WARN: rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (cmd) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1);
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China if (mac_disable(rsc->sc_ic.ic_mach) != 0)
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* free intterrupt resources */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Unregister from the MAC layer subsystem