a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Use is subject to license terms.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Copyright (c) 2004 David Young. All rights reserved.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * This code was written by David Young.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
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 *
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 */
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li#include <sys/sysmacros.h>
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include <sys/pci.h>
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li#include <sys/stat.h>
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include <sys/strsubr.h>
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li#include <sys/strsun.h>
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li#include <sys/mac_provider.h>
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include <sys/mac_wifi.h>
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li#include <sys/net80211.h>
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer#include <sys/byteorder.h>
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include "rtwreg.h"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include "rtwvar.h"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include "smc93cx6var.h"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include "rtwphy.h"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#include "rtwphyio.h"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * PIO access attributes for registers
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic ddi_device_acc_attr_t rtw_reg_accattr = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DEVICE_ATTR_V0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_STRUCTURE_LE_ACC,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_STRICTORDER_ACC,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DEFAULT_ACC
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * DMA access attributes for descriptors and bufs: NOT to be byte swapped.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic ddi_device_acc_attr_t rtw_desc_accattr = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DEVICE_ATTR_V0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_NEVERSWAP_ACC,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_STRICTORDER_ACC,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DEFAULT_ACC
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic ddi_device_acc_attr_t rtw_buf_accattr = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DEVICE_ATTR_V0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_NEVERSWAP_ACC,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_STRICTORDER_ACC,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DEFAULT_ACC
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Describes the chip's DMA engine
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic ddi_dma_attr_t dma_attr_desc = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DMA_ATTR_V0, /* dma_attr version */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x0000000000000000ull, /* dma_attr_addr_lo */
020c47705d28102a8df83a43ddf08e34dde21f22ql 0xFFFFFFFF, /* dma_attr_addr_hi */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000000FFFFFFFFull, /* dma_attr_count_max */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x100, /* dma_attr_align */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0xFFFFFFFF, /* dma_attr_burstsizes */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000001, /* dma_attr_minxfer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000000FFFFull, /* dma_attr_maxxfer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 1, /* dma_attr_sgllen */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 1, /* dma_attr_granular */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0 /* dma_attr_flags */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic ddi_dma_attr_t dma_attr_rxbuf = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DMA_ATTR_V0, /* dma_attr version */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x0000000000000000ull, /* dma_attr_addr_lo */
020c47705d28102a8df83a43ddf08e34dde21f22ql 0xFFFFFFFF, /* dma_attr_addr_hi */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000000FFFFFFFFull, /* dma_attr_count_max */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (uint32_t)16, /* dma_attr_align */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0xFFFFFFFF, /* dma_attr_burstsizes */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000001, /* dma_attr_minxfer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000000FFFFull, /* dma_attr_maxxfer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 1, /* dma_attr_sgllen */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 1, /* dma_attr_granular */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0 /* dma_attr_flags */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic ddi_dma_attr_t dma_attr_txbuf = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DMA_ATTR_V0, /* dma_attr version */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x0000000000000000ull, /* dma_attr_addr_lo */
020c47705d28102a8df83a43ddf08e34dde21f22ql 0xFFFFFFFF, /* dma_attr_addr_hi */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000000FFFFFFFFull, /* dma_attr_count_max */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (uint32_t)16, /* dma_attr_align */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0xFFFFFFFF, /* dma_attr_burstsizes */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000001, /* dma_attr_minxfer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0x00000000FFFFull, /* dma_attr_maxxfer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0xFFFFFFFFFFFFFFFFull, /* dma_attr_seg */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 1, /* dma_attr_sgllen */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 1, /* dma_attr_granular */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0 /* dma_attr_flags */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void *rtw_soft_state_p = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
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);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Listatic int rtw_quiesce(dev_info_t *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int rtw_m_stat(void *, uint_t, uint64_t *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int rtw_m_start(void *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void rtw_m_stop(void *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int rtw_m_promisc(void *, boolean_t);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int rtw_m_multicst(void *, boolean_t, const uint8_t *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int rtw_m_unicst(void *, const uint8_t *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic mblk_t *rtw_m_tx(void *, mblk_t *);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void rtw_m_ioctl(void *, queue_t *, mblk_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 Iyer uint_t, void *);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void rtw_m_propinfo(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic mac_callbacks_t rtw_m_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_m_stat,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_m_start,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_m_stop,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_m_promisc,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_m_multicst,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_m_unicst,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rtw_m_ioctl,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li NULL, /* mc_getcapab */
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li NULL,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li NULL,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rtw_m_setprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer rtw_m_getprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer rtw_m_propinfo
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlDDI_DEFINE_STREAM_OPS(rtw_dev_ops, nulldev, nulldev, rtw_attach, rtw_detach,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li nodev, NULL, D_MP, NULL, rtw_quiesce);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic struct modldrv rtw_modldrv = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &mod_driverops, /* Type of module. This one is a driver */
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li "realtek 8180L driver 1.7", /* short description */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rtw_dev_ops /* driver specific ops */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic struct modlinkage modlinkage = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql MODREV_1, (void *)&rtw_modldrv, NULL
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic uint32_t rtw_qlen[RTW_NTXPRI] = {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_TXQLENLO,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_TXQLENMD,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_TXQLENHI,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_TXQLENBCN
a72f7ea693101cc48bafbb4db6bb437d828011c4ql};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
020c47705d28102a8df83a43ddf08e34dde21f22qluint32_t rtw_dbg_flags = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
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;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li/*
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * Supported rates for 802.11b modes (in 500Kbps unit).
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li */
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Listatic const struct ieee80211_rateset rtw_rateset_11b =
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li { 4, { 2, 4, 11, 22 } };
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
a72f7ea693101cc48bafbb4db6bb437d828011c4qlint
a72f7ea693101cc48bafbb4db6bb437d828011c4ql_info(struct modinfo *modinfop)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (mod_info(&modlinkage, modinfop));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlint
a72f7ea693101cc48bafbb4db6bb437d828011c4ql_init(void)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int status;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql status = ddi_soft_state_init(&rtw_soft_state_p,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (rtw_softc_t), 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (status != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (status);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac_init_ops(&rtw_dev_ops, "rtw");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql status = mod_install(&modlinkage);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (status != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac_fini_ops(&rtw_dev_ops);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_soft_state_fini(&rtw_soft_state_p);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (status);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlint
a72f7ea693101cc48bafbb4db6bb437d828011c4ql_fini(void)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int status;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql status = mod_remove(&modlinkage);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (status == 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac_fini_ops(&rtw_dev_ops);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_soft_state_fini(&rtw_soft_state_p);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (status);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_dbg(uint32_t dbg_flags, const int8_t *fmt, ...)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql va_list args;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (dbg_flags & rtw_dbg_flags) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql va_start(args, fmt);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql vcmn_err(CE_CONT, fmt, args);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql va_end(args);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#ifdef DEBUG
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_print_regs(struct rtw_regs *regs, const char *dvname, const char *where)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define PRINTREG32(sc, reg) \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_REGDUMP, \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: reg[ " #reg " / %03x ] = %08x\n", \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dvname, reg, RTW_READ(regs, reg))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define PRINTREG16(sc, reg) \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_REGDUMP, \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: reg[ " #reg " / %03x ] = %04x\n", \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dvname, reg, RTW_READ16(regs, reg))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define PRINTREG8(sc, reg) \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_REGDUMP, \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: reg[ " #reg " / %03x ] = %02x\n", \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dvname, reg, RTW_READ8(regs, reg))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_REGDUMP, "%s: %s\n", dvname, where);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_IDR0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_IDR1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_MAR0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_MAR1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_TSFTRL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_TSFTRH);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_TLPDA);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_TNPDA);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_THPDA);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_TCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_RCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_TINT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_TBDA);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_BB);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_PHYCFG);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP0L);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP0H);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP1L);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP1H);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP2LL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP2LH);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP2HL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP2HH);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP3LL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP3LH);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP3HL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP3HH);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP4LL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP4LH);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP4HL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_WAKEUP4HH);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_DK0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_DK1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_DK2);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_DK3);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_RETRYCTR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_RDSAR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_FER);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_FEMR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_FPSR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_FFER);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 16-bit registers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_BRSR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_IMR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_ISR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_BCNITV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_ATIMWND);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_BINTRITV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_ATIMTRITV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_CRC16ERR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_CRC0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_CRC1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_CRC2);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_CRC3);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_CRC4);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_CWR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 8-bit registers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CONFIG0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CONFIG1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CONFIG2);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_MSR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CONFIG3);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CONFIG4);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_TESTR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_PSR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_SCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_PHYDELAY);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CRCOUNT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_PHYADDR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_PHYDATAW);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_PHYDATAR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_CONFIG5);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG8(regs, RTW_TPPOLL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG16(regs, RTW_BSSID16);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTREG32(regs, RTW_BSSID32);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#undef PRINTREG32
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#undef PRINTREG16
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#undef PRINTREG8
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif /* DEBUG */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic const char *
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_access_string(enum rtw_access access)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (access) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_NONE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("none");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_CONFIG:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("config");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_ANAPARM:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("anaparm");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("unknown");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Enable registers, switch register banks.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_config0123_enable(struct rtw_regs *regs, int enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t ecr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr = RTW_READ8(regs, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr &= ~(RTW_9346CR_EEM_MASK | RTW_9346CR_EECS | RTW_9346CR_EESK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr |= RTW_9346CR_EEM_CONFIG;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBW(regs, RTW_9346CR, MAX(RTW_CONFIG0, RTW_CONFIG3));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr |= RTW_9346CR_EEM_NORMAL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_9346CR, ecr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_9346CR, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * requires rtw_config0123_enable(, 1)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_anaparm_enable(struct rtw_regs *regs, int enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t cfg3;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg3 = RTW_READ8(regs, RTW_CONFIG3);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg3 |= RTW_CONFIG3_CLKRUNEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg3 |= RTW_CONFIG3_PARMEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg3 &= ~RTW_CONFIG3_PARMEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_CONFIG3, cfg3);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_CONFIG3, RTW_CONFIG3);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * requires rtw_anaparm_enable(, 1)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_txdac_enable(rtw_softc_t *rsc, int enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t anaparm;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm = RTW_READ(regs, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm &= ~RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_ANAPARM, anaparm);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_access1(struct rtw_regs *regs, enum rtw_access naccess)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ASSERT(naccess >= RTW_ACCESS_NONE && naccess <= RTW_ACCESS_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ASSERT(regs->r_access >= RTW_ACCESS_NONE &&
a72f7ea693101cc48bafbb4db6bb437d828011c4ql regs->r_access <= RTW_ACCESS_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (naccess == regs->r_access)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (naccess) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_NONE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (regs->r_access) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_ANAPARM:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_anaparm_enable(regs, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_CONFIG:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_config0123_enable(regs, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_NONE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_CONFIG:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (regs->r_access) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_NONE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_config0123_enable(regs, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_CONFIG:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_ANAPARM:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_anaparm_enable(regs, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_ANAPARM:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (regs->r_access) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_NONE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_config0123_enable(regs, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_CONFIG:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_anaparm_enable(regs, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ACCESS_ANAPARM:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_access(struct rtw_regs *regs, enum rtw_access access)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access1(regs, access);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ACCESS,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: access %s -> %s\n", __func__,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_access_string(regs->r_access),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_access_string(access));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql regs->r_access = access;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_continuous_tx_enable(rtw_softc_t *rsc, int enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t tcr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr = RTW_READ(regs, RTW_TCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr &= ~RTW_TCR_LBK_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= RTW_TCR_LBK_CONT;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= RTW_TCR_LBK_NORMAL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_TCR, tcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_TCR, RTW_TCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_txdac_enable(rsc, !enable);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_NONE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_chip_reset1(struct rtw_regs *regs, const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t cr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_CR, RTW_CR_RST);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBR(regs, RTW_CR, RTW_CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < 1000; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cr = RTW_READ8(regs, RTW_CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((cr & RTW_CR_RST) == 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RESET,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: reset in %dus\n", dvname, i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_RBR(regs, RTW_CR, RTW_CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DELAY(10); /* 10us */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: reset failed\n", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (ETIMEDOUT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_chip_reset(struct rtw_regs *regs, const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBW(regs, RTW_CR, RTW_TCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rtw_chip_reset1(regs, dvname));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_disable_interrupts(struct rtw_regs *regs)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_IMR, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_ISR, 0xffff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) RTW_READ16(regs, RTW_IMR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_enable_interrupts(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_inten = RTW_INTR_RX | RTW_INTR_TX | RTW_INTR_IOERROR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_IMR, rsc->sc_inten);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_ISR, 0xffff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX necessary? */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_intr_ack != NULL)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (*rsc->sc_intr_ack)(regs);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_recall_eeprom(struct rtw_regs *regs, const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t ecr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr = RTW_READ8(regs, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr = (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_AUTOLOAD;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_9346CR, ecr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBR(regs, RTW_9346CR, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* wait 25ms for completion */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < 250; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr = RTW_READ8(regs, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((ecr & RTW_9346CR_EEM_MASK) == RTW_9346CR_EEM_NORMAL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RESET,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: recall EEPROM in %dus\n", dvname, i * 100);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_RBR(regs, RTW_9346CR, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DELAY(100);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: recall EEPROM failed\n", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (ETIMEDOUT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_reset(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rc = rtw_chip_reset(&rsc->sc_regs, "rtw");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rc != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) rtw_recall_eeprom(&rsc->sc_regs, "rtw");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_mode(struct rtw_regs *regs, int mode)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t command;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql command = RTW_READ8(regs, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql command = command &~ RTW_EPROM_CMD_OPERATING_MODE_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql command = command | (mode<<RTW_EPROM_CMD_OPERATING_MODE_SHIFT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql command = command &~ (1<<RTW_EPROM_CS_SHIFT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql command = command &~ (1<<RTW_EPROM_CK_SHIFT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_9346CR, command);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_dma_start(struct rtw_regs *regs, int priority)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t check = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql check = RTW_READ8(regs, RTW_TPPOLL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (priority) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case (0):
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_TPPOLL,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (1<< RTW_TX_DMA_POLLING_LOWPRIORITY_SHIFT) | check);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case (1):
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_TPPOLL,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (1<< RTW_TX_DMA_POLLING_NORMPRIORITY_SHIFT) | check);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case (2):
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_TPPOLL,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (1<< RTW_TX_DMA_POLLING_HIPRIORITY_SHIFT) | check);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) RTW_READ8(regs, RTW_TPPOLL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_beacon_tx_disable(struct rtw_regs *regs)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t mask = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mask |= (1 << RTW_TX_DMA_STOP_BEACON_SHIFT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_mode(regs, RTW_EPROM_CMD_CONFIG);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_TPPOLL, mask);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_mode(regs, RTW_EPROM_CMD_NORMAL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rtx_disable(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_io_enable(rsc, RTW_CR_RE|RTW_CR_TE, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) RTW_READ8(regs, RTW_CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_srom_free(struct rtw_srom *sr)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (sr->sr_content == NULL)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql kmem_free(sr->sr_content, sr->sr_size);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sr->sr_size = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sr->sr_content = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_srom_defaults(struct rtw_srom *sr, uint32_t *flags, uint8_t *cs_threshold,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql enum rtw_rfchipid *rfchipid, uint32_t *rcr)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *flags |= (RTW_F_DIGPHY|RTW_F_ANTDIV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *cs_threshold = RTW_SR_ENERGYDETTHR_DEFAULT;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *rcr |= RTW_RCR_ENCS1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *rfchipid = RTW_RFCHIPID_PHILIPS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
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{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *rfname, *paname;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql char scratch[sizeof ("unknown 0xXX")];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint16_t version;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t mac[IEEE80211_ADDR_LEN];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *flags &= ~(RTW_F_DIGPHY|RTW_F_DFLANTB|RTW_F_ANTDIV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *rcr &= ~(RTW_RCR_ENCS1 | RTW_RCR_ENCS2);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql version = RTW_SR_GET16(sr, RTW_SR_VERSION);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: SROM version %d.%d", dvname,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql version >> 8, version & 0xff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (version <= 0x0101) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_NOTE, " is not understood, limping along "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "with defaults\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_srom_defaults(sr, flags, cs_threshold, rfchipid, rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < IEEE80211_ADDR_LEN; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac[i] = RTW_SR_GET(sr, RTW_SR_MAC + i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: EEPROM MAC %s\n", dvname, mac);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *cs_threshold = RTW_SR_GET(sr, RTW_SR_ENERGYDETTHR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((RTW_SR_GET(sr, RTW_SR_CONFIG2) & RTW_CONFIG2_ANT) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *flags |= RTW_F_ANTDIV;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Note well: the sense of the RTW_SR_RFPARM_DIGPHY bit seems
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * to be reversed.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DIGPHY) == 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *flags |= RTW_F_DIGPHY;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((RTW_SR_GET(sr, RTW_SR_RFPARM) & RTW_SR_RFPARM_DFLANTB) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *flags |= RTW_F_DFLANTB;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *rcr |= LSHIFT(MASK_AND_RSHIFT(RTW_SR_GET(sr, RTW_SR_RFPARM),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SR_RFPARM_CS_MASK), RTW_RCR_ENCS1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *rfchipid = RTW_SR_GET(sr, RTW_SR_RFCHIPID);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (*rfchipid) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_GCT: /* this combo seen in the wild */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = "GCT GRF5101";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql paname = "Winspring WS9901";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_MAXIM:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = "Maxim MAX2820"; /* guess */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql paname = "Maxim MAX2422"; /* guess */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_INTERSIL:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = "Intersil HFA3873"; /* guess */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql paname = "Intersil <unknown>";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_PHILIPS: /* this combo seen in the wild */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = "Philips SA2400A";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql paname = "Philips SA2411";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_RFMD:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * this is the same front-end as an atw(4)!
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = "RFMD RF2948B, " /* mentioned in Realtek docs */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "LNA: RFMD RF2494, " /* mentioned in Realtek docs */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "SYN: Silicon Labs Si4126";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql paname = "RFMD RF2189"; /* mentioned in Realtek docs */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_RESERVED:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = paname = "reserved";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) snprintf(scratch, sizeof (scratch),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "unknown 0x%02x", *rfchipid);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rfname = paname = scratch;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_PHY, "%s: RF: %s, PA: %s\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dvname, rfname, paname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (RTW_SR_GET(sr, RTW_SR_CONFIG0) & RTW_CONFIG0_GL_MASK) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_CONFIG0_GL_USA:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_USA;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_CONFIG0_GL_EUROPE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_EUROPE;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_CONFIG0_GL_JAPAN:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_JAPAN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_UNKNOWN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Returns -1 on failure.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_srom_read(struct rtw_regs *regs, uint32_t flags, struct rtw_srom *sr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct seeprom_descriptor sd;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t ecr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) memset(&sd, 0, sizeof (sd));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr = RTW_READ8(regs, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((flags & RTW_F_9356SROM) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c56 SROM\n", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sr->sr_size = 256;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_chip = C56_66;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: 93c46 SROM\n", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sr->sr_size = 128;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_chip = C46;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr &= ~(RTW_9346CR_EEDI | RTW_9346CR_EEDO | RTW_9346CR_EESK |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_9346CR_EEM_MASK | RTW_9346CR_EECS);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ecr |= RTW_9346CR_EEM_PROGRAM;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_9346CR, ecr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sr->sr_content = kmem_zalloc(sr->sr_size, KM_SLEEP);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (sr->sr_content == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: unable to allocate SROM buffer\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (ENOMEM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) memset(sr->sr_content, 0, sr->sr_size);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
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 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_handle = regs->r_handle;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_base = regs->r_base;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_regsize = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_control_offset = RTW_9346CR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_status_offset = RTW_9346CR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_dataout_offset = RTW_9346CR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_CK = RTW_9346CR_EESK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_CS = RTW_9346CR_EECS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_DI = RTW_9346CR_EEDO;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_DO = RTW_9346CR_EEDI;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * make read_seeprom enter EEPROM read/write mode
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_MS = ecr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sd.sd_RDY = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * TBD bus barriers
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!read_seeprom(&sd, sr->sr_content, 0, sr->sr_size/2)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: could not read SROM\n", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql kmem_free(sr->sr_content, sr->sr_size);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sr->sr_content = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1); /* XXX */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * end EEPROM read/write mode
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_9346CR,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (ecr & ~RTW_9346CR_EEM_MASK) | RTW_9346CR_EEM_NORMAL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBRW(regs, RTW_9346CR, RTW_9346CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rc = rtw_recall_eeprom(regs, dvname)) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#ifdef SROM_DEBUG
a72f7ea693101cc48bafbb4db6bb437d828011c4ql {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "\n%s: serial ROM:\n\t", dvname);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < sr->sr_size/2; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "offset-0x%x: %04x", 2*i, sr->sr_content[i]);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif /* DEBUG */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_rfprog(struct rtw_regs *regs, enum rtw_rfchipid rfchipid,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t cfg4;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *method;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg4 = RTW_READ8(regs, RTW_CONFIG4) & ~RTW_CONFIG4_RFTYPE_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (rfchipid) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg4 |= LSHIFT(0, RTW_CONFIG4_RFTYPE_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql method = "fallback";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_INTERSIL:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg4 |= RTW_CONFIG4_RFTYPE_INTERSIL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql method = "Intersil";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_PHILIPS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg4 |= RTW_CONFIG4_RFTYPE_PHILIPS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql method = "Philips";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_GCT: /* XXX a guess */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_RFMD:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cfg4 |= RTW_CONFIG4_RFTYPE_RFMD;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql method = "RFMD";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_CONFIG4, cfg4);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBR(regs, RTW_CONFIG4, RTW_CONFIG4);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_INIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: %s RF programming method, %02x\n", dvname, method,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_READ8(regs, RTW_CONFIG4));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_init_channels(enum rtw_locale locale,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_channel (*chans)[IEEE80211_CHAN_MAX+1],
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *name = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define ADD_CHANNEL(_chans, _chan) { \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (*_chans)[_chan].ich_flags = IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK;\
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (*_chans)[_chan].ich_freq = \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211_ieee2mhz(_chan, (*_chans)[_chan].ich_flags);\
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (locale) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_LOCALE_USA: /* 1-11 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql name = "USA";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 1; i <= 11; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ADD_CHANNEL(chans, i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_LOCALE_JAPAN: /* 1-14 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql name = "Japan";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ADD_CHANNEL(chans, 14);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 1; i <= 14; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ADD_CHANNEL(chans, i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_LOCALE_EUROPE: /* 1-13 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql name = "Europe";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 1; i <= 13; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ADD_CHANNEL(chans, i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default: /* 10-11 allowed by most countries */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql name = "<unknown>";
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 10; i <= 11; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ADD_CHANNEL(chans, i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "%s: Geographic Location %s\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dvname, name);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#undef ADD_CHANNEL
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set80211props(struct ieee80211com *ic)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_phytype = IEEE80211_T_DS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_opmode = IEEE80211_M_STA;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_caps = IEEE80211_C_PMGT | IEEE80211_C_IBSS |
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li IEEE80211_C_SHPREAMBLE;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li /* IEEE80211_C_HOSTAP | IEEE80211_C_MONITOR | IEEE80211_C_WEP */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li ic->ic_sup_rates[IEEE80211_MODE_11B] = rtw_rateset_11b;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_identify_country(struct rtw_regs *regs, enum rtw_locale *locale,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t cfg0 = RTW_READ8(regs, RTW_CONFIG0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (cfg0 & RTW_CONFIG0_GL_MASK) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_CONFIG0_GL_USA:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_USA;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_CONFIG0_GL_JAPAN:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_JAPAN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_CONFIG0_GL_EUROPE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_EUROPE;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *locale = RTW_LOCALE_UNKNOWN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_identify_sta(struct rtw_regs *regs, uint8_t *addr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql const char *dvname)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t idr0 = RTW_READ(regs, RTW_IDR0),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql idr1 = RTW_READ(regs, RTW_IDR1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *addr = MASK_AND_RSHIFT(idr0, BITS(0, 7));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *(addr + 1) = MASK_AND_RSHIFT(idr0, BITS(8, 15));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *(addr + 2) = MASK_AND_RSHIFT(idr0, BITS(16, 23));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *(addr + 3) = MASK_AND_RSHIFT(idr0, BITS(24, 31));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *(addr + 4) = MASK_AND_RSHIFT(idr1, BITS(0, 7));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *(addr + 5) = MASK_AND_RSHIFT(idr1, BITS(8, 15));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: 802.11mac address %x:%x:%x:%x:%x:%x\n", dvname,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *addr, *(addr+1), *(addr+2), *(addr+3), *(addr+4), *(addr+5));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic uint8_t
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_chan2txpower(struct rtw_srom *sr, struct ieee80211com *ic,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_channel *chan)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t idx = RTW_SR_TXPOWER1 + ieee80211_chan2ieee(ic, chan) - 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (RTW_SR_GET(sr, idx));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rxdesc_init(rtw_softc_t *rsc, struct rtw_rxbuf *rbf, int idx, int is_last)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t ctl = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t *buf = (uint8_t *)rbf->bf_dma.mem_va;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ASSERT(rbf != NULL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rbf->rxdesc->rd_buf = (rbf->bf_dma.cookie.dmac_address);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bzero(buf, rbf->bf_dma.alength);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC(rbf->bf_dma, DDI_DMA_SYNC_FORDEV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl = (rbf->bf_dma.alength & 0xfff) | RTW_RXCTL_OWN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (is_last)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl |= RTW_RXCTL_EOR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rbf->rxdesc->rd_ctl = (ctl);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync the mbuf */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync the descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DESC_OFFSET(hd_rx, idx),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SYNC_FORDEV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_idle(struct rtw_regs *regs)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int active;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* request stop DMA; wait for packets to stop transmitting. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (active = 0; active < 300 &&
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li (RTW_READ8(regs, RTW_TPPOLL) & RTW_TPPOLL_ALL) != 0; active++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql drv_usecwait(10);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_io_enable(rtw_softc_t *rsc, uint8_t flags, int enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t cr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_IOSTATE, "%s: %s 0x%02x\n", __func__,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql enable ? "enable" : "disable", flags);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cr = RTW_READ8(regs, RTW_CR);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* The receive engine will always start at RDSAR. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (enable && (flags & ~cr & RTW_CR_RE)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DESC_OFFSET(hd_rx, 0),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SYNC_FORCPU);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->rx_next = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rxdesc_init(rsc, rsc->rxbuf_h, 0, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (enable)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cr |= flags;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cr &= ~flags;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_CR, cr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) RTW_READ8(regs, RTW_CR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Allocate an area of memory and a DMA handle for accessing it
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
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 uint_t bind_flags, dma_area_t *dma_p)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int err;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Allocate handle
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_dma_alloc_handle(devinfo, dma_attr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SLEEP, NULL, &dma_p->dma_hdl);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Allocate memory
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql alloc_flags, DDI_DMA_SLEEP, NULL, &dma_p->mem_va,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &dma_p->alength, &dma_p->acc_hdl);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Bind the two together
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->mem_va, dma_p->alength, bind_flags,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SLEEP, NULL, &dma_p->cookie, &dma_p->ncookies);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((dma_p->ncookies != 1) || (err != DDI_DMA_MAPPED))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->nslots = ~0U;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->size = ~0U;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->token = ~0U;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->offset = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_SUCCESS);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Free one allocated area of DMAable memory
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_free_dma_mem(dma_area_t *dma_p)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (dma_p->dma_hdl != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) ddi_dma_unbind_handle(dma_p->dma_hdl);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (dma_p->acc_hdl != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_dma_mem_free(&dma_p->acc_hdl);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->acc_hdl = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_dma_free_handle(&dma_p->dma_hdl);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->ncookies = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dma_p->dma_hdl = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_dma_free(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txbuf *txbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_rxbuf *rxbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i, j;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Free TX DMA buffer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_free_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql while (txbf != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_free_dma_mem(&txbf->bf_dma);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_remove(&rsc->sc_txq[i].tx_free_list, txbf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_free_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_destroy(&rsc->sc_txq[i].tx_free_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql while (txbf != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_free_dma_mem(&txbf->bf_dma);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_destroy(&rsc->sc_txq[i].tx_dirty_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_txq[i].txbuf_h != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql kmem_free(rsc->sc_txq[i].txbuf_h,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txbuf) * rtw_qlen[i]);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_txq[i].txbuf_h = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Free RX DMA buffer */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxbf = rsc->rxbuf_h;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < RTW_RXQLEN; j++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_free_dma_mem(&rxbf->bf_dma);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxbf++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->rxbuf_h != NULL) {
020c47705d28102a8df83a43ddf08e34dde21f22ql kmem_free(rsc->rxbuf_h,
020c47705d28102a8df83a43ddf08e34dde21f22ql sizeof (struct rtw_rxbuf) * RTW_RXQLEN);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->rxbuf_h = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_free_dma_mem(&rsc->sc_desc_dma);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_dma_init(dev_info_t *devinfo, rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i, j, err;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql size_t size;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t buflen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txdesc *txds;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_rxdesc *rxds;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txbuf *txbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_rxbuf *rxbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t phybaseaddr, ptx[RTW_NTXPRI], prx;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql caddr_t virbaseaddr, vtx[RTW_NTXPRI], vrx;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
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 (IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN +
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_WEP_CRCLEN), rsc->sc_cachelsz);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql size = sizeof (struct rtw_descs);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = rtw_alloc_dma_mem(devinfo, &dma_attr_desc, size,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rtw_desc_accattr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_CONSISTENT, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rsc->sc_desc_dma);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto error;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql virbaseaddr = rsc->sc_desc_dma.mem_va;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql vtx[0] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txlo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql vtx[1] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txmd));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql vtx[2] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_txhi));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql vtx[3] = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_bcn));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_DMA, "p[%d]=%x, v[%d]=%x", i, ptx[i],
a72f7ea693101cc48bafbb4db6bb437d828011c4ql i, vtx[i]);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_DMA, "ring%d:", i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_create(&rsc->sc_txq[i].tx_free_list,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txbuf),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql offsetof(struct rtw_txbuf, bf_node));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_create(&rsc->sc_txq[i].tx_dirty_list,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txbuf),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql offsetof(struct rtw_txbuf, bf_node));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* virtual address of the first descriptor */
020c47705d28102a8df83a43ddf08e34dde21f22ql rsc->sc_txq[i].txdesc_h =
020c47705d28102a8df83a43ddf08e34dde21f22ql (struct rtw_txdesc *)(uintptr_t)vtx[i];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txds = rsc->sc_txq[i].txdesc_h;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* allocate data structures to describe TX DMA buffers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql buflen = sizeof (struct rtw_txbuf) * rtw_qlen[i];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = (struct rtw_txbuf *)kmem_zalloc(buflen, KM_SLEEP);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_txq[i].txbuf_h = txbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < rtw_qlen[i]; j++, txbf++, txds++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf->txdesc = txds;
020c47705d28102a8df83a43ddf08e34dde21f22ql txbf->bf_daddr = ptx[i] + ((uintptr_t)txds -
020c47705d28102a8df83a43ddf08e34dde21f22ql (uintptr_t)rsc->sc_txq[i].txdesc_h);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* alloc DMA memory */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = rtw_alloc_dma_mem(devinfo, &dma_attr_txbuf,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_dmabuf_size,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rtw_buf_accattr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_STREAMING,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_WRITE | DDI_DMA_STREAMING,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &txbf->bf_dma);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto error;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_DMA, "pbufaddr[%d]=%x",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql j, txbf->bf_dma.cookie.dmac_address);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql prx = RTW_RING_BASE(phybaseaddr, hd_rx);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql vrx = (caddr_t)(RTW_RING_BASE(virbaseaddr, hd_rx));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* virtual address of the first descriptor */
020c47705d28102a8df83a43ddf08e34dde21f22ql rsc->rxdesc_h = (struct rtw_rxdesc *)(uintptr_t)vrx;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxds = rsc->rxdesc_h;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* allocate data structures to describe RX DMA buffers */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql buflen = sizeof (struct rtw_rxbuf) * RTW_RXQLEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxbf = (struct rtw_rxbuf *)kmem_zalloc(buflen, KM_SLEEP);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->rxbuf_h = rxbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < RTW_RXQLEN; j++, rxbf++, rxds++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxbf->rxdesc = rxds;
020c47705d28102a8df83a43ddf08e34dde21f22ql rxbf->bf_daddr =
020c47705d28102a8df83a43ddf08e34dde21f22ql prx + ((uintptr_t)rxds - (uintptr_t)rsc->rxdesc_h);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* alloc DMA memory */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = rtw_alloc_dma_mem(devinfo, &dma_attr_rxbuf,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_dmabuf_size,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rtw_buf_accattr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_STREAMING, DDI_DMA_READ | DDI_DMA_STREAMING,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rxbf->bf_dma);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto error;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_SUCCESS);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlerror:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_hwring_setup(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t phybaseaddr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
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));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->hw_start = RTW_READ(regs, RTW_TNPDA);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->hw_go = RTW_READ(regs, RTW_TNPDA);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_swring_setup(rtw_softc_t *rsc, int flag)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i, j;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int is_last;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txbuf *txbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_rxbuf *rxbf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t phybaseaddr, ptx[RTW_NTXPRI], baddr_desc, taddr_desc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql phybaseaddr = rsc->sc_desc_dma.cookie.dmac_address;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[0] = RTW_RING_BASE(phybaseaddr, hd_txlo);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[1] = RTW_RING_BASE(phybaseaddr, hd_txmd);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[2] = RTW_RING_BASE(phybaseaddr, hd_txhi);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ptx[3] = RTW_RING_BASE(phybaseaddr, hd_bcn);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC(rsc->sc_desc_dma, DDI_DMA_SYNC_FORDEV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync tx desc and tx buf */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_txq[i].tx_prod = rsc->sc_txq[i].tx_cons = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_txq[i].tx_nfree = rtw_qlen[i];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_free_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql while (txbf != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_remove(&rsc->sc_txq[i].tx_free_list, txbf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_free_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql while (txbf != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_remove(&rsc->sc_txq[i].tx_dirty_list, txbf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = list_head(&rsc->sc_txq[i].tx_dirty_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf = rsc->sc_txq[i].txbuf_h;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql baddr_desc = ptx[i];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql taddr_desc = baddr_desc + sizeof (struct rtw_txdesc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < rtw_qlen[i]; j++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_insert_tail(&rsc->sc_txq[i].tx_free_list, txbf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (j == (rtw_qlen[i] - 1)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql is_last = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql is_last = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (is_last) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf->txdesc->td_next = baddr_desc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf->txdesc->td_next = taddr_desc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf->next_bf_daddr = txbf->txdesc->td_next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC(txbf->bf_dma, DDI_DMA_SYNC_FORDEV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf->order = j;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql txbf++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql taddr_desc += sizeof (struct rtw_txdesc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!flag)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sync rx desc and rx buf */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->rx_next = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxbf = rsc->rxbuf_h;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (j = 0; j < RTW_RXQLEN; j++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC(rxbf->bf_dma, DDI_DMA_SYNC_FORCPU);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (j == (RTW_RXQLEN - 1))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql is_last = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql is_last = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rxdesc_init(rsc, rxbf, j, is_last);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rxbf++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_resume_ticks(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(&rsc->sc_regs, RTW_TINT, 0xffffffff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlconst char *
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_pwrstate_string(enum rtw_pwrstate power)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ON:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("on");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_SLEEP:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("sleep");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_OFF:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("off");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return ("unknown");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
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 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_maxim_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int before_rf, int digphy)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t anaparm;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm = RTW_READ(regs, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_OFF:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_MAXIM_OFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_SLEEP:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_MAXIM_SLEEP;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ON:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_MAXIM_ON;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_PWR,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, rtw_pwrstate_string(power),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (before_rf) ? "before" : "after", anaparm);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_ANAPARM, anaparm);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * XXX I am using the RFMD settings gleaned from the reference
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * driver. They agree
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*ARGSUSED*/
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rfmd_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int before_rf, int digphy)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t anaparm;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm = RTW_READ(regs, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_OFF:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_RFMD_OFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_SLEEP:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_RFMD_SLEEP;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ON:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_RFMD_ON;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_PWR,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, rtw_pwrstate_string(power),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (before_rf) ? "before" : "after", anaparm);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_ANAPARM, anaparm);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_philips_pwrstate(struct rtw_regs *regs, enum rtw_pwrstate power,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int before_rf, int digphy)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t anaparm;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm = RTW_READ(regs, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm &= ~(RTW_ANAPARM_RFPOW_MASK | RTW_ANAPARM_TXDACOFF);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_OFF:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_OFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_SLEEP:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_PHILIPS_SLEEP;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ON:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!before_rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (digphy) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_DIG_PHILIPS_ON;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX guess */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_TXDACOFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql anaparm |= RTW_ANAPARM_RFPOW_ANA_PHILIPS_ON;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_PWR,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: power state %s, %s RF, reg[ANAPARM] <- %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, rtw_pwrstate_string(power),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (before_rf) ? "before" : "after", anaparm);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_ANAPARM, anaparm);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_ANAPARM, RTW_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_pwrstate0(rtw_softc_t *rsc, enum rtw_pwrstate power, int before_rf,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int digphy)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (*rsc->sc_pwrstate_cb)(regs, power, before_rf, digphy);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_NONE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rf_destroy(struct rtw_rf *rf)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (*rf->rf_destroy)(rf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rf_pwrstate(struct rtw_rf *rf, enum rtw_pwrstate power)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (*rf->rf_pwrstate)(rf, power);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_pwrstate(rtw_softc_t *rsc, enum rtw_pwrstate power)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_PWR,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: %s->%s\n", __func__,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_pwrstate_string(rsc->sc_pwrstate), rtw_pwrstate_string(power));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_pwrstate == power)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_pwrstate0(rsc, power, 1, rsc->sc_flags & RTW_F_DIGPHY);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rc = rtw_rf_pwrstate(rsc->sc_rf, power);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_pwrstate0(rsc, power, 0, rsc->sc_flags & RTW_F_DIGPHY);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (power) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_ON:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD set LEDs */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_SLEEP:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_OFF:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rc == 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_pwrstate = power;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_pwrstate = RTW_OFF;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlvoid
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_disable(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rsc->sc_flags & RTW_F_ENABLED) == 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* turn off PHY */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rsc->sc_flags & RTW_F_INVALID) == 0 &&
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (rc = rtw_pwrstate(rsc, RTW_OFF)) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "failed to turn off PHY (%d)\n", rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_disable != NULL)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (*rsc->sc_disable)(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_flags &= ~RTW_F_ENABLED;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlint
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_enable(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rsc->sc_flags & RTW_F_ENABLED) == 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_enable != NULL && (*rsc->sc_enable)(rsc) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "device enable failed\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (EIO);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_flags |= RTW_F_ENABLED;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_pwrstate(rsc, RTW_ON) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "PHY turn on failed\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_set_nettype(rtw_softc_t *rsc, enum ieee80211_opmode opmode)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t msr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* I'm guessing that MSR is protected as CONFIG[0123] are. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(&rsc->sc_regs, RTW_ACCESS_CONFIG);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql msr = RTW_READ8(&rsc->sc_regs, RTW_MSR) & ~RTW_MSR_NETYPE_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (opmode) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_AHDEMO:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_IBSS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql msr |= RTW_MSR_NETYPE_ADHOC_OK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_HOSTAP:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql msr |= RTW_MSR_NETYPE_AP_OK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_STA:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql msr |= RTW_MSR_NETYPE_INFRA_OK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(&rsc->sc_regs, RTW_MSR, msr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(&rsc->sc_regs, RTW_ACCESS_NONE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_pktfilt_load(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211com *ic = &rsc->sc_ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX might be necessary to stop Rx/Tx engines while setting filters */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr &= ~RTW_RCR_PKTFILTER_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr &= ~(RTW_RCR_MXDMA_MASK | RTW_RCR_RXFTH_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_PKTFILTER_DEFAULT;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* MAC auto-reset PHY (huh?) */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_ENMARP;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* DMA whole Rx packets, only. Set Tx DMA burst size to 1024 bytes. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_RXFTH_WHOLE |RTW_RCR_MXDMA_1024;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (ic->ic_opmode) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_AHDEMO:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_IBSS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* receive broadcasts in our BSS */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_ADD3;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#if 0
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX accept all broadcast if scanning */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_AB; /* accept all broadcast */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_MAR0, 0xffffffff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_MAR1, 0xffffffff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_AM;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_MAR0, RTW_RCR); /* RTW_MAR0 < RTW_MAR1 < RTW_RCR */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_PKTFILT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "RTW_MAR0 %08x RTW_MAR1 %08x RTW_RCR %08x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_READ(regs, RTW_MAR0),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_READ(regs, RTW_MAR1), RTW_READ(regs, RTW_RCR));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_transmit_config(struct rtw_regs *regs)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t tcr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr = RTW_READ(regs, RTW_TCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= RTW_TCR_CWMIN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr &= ~RTW_TCR_MXDMA_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= RTW_TCR_MXDMA_1024;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= RTW_TCR_SAT; /* send ACK as fast as possible */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr &= ~RTW_TCR_LBK_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= RTW_TCR_LBK_NORMAL; /* normal operating mode */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* set short/long retry limits */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr &= ~(RTW_TCR_SRL_MASK|RTW_TCR_LRL_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr |= LSHIFT(0x4, RTW_TCR_SRL_MASK) | LSHIFT(0x4, RTW_TCR_LRL_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql tcr &= ~RTW_TCR_CRC; /* NIC appends CRC32 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_TCR, tcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_TCR, RTW_TCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlint
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_refine_setting(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rc = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rc = rtw_reset(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rc != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_beacon_tx_disable(regs);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_io_enable(rsc, RTW_CR_RE|RTW_CR_TE, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_mode(regs, RTW_EPROM_CMD_CONFIG);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_transmit_config(regs);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_pktfilt_load(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_CONFIG);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_TINT, 0xffffffff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_MSR, 0x0); /* no link */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_BRSR, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_ANAPARM);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_NONE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_FEMR, 0xffff);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_FEMR, RTW_FEMR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_rfprog(regs, rsc->sc_rfchipid, "rtw");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_PHYDELAY, rsc->sc_phydelay);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_CRCOUNT, RTW_CRCOUNT_MAGIC);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_mode(regs, RTW_EPROM_CMD_NORMAL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_tune(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211com *ic = &rsc->sc_ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t chan;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int antdiv = rsc->sc_flags & RTW_F_ANTDIV,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dflantb = rsc->sc_flags & RTW_F_DFLANTB;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ASSERT(ic->ic_curchan != NULL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql chan = ieee80211_chan2ieee(ic, ic->ic_curchan);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw: chan no = %x", chan);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (chan == IEEE80211_CHAN_ANY) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: chan == IEEE80211_CHAN_ANY\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (chan == rsc->sc_cur_chan) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_TUNE,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: already tuned chan %d\n", __func__, chan);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_idle(&rsc->sc_regs);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ASSERT((rsc->sc_flags & RTW_F_ENABLED) != 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rc = rtw_phy_init(&rsc->sc_regs, rsc->sc_rf,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_chan2txpower(&rsc->sc_srom, ic, ic->ic_curchan),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_csthr, ic->ic_curchan->ich_freq, antdiv,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql dflantb, RTW_ON)) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX condition on powersaving */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_NOTE, "phy init failed\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_resume_ticks(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_cur_chan = chan;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_init(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211com *ic = &rsc->sc_ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rc = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rtw_stop(rsc);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rc = rtw_enable(rsc)) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto out;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rc = rtw_refine_setting(rsc);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (rc != 0) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_swring_setup(rsc, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_hwring_setup(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(&rsc->sc_regs, RTW_BSSID16, 0x0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(&rsc->sc_regs, RTW_BSSID32, 0x0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_enable_interrupts(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_ibss_chan = &ic->ic_sup_channels[1];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_curchan = ic->ic_ibss_chan;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_TUNE, "%s: channel %d freq %d flags 0x%04x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, ieee80211_chan2ieee(ic, ic->ic_curchan),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_curchan->ich_freq, ic->ic_curchan->ich_flags);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_invalid = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4qlout:
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic struct rtw_rf *
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rf_attach(rtw_softc_t *rsc, enum rtw_rfchipid rfchipid, int digphy)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rf_write_t rf_write;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_rf *rf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rtw_host_rfio;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (rfchipid) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rf_write = rtw_rf_hostwrite;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_INTERSIL:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_PHILIPS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_GCT: /* XXX a guess */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_RFMD:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_host_rfio = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rf_write = (rtw_host_rfio) ? rtw_rf_hostwrite : rtw_rf_macwrite;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (rfchipid) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_MAXIM:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rf = rtw_max2820_create(&rsc->sc_regs, rf_write, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_pwrstate_cb = rtw_maxim_pwrstate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_PHILIPS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rf = rtw_sa2400_create(&rsc->sc_regs, rf_write, digphy);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_pwrstate_cb = rtw_philips_pwrstate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case RTW_RFCHIPID_RFMD:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX RFMD has no RF constructor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_pwrstate_cb = rtw_rfmd_pwrstate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (NULL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rf != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rf->rf_continuous_tx_cb =
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (rtw_continuous_tx_cb_t)rtw_continuous_tx_enable;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rf->rf_continuous_tx_arg = (void *)rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Revision C and later use a different PHY delay setting than
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * revisions A and B.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic uint8_t
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_check_phydelay(struct rtw_regs *regs, uint32_t rcr0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define REVAB (RTW_RCR_MXDMA_UNLIMITED | RTW_RCR_AICV)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define REVC (REVAB | RTW_RCR_RXFTH_WHOLE)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t phydelay = LSHIFT(0x6, RTW_PHYDELAY_PHYDELAY);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, REVAB);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBW(regs, RTW_RCR, RTW_RCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, REVC);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WBR(regs, RTW_RCR, RTW_RCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((RTW_READ(regs, RTW_RCR) & REVC) == REVC)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql phydelay |= RTW_PHYDELAY_REVC_MAGIC;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, rcr0); /* restore RCR */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_RCR, RTW_RCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (phydelay);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#undef REVC
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void rtw_intr_rx(rtw_softc_t *rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void rtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_get_rate(struct ieee80211com *ic)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t (*rates)[IEEE80211_RATE_MAXSIZE];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int rate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rates = &ic->ic_bss->in_rates.ir_rates;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rate = ic->ic_fixed_rate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else if (ic->ic_state == IEEE80211_S_RUN)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rate = (*rates)[ic->ic_bss->in_txrate];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rate = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rate & IEEE80211_RATE_VAL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments in:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * paylen: payload length (no FCS, no WEP header)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * hdrlen: header length
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * rate: MSDU speed, units 500kb/s
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * flags: IEEE80211_F_SHPREAMBLE (use short preamble),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * IEEE80211_F_SHSLOT (use short slot length)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments out:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
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
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_compute_duration1(int len, int use_ack, uint32_t flags, int rate,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_ieee80211_duration *d)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int pre, ctsrate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint16_t ack, bitlen, data_dur, remainder;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * RTS reserves medium for SIFS | CTS | SIFS | (DATA) | SIFS | ACK
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * DATA reserves medium for SIFS | ACK
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * XXXMYC: no ACK on multicast/broadcast or control packets
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bitlen = len * 8;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql pre = IEEE80211_DUR_DS_SIFS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((flags & IEEE80211_F_SHPREAMBLE) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql pre += IEEE80211_DUR_DS_SHORT_PREAMBLE +
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_DUR_DS_FAST_PLCPHDR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql pre += IEEE80211_DUR_DS_LONG_PREAMBLE +
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_DUR_DS_SLOW_PLCPHDR;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql d->d_residue = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql data_dur = (bitlen * 2) / rate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql remainder = (bitlen * 2) % rate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (remainder != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rate == 22)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql d->d_residue = (rate - remainder) / 16;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql data_dur++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (rate) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 2: /* 1 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 4: /* 2 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 1 - 2 Mb/s WLAN: send ACK/CTS at 1 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctsrate = 2;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 11: /* 5.5 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 22: /* 11 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 44: /* 22 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* 5.5 - 11 Mb/s WLAN: send ACK/CTS at 2 Mb/s */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctsrate = 4;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql d->d_plcp_len = data_dur;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ack = (use_ack) ? pre + (IEEE80211_DUR_DS_SLOW_ACK * 2) / ctsrate : 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql d->d_rts_dur =
a72f7ea693101cc48bafbb4db6bb437d828011c4ql pre + (IEEE80211_DUR_DS_SLOW_CTS * 2) / ctsrate +
a72f7ea693101cc48bafbb4db6bb437d828011c4ql pre + data_dur +
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ack;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql d->d_data_dur = ack;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments in:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * wh: 802.11 header
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * paylen: payload length (no FCS, no WEP header)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * rate: MSDU speed, units 500kb/s
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * fraglen: fragment length, set to maximum (or higher) for no
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * fragmentation
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * flags: IEEE80211_F_PRIVACY (hardware adds WEP),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * IEEE80211_F_SHPREAMBLE (use short preamble),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * IEEE80211_F_SHSLOT (use short slot length)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Arguments out:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * d0: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * of first/only fragment
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * dn: 802.11 Duration fields (RTS/Data), PLCP Length, Service fields
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * of first/only fragment
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_compute_duration(struct ieee80211_frame *wh, int len,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t flags, int fraglen, int rate, struct rtw_ieee80211_duration *d0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_ieee80211_duration *dn, int *npktp)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int ack, rc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int firstlen, hdrlen, lastlen, lastlen0, npkt, overlen, paylen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* don't think about addr4 here */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql hdrlen = sizeof (struct ieee80211_frame);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql paylen = len - hdrlen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((wh->i_fc[1] & IEEE80211_FC1_WEP) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql overlen = 8 + IEEE80211_CRC_LEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql paylen -= 8;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql overlen = IEEE80211_CRC_LEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql npkt = paylen / fraglen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql lastlen0 = paylen % fraglen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (npkt == 0) /* no fragments */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql lastlen = paylen + overlen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else if (lastlen0 != 0) { /* a short "tail" fragment */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql lastlen = lastlen0 + overlen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql npkt++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else /* full-length "tail" fragment */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql lastlen = fraglen + overlen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (npktp != NULL)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *npktp = npkt;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (npkt > 1)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql firstlen = fraglen + overlen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql firstlen = paylen + overlen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ack = !IEEE80211_IS_MULTICAST(wh->i_addr1) &&
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (wh->i_fc[1] & IEEE80211_FC0_TYPE_MASK) !=
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_FC0_TYPE_CTL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rc = rtw_compute_duration1(firstlen + hdrlen,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ack, flags, rate, d0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rc == -1)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (npkt <= 1) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *dn = *d0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (rtw_compute_duration1(lastlen + hdrlen, ack, flags,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rate, dn));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_assembly_80211(rtw_softc_t *rsc, struct rtw_txbuf *bf,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mblk_t *mp)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txdesc *ds;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_frame *wh;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t *buf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t ctl0 = 0, ctl1 = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int npkt, rate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_ieee80211_duration d0, dn;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int32_t iswep, pktlen, mblen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mblk_t *mp0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic = &rsc->sc_ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds = bf->txdesc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql buf = (uint8_t *)bf->bf_dma.mem_va;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bzero(buf, bf->bf_dma.alength);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bzero((uint8_t *)ds, sizeof (struct rtw_txdesc));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql wh = (struct ieee80211_frame *)mp->b_rptr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql iswep = wh->i_fc[1] & IEEE80211_FC1_WEP;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* ieee80211_crypto_encap() needs a single mblk */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mp0 = allocb(bf->bf_dma.alength, BPRI_MED);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (mp0 == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: allocb(mp) error", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (; mp != NULL; mp = mp->b_cont) {
020c47705d28102a8df83a43ddf08e34dde21f22ql mblen = (uintptr_t)mp->b_wptr - (uintptr_t)mp->b_rptr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bcopy(mp->b_rptr, mp0->b_wptr, mblen);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mp0->b_wptr += mblen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (iswep) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_key *k;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql k = ieee80211_crypto_encap(ic, mp0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (k == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: ieee80211_crypto_encap() error",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql pktlen = msgdsize(mp0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#if 0
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#endif
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV); */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (pktlen > bf->bf_dma.alength) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s: overlength packet pktlen = %d\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, pktlen);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bcopy(mp0->b_rptr, buf, pktlen);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORDEV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* setup descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 = RTW_TXCTL0_RTSRATE_1MBPS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (((ic->ic_flags & IEEE80211_F_SHPREAMBLE) != 0) &&
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (ic->ic_bss->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 |= RTW_TXCTL0_SPLCP;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX do real rate control */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_FC0_TYPE_MGT)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rate = 2;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rate = MAX(2, rtw_get_rate(ic));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 = ctl0 |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql LSHIFT(pktlen, RTW_TXCTL0_TPKTSIZE_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: rate = %d", __func__, rate);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (rate) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 2:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 |= RTW_TXCTL0_RATE_1MBPS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 4:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 |= RTW_TXCTL0_RATE_2MBPS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 11:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 |= RTW_TXCTL0_RATE_5MBPS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 22:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 |= RTW_TXCTL0_RATE_11MBPS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* XXX >= ? Compare after fragmentation? */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (pktlen > ic->ic_rtsthreshold) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 |= RTW_TXCTL0_RTSEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_NOTE, "%s: fragmentation: pktlen = %d",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, pktlen);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_FC0_TYPE_MGT) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 &= ~(RTW_TXCTL0_SPLCP | RTW_TXCTL0_RTSEN);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_FC0_SUBTYPE_BEACON)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl0 |= RTW_TXCTL0_BEACON;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_compute_duration(wh, pktlen,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_flags, ic->ic_fragthreshold,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rate, &d0, &dn, &npkt) == -1) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: fail compute duration\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
020c47705d28102a8df83a43ddf08e34dde21f22ql *(uint16_t *)(uintptr_t)wh->i_dur = (d0.d_data_dur);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl1 = LSHIFT(d0.d_plcp_len, RTW_TXCTL1_LENGTH_MASK) |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql LSHIFT(d0.d_rts_dur, RTW_TXCTL1_RTSDUR_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (d0.d_residue)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ctl1 |= RTW_TXCTL1_LENGEXT;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: duration=%x, ctl1=%x", __func__,
020c47705d28102a8df83a43ddf08e34dde21f22ql *(uint16_t *)(uintptr_t)wh->i_dur, ctl1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (bf->bf_dma.alength > RTW_TXLEN_LENGTH_MASK) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: seg too long\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (-1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_ctl0 = ctl0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_ctl0 |= RTW_TXCTL0_OWN | RTW_TXCTL0_LS | RTW_TXCTL0_FS;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_ctl1 = ctl1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_buf = bf->bf_dma.cookie.dmac_address;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_len = pktlen & 0xfff;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_next = bf->next_bf_daddr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DESC_OFFSET(hd_txmd, bf->order),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SYNC_FORDEV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "descriptor: order = %d, phy_addr=%x, ctl0=%x,"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql " ctl1=%x, buf=%x, len=%x, next=%x", bf->order,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf->bf_daddr, ds->td_ctl0, ds->td_ctl1,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_buf, ds->td_len, ds->td_next);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_pktxmt64++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_bytexmt64 += pktlen;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_node *in = ic->ic_bss;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txbuf *bf = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int ret, i = RTW_TXPRIMD;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_txlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_txq[i].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf = list_head(&rsc->sc_txq[i].tx_free_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((bf == NULL) || (rsc->sc_txq[i].tx_nfree <= 4)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: no tx buf\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_noxmtbuf++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((type & IEEE80211_FC0_TYPE_MASK) ==
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_FC0_TYPE_DATA) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "%s: need reschedule\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_need_reschedule = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txq[i].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_remove(&rsc->sc_txq[i].tx_free_list, bf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_txq[i].tx_nfree--;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* assemble 802.11 frame here */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ret = rtw_assembly_80211(rsc, bf, mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ret != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "%s assembly frame error\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txq[i].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((type & IEEE80211_FC0_TYPE_MASK) !=
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_FC0_TYPE_DATA) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_insert_tail(&rsc->sc_txq[i].tx_dirty_list, bf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf->bf_in = in;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_dma_start(&rsc->sc_regs, i);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txq[i].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic mblk_t *
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_m_tx(void *arg, mblk_t *mp)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = (ieee80211com_t *)rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mblk_t *next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ic->ic_state != IEEE80211_S_RUN) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsgchain(mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (NULL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql while (mp != NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql next = mp->b_next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mp->b_next = NULL;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_send(ic, mp, IEEE80211_FC0_TYPE_DATA)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mp->b_next = next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mp = next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_next_scan(void *arg)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_scan_id = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ic->ic_state == IEEE80211_S_SCAN) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_TUNE, "rtw_next_scan\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) ieee80211_next_scan(ic);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_join_bss(rtw_softc_t *rsc, uint8_t *bssid, uint16_t intval0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint16_t bcnitv, intval;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < IEEE80211_ADDR_LEN; i++)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_BSSID + i, bssid[i]);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_BSSID16, RTW_BSSID32);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_CONFIG);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_MSR, 0x8); /* sta mode link ok */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql intval = MIN(intval0, PRESHIFT(RTW_BCNITV_BCNITV_MASK));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bcnitv = RTW_READ16(regs, RTW_BCNITV) & ~RTW_BCNITV_BCNITV_MASK;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bcnitv |= LSHIFT(intval, RTW_BCNITV_BCNITV_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_BCNITV, bcnitv);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_ATIMWND, LSHIFT(1, RTW_ATIMWND_ATIMWND));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_ATIMTRITV, LSHIFT(2, RTW_ATIMTRITV_ATIMTRITV));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_access(regs, RTW_ACCESS_NONE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD WEP */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* RTW_WRITE8(regs, RTW_SCR, 0); */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Set the starting transmit rate for a node.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rate_ctl_start(rtw_softc_t *rsc, struct ieee80211_node *in)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = (ieee80211com_t *)rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int32_t srate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
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 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql srate = in->in_rates.ir_nrates - 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ic->ic_curmode != IEEE80211_MODE_11B) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Scan the negotiated rate set to find the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * closest rate.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* NB: the rate set is assumed sorted */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (; srate >= 0 && IEEE80211_RATE(srate) > 72;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql srate--)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
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 */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* NB: the rate set is assumed sorted */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql srate = in->in_rates.ir_nrates - 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (; srate >= 0 && IEEE80211_RATE(srate) != ic->ic_fixed_rate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql srate--)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql in->in_txrate = srate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Reset the rate control state for each 802.11 state transition.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rate_ctl_reset(rtw_softc_t *rsc, enum ieee80211_state state)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = &rsc->sc_ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211_node_t *in;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ic->ic_opmode == IEEE80211_M_STA) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Reset local xmit state; this is really only
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * meaningful when operating in station mode.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql in = (struct ieee80211_node *)ic->ic_bss;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (state == IEEE80211_S_RUN) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rate_ctl_start(rsc, in);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql in->in_txrate = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql/*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Examine and potentially adjust the transmit rate.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_rate_ctl(void *arg)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = (ieee80211com_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_node *in = ic->ic_bss;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_rateset *rs = &in->in_rates;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li int32_t mod = 1, nrate, enough;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li enough = (rsc->sc_tx_ok + rsc->sc_tx_err) >= 600? 1 : 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li /* err ratio is high -> down */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (enough && rsc->sc_tx_ok < rsc->sc_tx_err)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mod = -1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql nrate = in->in_txrate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (mod) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case -1:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (nrate > 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql nrate--;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case 1:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (nrate + 1 < rs->ir_nrates) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql nrate++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (nrate != in->in_txrate)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql in->in_txrate = nrate;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_tx_ok = rsc->sc_tx_err = rsc->sc_tx_retr = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ic->ic_state == IEEE80211_S_RUN)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql drv_usectohz(1000000));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int32_t
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_new_state(ieee80211com_t *ic, enum ieee80211_state nstate, int arg)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int error;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql enum ieee80211_state ostate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ostate = ic->ic_state;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw_new_state: ostate:0x%x, nstate:0x%x, opmode:0x%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ostate, nstate, ic->ic_opmode);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_scan_id != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) untimeout(rsc->sc_scan_id);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_scan_id = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_ratectl_id != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) untimeout(rsc->sc_ratectl_id);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_ratectl_id = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rate_ctl_reset(rsc, nstate);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ostate == IEEE80211_S_INIT && nstate != IEEE80211_S_INIT)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) rtw_pwrstate(rsc, RTW_ON);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (nstate != IEEE80211_S_INIT) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if ((error = rtw_tune(rsc)) != 0) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_exit(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li return (error);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (nstate) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_S_INIT:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_INIT\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_S_SCAN:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_SCAN\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_scan_id = timeout(rtw_next_scan, ic,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql drv_usectohz(200000));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_nettype(rsc, IEEE80211_M_MONITOR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_S_RUN:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_new_state: S_RUN\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (ic->ic_opmode) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_HOSTAP:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_IBSS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_nettype(rsc, IEEE80211_M_MONITOR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* TBD */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*FALLTHROUGH*/
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_AHDEMO:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_STA:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw_new_state: sta\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_join_bss(rsc, ic->ic_bss->in_bssid, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_ratectl_id = timeout(rtw_rate_ctl, ic,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql drv_usectohz(1000000));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_M_MONITOR:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set_nettype(rsc, ic->ic_opmode);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_S_ASSOC:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case IEEE80211_S_AUTH:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Invoke the parent method to complete the work.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql error = rsc->sc_newstate(ic, nstate, arg);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (error);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_intr_rx(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define IS_BEACON(__fc0) \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ((__fc0 & (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_MASK)) ==\
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * ratetbl[4] = {2, 4, 11, 22};
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_rxbuf *bf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_rxdesc *ds;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int hwrate, len, rssi;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t hstat, hrssi, htsftl;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int is_last, next, n = 0, i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct ieee80211_frame *wh;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = (ieee80211com_t *)rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mblk_t *mp;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV, "%s rtw_intr_rx: enter ic_state=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, rsc->sc_ic.ic_state);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->rxbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql next = rsc->rx_next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->rxbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_RXQLEN; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DESC_OFFSET(hd_rx, next),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SYNC_FORKERNEL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql n++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf = rsc->rxbuf_h + next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds = bf->rxdesc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql hstat = (ds->rd_stat);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql hrssi = ds->rd_rssi;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql htsftl = ds->rd_tsftl;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* htsfth = ds->rd_tsfth; */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV, "%s: stat=%x\n", __func__, hstat);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* still belongs to NIC */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((hstat & RTW_RXSTAT_OWN) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (n > 1) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s: n > 1\n", __func__);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DESC_OFFSET(hd_rx, 0),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_rxdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SYNC_FORCPU);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf = rsc->rxbuf_h;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds = bf->rxdesc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql hstat = (ds->rd_stat);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((hstat & RTW_RXSTAT_OWN) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql next = 0 /* RTW_RXQLEN - 1 */;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql continue;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_pktrcv64++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((hstat & RTW_RXSTAT_IOERROR) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw: DMA error/FIFO overflow %08x, "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rx descriptor %d\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql hstat & RTW_RXSTAT_IOERROR, next);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql len = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_LENGTH_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_bytercv64 += len;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* CRC is included with the packet; trim it off. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* len -= IEEE80211_CRC_LEN; */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql hwrate = MASK_AND_RSHIFT(hstat, RTW_RXSTAT_RATE_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (hwrate >= 4) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((hstat & RTW_RXSTAT_RES) != 0 &&
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_ic.ic_opmode != IEEE80211_M_MONITOR) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* if bad flags, skip descriptor */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((hstat & RTW_RXSTAT_ONESEG) != RTW_RXSTAT_ONESEG) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw too many rx segments\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_rfchipid == RTW_RFCHIPID_PHILIPS)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_RSSI);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rssi = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_IMR_RSSI);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * TBD find out each front-end's LNA gain in the
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * front-end's units
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((hrssi & RTW_RXRSSI_IMR_LNA) == 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rssi |= 0x80;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* sq = MASK_AND_RSHIFT(hrssi, RTW_RXRSSI_SQ); */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* deal with the frame itself here */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mp = allocb(rsc->sc_dmabuf_size, BPRI_MED);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (mp == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "rtw: alloc mblk error");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_norcvbuf++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql len -= IEEE80211_CRC_LEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC(bf->bf_dma, DDI_DMA_SYNC_FORKERNEL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bcopy(bf->bf_dma.mem_va, mp->b_rptr, len);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mp->b_wptr += len;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql wh = (struct ieee80211_frame *)mp->b_rptr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) ==
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_FC0_TYPE_CTL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "TYPE CTL !!\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql freemsg(mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) ieee80211_input(ic, mp, ic->ic_bss, rssi, htsftl);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlnext:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (next == 63)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql is_last = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql is_last = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rxdesc_init(rsc, bf, next, is_last);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql next = (next + 1)%RTW_RXQLEN;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_RECV, "%s: next = %d\n", __func__, next);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->rxbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->rx_next = next;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->rxbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_ring_recycling(rtw_softc_t *rsc, uint16_t isr, uint32_t pri)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txbuf *bf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_txdesc *ds;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t hstat;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t head = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t cnt = 0, idx = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_txq[pri].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql head = RTW_READ(&rsc->sc_regs, RTW_TNPDA);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (head == rsc->hw_go) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txq[pri].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "rtw_ring_recycling: enter ic_state=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_ic.ic_state);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf = list_head(&rsc->sc_txq[pri].tx_dirty_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (bf == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw_ring_recycling: dirty bf[%d] NULL\n", pri);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txq[pri].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql while ((bf != NULL) && (rsc->hw_go != head)) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cnt++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql idx = (rsc->hw_go - rsc->hw_start) / sizeof (struct rtw_txdesc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (idx == 63)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->hw_go = rsc->hw_start;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->hw_go += sizeof (struct rtw_txdesc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DESC_OFFSET(hd_txmd, idx),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SYNC_FORCPU);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT, "Head = 0x%x\n", head);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds = bf->txdesc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql hstat = (ds->td_stat);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ds->td_len = ds->td_len & 0xfff;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "%s rtw_ring_recycling: stat=%x, pri=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql __func__, hstat, pri);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (hstat & RTW_TXSTAT_TOK)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_tx_ok++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "TX err @%d, o %d, retry[%d], isr[0x%x], cnt %d\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql idx, (hstat & RTW_TXSTAT_OWN)?1:0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (hstat & RTW_TXSTAT_DRC_MASK), isr, cnt);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((hstat & RTW_TXSTAT_DRC_MASK) <= 4) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_tx_ok++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_tx_err++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_tx_retr +=
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (hstat & RTW_TXSTAT_DRC_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_xmtretry +=
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (hstat & RTW_TXSTAT_DRC_MASK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_remove(&rsc->sc_txq[pri].tx_dirty_list, bf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql list_insert_tail(&rsc->sc_txq[pri].tx_free_list,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (rsc->sc_txq[pri].tx_nfree)++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_need_reschedule == 1) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac_tx_update(rsc->sc_ic.ic_mach);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_need_reschedule = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_XMIT,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw_ring_recycling: nfree[%d]=%d\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql pri, rsc->sc_txq[pri].tx_nfree);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bzero((uint8_t *)ds, sizeof (struct rtw_txdesc));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DMA_SYNC_DESC(rsc->sc_desc_dma,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DESC_OFFSET(hd_txmd, idx),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql sizeof (struct rtw_txdesc),
a72f7ea693101cc48bafbb4db6bb437d828011c4ql DDI_DMA_SYNC_FORDEV);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bf = list_head(&rsc->sc_txq[pri].tx_dirty_list);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_txq[pri].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_intr_timeout(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_resume_ticks(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic uint_t
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_intr(caddr_t arg)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
020c47705d28102a8df83a43ddf08e34dde21f22ql /* LINTED E_BAD_PTR_CAST_ALIGN */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint16_t isr = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql isr = RTW_READ16(regs, RTW_ISR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE16(regs, RTW_ISR, isr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (isr == 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_INTR_UNCLAIMED);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#ifdef DEBUG
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#define PRINTINTR(flag) { \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((isr & flag) != 0) { \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_INTR, "|" #flag); \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } \
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rtw_dbg_flags & RTW_DEBUG_INTR) != 0 && isr != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_INTR, "rtw: reg[ISR] = %x", isr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TXFOVW);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TIMEOUT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_BCNINT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_ATIMINT);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TBDER);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TBDOK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_THPDER);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_THPDOK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TNPDER);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TNPDOK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_RXFOVW);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_RDU);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TLPDER);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_TLPDOK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_RER);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql PRINTINTR(RTW_INTR_ROK);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#undef PRINTINTR
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif /* DEBUG */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_intr++;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((isr & RTW_INTR_RX) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_intr_rx(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((isr & RTW_INTR_TIMEOUT) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_intr_timeout(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((isr & RTW_INTR_TX) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_ring_recycling(rsc, isr, 1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_INTR_CLAIMED);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Lirtw_stop(void *arg)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_disable_interrupts(regs);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_invalid = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Listatic void
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Lirtw_m_stop(void *arg)
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li{
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rtw_softc_t *rsc = (rtw_softc_t *)arg;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rtw_stop(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li/*
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * quiesce(9E) entry point.
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li *
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 * blocked.
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li *
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 */
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Liint
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Lirtw_quiesce(dev_info_t *dip)
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li{
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rtw_softc_t *rsc = NULL;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li struct rtw_regs *regs;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(dip));
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li ASSERT(rsc != NULL);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li regs = &rsc->sc_regs;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rtw_dbg_flags = 0;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rtw_disable_interrupts(regs);
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
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li return (DDI_SUCCESS);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li}
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li/*
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li * callback functions for /get/set properties
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li */
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Listatic int
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Lirtw_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li uint_t wldp_length, const void *wldp_buf)
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li{
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rtw_softc_t *rsc = (rtw_softc_t *)arg;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li struct ieee80211com *ic = &rsc->sc_ic;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li int err;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li err = ieee80211_setprop(ic, pr_name, wldp_pr_num,
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li wldp_length, wldp_buf);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li if (err == ENETRESET) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (ic->ic_des_esslen && (rsc->sc_invalid == 0)) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) rtw_init(rsc);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li }
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li err = 0;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li }
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li return (err);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li}
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Listatic int
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Lirtw_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t wldp_length, void *wldp_buf)
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li{
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li rtw_softc_t *rsc = arg;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li int err;
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li err = ieee80211_getprop(&rsc->sc_ic, pr_name, wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer wldp_length, wldp_buf);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li return (err);
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li}
94d05f6c7f329fdf908da99ab50b37d3d33f9fe5Qin Michael Li
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerrtw_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t prh)
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer{
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer rtw_softc_t *rsc = arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ieee80211_propinfo(&rsc->sc_ic, pr_name, wldp_pr_num, prh);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_m_start(void *arg)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = (ieee80211com_t *)rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int ret;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#ifdef DEBUG
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_print_regs(&rsc->sc_regs, "rtw", "rtw_start");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql#endif
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ret = rtw_init(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ret) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "rtw: failed to do rtw_init\n");
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li return (EIO);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_m_unicst(void *arg, const uint8_t *macaddr)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic = (ieee80211com_t *)rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t t;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql bcopy(macaddr, ic->ic_macaddr, 6);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ((*(macaddr + 2))<<8) | (*(macaddr + 3));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_IDR0, ntohl(t));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_IDR1, ntohl(t));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_m_promisc(void *arg, boolean_t on)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (on)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_PROMIC;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql else
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr &= ~RTW_RCR_PROMIC;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_m_multicst(void *arg, boolean_t add, const uint8_t *macaddr)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql struct rtw_regs *regs = &rsc->sc_regs;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t t;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (add) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr |= RTW_RCR_AM;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql t = ((*macaddr)<<24) | ((*(macaddr + 1))<<16) |
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ((*(macaddr + 2))<<8) | (*(macaddr + 3));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_MAR0, ntohl(t));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql t = ((*(macaddr + 4))<<24) | ((*(macaddr + 5))<<16);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_MAR1, ntohl(t));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_MAR0, RTW_RCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql } else {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr &= ~RTW_RCR_AM;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_MAR0, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_MAR1, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE(regs, RTW_RCR, rsc->sc_rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_SYNC(regs, RTW_MAR0, RTW_RCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Lirtw_m_ioctl(void* arg, queue_t *wq, mblk_t *mp)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = arg;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li struct ieee80211com *ic = &rsc->sc_ic;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li int err;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li err = ieee80211_ioctl(ic, wq, mp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err == ENETRESET) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (ic->ic_des_esslen && (rsc->sc_invalid == 0)) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) rtw_init(rsc);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) ieee80211_new_state(ic,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_S_SCAN, -1);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_m_stat(void *arg, uint_t stat, uint64_t *val)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc = (rtw_softc_t *)arg;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li ieee80211com_t *ic = &rsc->sc_ic;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li struct ieee80211_node *in = 0;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li struct ieee80211_rateset *rs = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_enter(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (stat) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case MAC_STAT_IFSPEED:
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li in = ic->ic_bss;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rs = &in->in_rates;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li *val = ((ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE) ?
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (rs->ir_rates[in->in_txrate] & IEEE80211_RATE_VAL)
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li : ic->ic_fixed_rate) / 2 * 1000000;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case MAC_STAT_NOXMTBUF:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = rsc->sc_noxmtbuf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case MAC_STAT_NORCVBUF:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = rsc->sc_norcvbuf;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case MAC_STAT_RBYTES:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = rsc->sc_bytercv64;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case MAC_STAT_IPACKETS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = rsc->sc_pktrcv64;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case MAC_STAT_OBYTES:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = rsc->sc_bytexmt64;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case MAC_STAT_OPACKETS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = rsc->sc_pktxmt64;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_TX_RETRANS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = rsc->sc_xmtretry;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_TX_FRAGS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_MCAST_TX:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_RTS_SUCCESS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_RTS_FAILURE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_ACK_FAILURE:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_RX_FRAGS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_MCAST_RX:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case WIFI_STAT_RX_DUPS:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (ieee80211_stat(ic, stat, val));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql *val = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_exit(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic void
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_mutex_destroy(rtw_softc_t *rsc)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_destroy(&rsc->rxbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_destroy(&rsc->sc_txlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql for (i = 0; i < RTW_NTXPRI; i++) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_destroy(&rsc->sc_txq[RTW_NTXPRI - 1 - i].txbuf_lock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mutex_destroy(&rsc->sc_genlock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211com_t *ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint8_t csz;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint32_t i;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql uint16_t vendor_id, device_id, command;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int32_t err;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql char strbuf[32];
a72f7ea693101cc48bafbb4db6bb437d828011c4ql wifi_data_t wd = { 0 };
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac_register_t *macp;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql int instance = ddi_get_instance(devinfo);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (cmd) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case DDI_ATTACH:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li case DDI_RESUME:
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc = ddi_get_soft_state(rtw_soft_state_p,
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li ddi_get_instance(devinfo));
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li ASSERT(rsc != NULL);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_enter(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_flags &= ~RTW_F_SUSPEND;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_exit(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if ((rsc->sc_flags & RTW_F_PLUMBED)) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li err = rtw_init(rsc);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (err == 0) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_enter(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_flags &= ~RTW_F_PLUMBED;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_exit(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li }
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li }
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li return (DDI_SUCCESS);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ddi_soft_state_zalloc(rtw_soft_state_p,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_get_instance(devinfo)) != DDI_SUCCESS) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "Unable to alloc softstate\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic = &rsc->sc_ic;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_dev = devinfo;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_regs_map_setup(devinfo, 0, (caddr_t *)&rsc->sc_cfg_base, 0, 0,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rtw_reg_accattr, &rsc->sc_cfg_handle);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "ddi_regs_map_setup() failed");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql csz = ddi_get8(rsc->sc_cfg_handle,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_CACHE_LINESZ));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!csz)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql csz = 16;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_cachelsz = csz << 2;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql vendor_id = ddi_get16(rsc->sc_cfg_handle,
020c47705d28102a8df83a43ddf08e34dde21f22ql (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_VENID));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql device_id = ddi_get16(rsc->sc_cfg_handle,
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
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Enable response to memory space accesses,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * and enabe bus master.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql command = PCI_COMM_MAE | PCI_COMM_ME;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_put16(rsc->sc_cfg_handle,
020c47705d28102a8df83a43ddf08e34dde21f22ql (uint16_t *)((uintptr_t)rsc->sc_cfg_base + PCI_CONF_COMM), command);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "set command reg to 0x%x \n", command);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_put8(rsc->sc_cfg_handle,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (uint8_t *)(rsc->sc_cfg_base + PCI_CONF_LATENCY_TIMER), 0xa8);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_regs_map_free(&rsc->sc_cfg_handle);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_regs_map_setup(devinfo, 2, (caddr_t *)&rsc->sc_regs.r_base,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql 0, 0, &rtw_reg_accattr, &rsc->sc_regs.r_handle);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "ddi_regs_map_setup() failed");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: r_base=%x, r_handle=%x\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_regs.r_base, rsc->sc_regs.r_handle);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = rtw_dma_init(devinfo, rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "failed to init dma: %d\n", err);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Stop the transmit and receive processes. First stop DMA,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * then disable receiver and transmitter.
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_WRITE8(&rsc->sc_regs, RTW_TPPOLL, RTW_TPPOLL_SALL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_io_enable(rsc, RTW_CR_RE | RTW_CR_TE, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Reset the chip to a known state. */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_reset(rsc) != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "failed to reset\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail2;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rcr = RTW_READ(&rsc->sc_regs, RTW_RCR);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((rsc->sc_rcr & RTW_RCR_9356SEL) != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_flags |= RTW_F_9356SROM;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_srom_read(&rsc->sc_regs, rsc->sc_flags, &rsc->sc_srom,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw") != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "failed to read srom\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail2;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_srom_parse(&rsc->sc_srom, &rsc->sc_flags, &rsc->sc_csthr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql &rsc->sc_rfchipid, &rsc->sc_rcr, &rsc->sc_locale,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw") != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw_attach():"
a72f7ea693101cc48bafbb4db6bb437d828011c4ql " malformed serial ROM\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail3;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_PHY, "rtw: %s PHY\n",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ((rsc->sc_flags & RTW_F_DIGPHY) != 0) ? "digital" : "analog");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_rf = rtw_rf_attach(rsc, rsc->sc_rfchipid,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_flags & RTW_F_DIGPHY);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_rf == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql cmn_err(CE_WARN, "rtw: rtw_attach(): could not attach RF\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail3;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_phydelay = rtw_check_phydelay(&rsc->sc_regs, rsc->sc_rcr);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw: PHY delay %d\n", rsc->sc_phydelay);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rsc->sc_locale == RTW_LOCALE_UNKNOWN)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_identify_country(&rsc->sc_regs, &rsc->sc_locale,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_init_channels(rsc->sc_locale, &rsc->sc_ic.ic_sup_channels,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_set80211props(ic);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (rtw_identify_sta(&rsc->sc_regs, ic->ic_macaddr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw") != 0)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail4;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_xmit = rtw_send;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211_attach(ic);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_newstate = ic->ic_newstate;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_newstate = rtw_new_state;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211_media_init(ic);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ic->ic_def_txkey = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ddi_get_iblock_cookie(devinfo, 0, &(rsc->sc_iblock))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql != DDI_SUCCESS) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "Can not get iblock cookie for INT\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail5;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
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 rsc->sc_iblock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
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
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (ddi_add_intr(devinfo, 0, &rsc->sc_iblock, NULL, rtw_intr,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (caddr_t)(rsc)) != DDI_SUCCESS) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "Can not add intr for rtw driver\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail7;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Provide initial settings for the WiFi plugin; whenever this
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * information changes, we need to call mac_plugindata_update()
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql wd.wd_opmode = ic->ic_opmode;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql wd.wd_secalloc = WIFI_SEC_NONE;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "MAC version mismatch\n");
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail8;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_driver = rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_dip = devinfo;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_src_addr = ic->ic_macaddr;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_callbacks = &rtw_m_callbacks;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_min_sdu = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_max_sdu = IEEE80211_MTU;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_pdata = &wd;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql macp->m_pdata_size = sizeof (wd);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = mac_register(macp, &ic->ic_mach);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac_free(macp);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != 0) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "mac_register err %x\n", err);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail8;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* Create minor node of type DDI_NT_NET_WIFI */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "rtw", instance);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql err = ddi_create_minor_node(devinfo, strbuf, S_IFCHR,
a72f7ea693101cc48bafbb4db6bb437d828011c4ql instance + 1, DDI_NT_NET_WIFI, 0);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (err != DDI_SUCCESS) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql RTW_DPRINTF(RTW_DEBUG_ATTACH, "WARN: rtw: rtw_attach(): "
a72f7ea693101cc48bafbb4db6bb437d828011c4ql "Create minor node failed - %d\n", err);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql goto attach_fail9;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_flags |= RTW_F_ATTACHED;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_need_reschedule = 0;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc->sc_invalid = 1;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_SUCCESS);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail9:
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li (void) mac_disable(ic->ic_mach);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) mac_unregister(ic->ic_mach);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail8:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_remove_intr(devinfo, 0, rsc->sc_iblock);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail7:
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail6:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_mutex_destroy(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail5:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211_detach(ic);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail4:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rf_destroy(rsc->sc_rf);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail3:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_srom_free(&rsc->sc_srom);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail2:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_dma_free(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail1:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_regs_map_free(&rsc->sc_regs.r_handle);
a72f7ea693101cc48bafbb4db6bb437d828011c4qlattach_fail0:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4qlstatic int32_t
a72f7ea693101cc48bafbb4db6bb437d828011c4qlrtw_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
a72f7ea693101cc48bafbb4db6bb437d828011c4ql{
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_softc_t *rsc;
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rsc = ddi_get_soft_state(rtw_soft_state_p, ddi_get_instance(devinfo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ASSERT(rsc != NULL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql switch (cmd) {
a72f7ea693101cc48bafbb4db6bb437d828011c4ql case DDI_DETACH:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql break;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li case DDI_SUSPEND:
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li ieee80211_new_state(&rsc->sc_ic, IEEE80211_S_INIT, -1);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_enter(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_flags |= RTW_F_SUSPEND;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_exit(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li if (rsc->sc_invalid == 0) {
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rtw_stop(rsc);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_enter(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li rsc->sc_flags |= RTW_F_PLUMBED;
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li mutex_exit(&rsc->sc_genlock);
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li }
9aa73b6813b3fd35e78fcc44fd17535e765e504cQin Michael Li return (DDI_SUCCESS);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql default:
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql }
a72f7ea693101cc48bafbb4db6bb437d828011c4ql if (!(rsc->sc_flags & RTW_F_ATTACHED))
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_FAILURE);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China if (mac_disable(rsc->sc_ic.ic_mach) != 0)
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China return (DDI_FAILURE);
42516a0c6ebf6e259c2abcd1ca315fec43268f39xinghua wen - Sun Microsystems - Beijing China
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /* free intterrupt resources */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_remove_intr(devinfo, 0, rsc->sc_iblock);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_mutex_destroy(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ieee80211_detach((ieee80211com_t *)rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql /*
a72f7ea693101cc48bafbb4db6bb437d828011c4ql * Unregister from the MAC layer subsystem
a72f7ea693101cc48bafbb4db6bb437d828011c4ql */
a72f7ea693101cc48bafbb4db6bb437d828011c4ql (void) mac_unregister(rsc->sc_ic.ic_mach);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_rf_destroy(rsc->sc_rf);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_srom_free(&rsc->sc_srom);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql rtw_dma_free(rsc);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_remove_minor_node(devinfo, NULL);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_regs_map_free(&rsc->sc_regs.r_handle);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql ddi_soft_state_free(rtw_soft_state_p, ddi_get_instance(devinfo));
a72f7ea693101cc48bafbb4db6bb437d828011c4ql
a72f7ea693101cc48bafbb4db6bb437d828011c4ql return (DDI_SUCCESS);
a72f7ea693101cc48bafbb4db6bb437d828011c4ql}