bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Use is subject to license terms.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Copyright(c) 2004
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
bb5e3b2f129cc39517b925419c22f69a378ec023eh *
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Redistribution and use in source and binary forms, with or without
bb5e3b2f129cc39517b925419c22f69a378ec023eh * modification, are permitted provided that the following conditions
bb5e3b2f129cc39517b925419c22f69a378ec023eh * are met:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * 1. Redistributions of source code must retain the above copyright
bb5e3b2f129cc39517b925419c22f69a378ec023eh * notice unmodified, this list of conditions, and the following
bb5e3b2f129cc39517b925419c22f69a378ec023eh * disclaimer.
bb5e3b2f129cc39517b925419c22f69a378ec023eh * 2. Redistributions in binary form must reproduce the above copyright
bb5e3b2f129cc39517b925419c22f69a378ec023eh * notice, this list of conditions and the following disclaimer in the
bb5e3b2f129cc39517b925419c22f69a378ec023eh * documentation and/or other materials provided with the distribution.
bb5e3b2f129cc39517b925419c22f69a378ec023eh *
bb5e3b2f129cc39517b925419c22f69a378ec023eh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
bb5e3b2f129cc39517b925419c22f69a378ec023eh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
bb5e3b2f129cc39517b925419c22f69a378ec023eh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
bb5e3b2f129cc39517b925419c22f69a378ec023eh * DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
bb5e3b2f129cc39517b925419c22f69a378ec023eh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
bb5e3b2f129cc39517b925419c22f69a378ec023eh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
bb5e3b2f129cc39517b925419c22f69a378ec023eh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
bb5e3b2f129cc39517b925419c22f69a378ec023eh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
bb5e3b2f129cc39517b925419c22f69a378ec023eh * SUCH DAMAGE.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/types.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/byteorder.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/conf.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/cmn_err.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/stat.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/ddi.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/sunddi.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/strsubr.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/ethernet.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <inet/common.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <inet/nd.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <inet/mi.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/note.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/stream.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/strsun.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/modctl.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/devops.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/dlpi.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_provider.h>
e7801d59e8ceda0cde8ebdfdddd7582ee2ea96efsowmini#include <net/if.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/mac_wifi.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/varargs.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/policy.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "ipw2100.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include "ipw2100_impl.h"
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <inet/wifi_ioctl.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * kCF framework include files
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/crypto/common.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh#include <sys/crypto/api.h>
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void *ipw2100_ssp = NULL;
193974072f41a843678abf5f61979c748687e66bSherry Moorestatic char ipw2100_ident[] = IPW2100_DRV_DESC;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * PIO access attribute for register
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic ddi_device_acc_attr_t ipw2100_csr_accattr = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DEVICE_ATTR_V0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_STRUCTURE_LE_ACC,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_STRICTORDER_ACC
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic ddi_device_acc_attr_t ipw2100_dma_accattr = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DEVICE_ATTR_V0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_NEVERSWAP_ACC,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_STRICTORDER_ACC
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic ddi_dma_attr_t ipw2100_dma_attr = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh DMA_ATTR_V0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x0000000000000000ULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x0000000000000004ULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0xfff,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 1,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0x00000000ffffffffULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 1,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 1,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic const struct ieee80211_rateset ipw2100_rateset_11b = { 4,
bb5e3b2f129cc39517b925419c22f69a378ec023eh {2, 4, 11, 22}
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * For mfthread only
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehextern pri_t minclsyspri;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ipw2100 specific hardware operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_hwconf_get(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_chip_reset(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_master_stop(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_stop(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_config(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_cmd(struct ipw2100_softc *sc, uint32_t type,
bb5e3b2f129cc39517b925419c22f69a378ec023eh void *buf, size_t len);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_dma_region_alloc(struct ipw2100_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct dma_region *dr, size_t size, uint_t dir, uint_t flags);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_dma_region_free(struct dma_region *dr);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_tables_init(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_ring_hwsetup(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_ring_alloc(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_ring_free(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_ring_reset(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_ring_init(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * GLD specific operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_m_stat(void *arg, uint_t stat, uint64_t *val);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_m_start(void *arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_m_stop(void *arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_m_unicst(void *arg, const uint8_t *macaddr);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_m_multicst(void *arg, boolean_t add, const uint8_t *m);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_m_promisc(void *arg, boolean_t on);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic mblk_t *ipw2100_m_tx(void *arg, mblk_t *mp);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_m_ioctl(void *arg, queue_t *wq, mblk_t *mp);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinastatic int ipw2100_m_setprop(void *arg, const char *pr_name,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China mac_prop_id_t wldp_pr_num, uint_t wldp_length, const void *wldp_buf);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinastatic int ipw2100_m_getprop(void *arg, const char *pr_name,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_id_t wldp_pr_num, uint_t wldp_length, void *wldp_buf);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void ipw2100_m_propinfo(void *, const char *, mac_prop_id_t,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer mac_prop_info_handle_t);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Interrupt and Data transferring operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint_t ipw2100_intr(caddr_t arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_send(struct ieee80211com *ic, mblk_t *mp, uint8_t type);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_rcvpkt(struct ipw2100_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_status *status, uint8_t *rxbuf);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * WiFi specific operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_newstate(struct ieee80211com *ic,
bb5e3b2f129cc39517b925419c22f69a378ec023eh enum ieee80211_state state, int arg);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void ipw2100_thread(struct ipw2100_softc *sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * IOCTL Handler
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_ioctl(struct ipw2100_softc *sc, queue_t *q, mblk_t *m);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw2100_getset(struct ipw2100_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *m, uint32_t cmd, boolean_t *need_net80211);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw_wificfg_radio(struct ipw2100_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t cmd, wldp_t *outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw_wificfg_desrates(wldp_t *outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int ipw_wificfg_disassoc(struct ipw2100_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh wldp_t *outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg/*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Suspend / Resume operations
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergstatic int ipw2100_cpr_suspend(struct ipw2100_softc *sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergstatic int ipw2100_cpr_resume(struct ipw2100_softc *sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Mac Call Back entries
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehmac_callbacks_t ipw2100_m_callbacks = {
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer MC_IOCTL | MC_SETPROP | MC_GETPROP | MC_PROPINFO,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_m_stat,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_m_start,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_m_stop,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_m_promisc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_m_multicst,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_m_unicst,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_m_tx,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer NULL,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China ipw2100_m_ioctl,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China NULL,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China NULL,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China NULL,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China ipw2100_m_setprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ipw2100_m_getprop,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ipw2100_m_propinfo
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * DEBUG Facility
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define MAX_MSG (128)
bb5e3b2f129cc39517b925419c22f69a378ec023ehuint32_t ipw2100_debug = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * supported debug marsks:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_INIT
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_GLD
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_TABLE
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_SOFTINT
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_CSR
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_INT
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_FW
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_IOCTL
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_HWCAP
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_STATISTIC
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_RING
bb5e3b2f129cc39517b925419c22f69a378ec023eh * | IPW2100_DBG_WIFI
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China * | IPW2100_DBG_BRUSSELS
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * global tuning parameters to work around unknown hardware issues
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint32_t delay_config_stable = 100000; /* 100ms */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint32_t delay_fatal_recover = 100000 * 20; /* 2s */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint32_t delay_aux_thread = 100000; /* 100ms */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehvoid
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_dbg(dev_info_t *dip, int level, const char *fmt, ...)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh va_list ap;
bb5e3b2f129cc39517b925419c22f69a378ec023eh char buf[MAX_MSG];
bb5e3b2f129cc39517b925419c22f69a378ec023eh int instance;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh va_start(ap, fmt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) vsnprintf(buf, sizeof (buf), fmt, ap);
bb5e3b2f129cc39517b925419c22f69a378ec023eh va_end(ap);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (dip) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh instance = ddi_get_instance(dip);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmn_err(level, "%s%d: %s", IPW2100_DRV_NAME, instance, buf);
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmn_err(level, "%s: %s", IPW2100_DRV_NAME, buf);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * device operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_acc_handle_t cfgh;
bb5e3b2f129cc39517b925419c22f69a378ec023eh caddr_t regs;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int instance, err, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh char strbuf[32];
bb5e3b2f129cc39517b925419c22f69a378ec023eh wifi_data_t wd = { 0 };
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_register_t *macp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg switch (cmd) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg case DDI_ATTACH:
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg break;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg case DDI_RESUME:
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc = ddi_get_soft_state(ipw2100_ssp, ddi_get_instance(dip));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg if (sc == NULL) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg err = DDI_FAILURE;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg goto fail1;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg }
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return (ipw2100_cpr_resume(sc));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_FAILURE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh instance = ddi_get_instance(dip);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_soft_state_zalloc(ipw2100_ssp, instance);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): unable to allocate soft state\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc = ddi_get_soft_state(ipw2100_ssp, instance);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dip = dip;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Map config spaces register
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_regs_map_setup(dip, IPW2100_PCI_CFG_RNUM, &regs,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0, 0, &ipw2100_csr_accattr, &cfgh);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): unable to map spaces regs\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_put8(cfgh, (uint8_t *)(regs + 0x41), 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_regs_map_free(&cfgh);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Map operating registers
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_regs_map_setup(dip, IPW2100_PCI_CSR_RNUM, &sc->sc_regs,
bb5e3b2f129cc39517b925419c22f69a378ec023eh 0, 0, &ipw2100_csr_accattr, &sc->sc_ioh);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): unable to map device regs\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Reset the chip
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_chip_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): reset failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail3;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Get the hw conf, including MAC address, then init all rings.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_hwconf_get(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_ring_init(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "unable to allocate and initialize rings\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail3;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Initialize mutexs and condvars
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_get_iblock_cookie(dip, 0, &sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): ddi_get_iblock_cookie() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail4;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * interrupt lock
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_init(&sc->sc_ilock, "interrupt-lock", MUTEX_DRIVER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void *) sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_init(&sc->sc_fw_cond, "firmware", CV_DRIVER, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_init(&sc->sc_cmd_cond, "command", CV_DRIVER, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx ring lock
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_init(&sc->sc_tx_lock, "tx-ring", MUTEX_DRIVER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void *) sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_init(&sc->sc_tx_cond, "tx-ring", CV_DRIVER, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rescheuled lock
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_init(&sc->sc_resched_lock, "reschedule-lock", MUTEX_DRIVER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void *) sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * initialize the mfthread
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_init(&sc->sc_mflock, "function-lock", MUTEX_DRIVER,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void *) sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_init(&sc->sc_mfthread_cv, NULL, CV_DRIVER, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_mf_thread = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_mfthread_switch = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Initialize the wifi part, which will be used by
bb5e3b2f129cc39517b925419c22f69a378ec023eh * generic layer
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_phytype = IEEE80211_T_DS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_opmode = IEEE80211_M_STA;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_state = IEEE80211_S_INIT;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_maxrssi = 49;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Future, could use s/w to handle encryption: IEEE80211_C_WEP
bb5e3b2f129cc39517b925419c22f69a378ec023eh * and need to add support for IEEE80211_C_IBSS
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_caps = IEEE80211_C_SHPREAMBLE | IEEE80211_C_TXPMGT |
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_C_PMGT;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_rates[IEEE80211_MODE_11B] = ipw2100_rateset_11b;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(ic->ic_macaddr, sc->sc_macaddr);
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 1; i < 16; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_chmask &(1 << i)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* IEEE80211_CHAN_B */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_freq = ieee80211_ieee2mhz(i,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_sup_channels[i].ich_flags =
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_ibss_chan = &ic->ic_sup_channels[0];
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_xmit = ipw2100_send;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * init Wifi layer
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_attach(ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Override 80211 default routines
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_media_init(ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_newstate = ic->ic_newstate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_newstate = ipw2100_newstate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * initialize default tx key
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_def_txkey = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Set the Authentication to AUTH_Open only.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_authmode = IEEE80211_AUTH_OPEN;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Add the interrupt handler
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_add_intr(dip, 0, &sc->sc_iblk, NULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_intr, (caddr_t)sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): ddi_add_intr() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail5;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Initialize pointer to device specific functions
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh wd.wd_secalloc = WIFI_SEC_NONE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh wd.wd_opmode = ic->ic_opmode;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp = mac_alloc(MAC_VERSION);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): mac_alloc() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail6;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_type_ident = MAC_PLUGIN_IDENT_WIFI;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_driver = sc;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_dip = dip;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_src_addr = ic->ic_macaddr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_callbacks = &ipw2100_m_callbacks;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_min_sdu = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_max_sdu = IEEE80211_MTU;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_pdata = &wd;
bb5e3b2f129cc39517b925419c22f69a378ec023eh macp->m_pdata_size = sizeof (wd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Register the macp to mac
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = mac_register(macp, &ic->ic_mach);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_free(macp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): mac_register() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail6;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Create minor node of type DDI_NT_NET_WIFI
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) snprintf(strbuf, sizeof (strbuf), "%s%d",
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DRV_NAME, instance);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_create_minor_node(dip, strbuf, S_IFCHR,
bb5e3b2f129cc39517b925419c22f69a378ec023eh instance + 1, DDI_NT_NET_WIFI, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_attach(): ddi_create_minor_node() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Cache firmware, always return true
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2100_cache_firmware(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Notify link is down now
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * create the mf thread to handle the link status,
bb5e3b2f129cc39517b925419c22f69a378ec023eh * recovery fatal error, etc.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_mfthread_switch = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_mf_thread == NULL)
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_thread, sc, 0, &p0, TS_RUN, minclsyspri);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail6:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_remove_intr(dip, 0, sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail5:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_detach(ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_ilock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_mfthread_cv);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_tx_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_cmd_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_fw_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail4:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_ring_free(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail3:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_regs_map_free(&sc->sc_ioh);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail2:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_free(ipw2100_ssp, instance);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail1:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc =
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_get_soft_state(ipw2100_ssp, ddi_get_instance(dip));
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ASSERT(sc != NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg switch (cmd) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg case DDI_DETACH:
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg break;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg case DDI_SUSPEND:
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return (ipw2100_cpr_suspend(sc));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Destroy the mf_thread
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_mfthread_switch = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (sc->sc_mf_thread != NULL) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (cv_wait_sig(&sc->sc_mfthread_cv, &sc->sc_mflock) == 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Unregister from the MAC layer subsystem
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = mac_unregister(sc->sc_ic.ic_mach);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_remove_intr(dip, 0, sc->sc_iblk);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * destroy the cv
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_ilock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_destroy(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_mfthread_cv);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_tx_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_cmd_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_destroy(&sc->sc_fw_cond);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * detach ieee80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_detach(&sc->sc_ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2100_free_firmware(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_ring_free(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_regs_map_free(&sc->sc_ioh);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_remove_minor_node(dip, NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_free(ipw2100_ssp, ddi_get_instance(dip));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergint
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergipw2100_cpr_suspend(struct ipw2100_softc *sc)
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg{
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "ipw2100_cpr_suspend(): enter\n"));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Destroy the mf_thread
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg mutex_enter(&sc->sc_mflock);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc->sc_mfthread_switch = 0;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg while (sc->sc_mf_thread != NULL) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg if (cv_wait_sig(&sc->sc_mfthread_cv, &sc->sc_mflock) == 0)
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg break;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg }
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg mutex_exit(&sc->sc_mflock);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * stop the hardware; this mask all interrupts
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ipw2100_stop(sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc->sc_flags &= ~IPW2100_FLAG_RUNNING;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc->sc_suspended = 1;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg (void) ipw2100_free_firmware(sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ipw2100_ring_free(sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return (DDI_SUCCESS);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg}
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergint
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldbergipw2100_cpr_resume(struct ipw2100_softc *sc)
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg{
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg struct ieee80211com *ic = &sc->sc_ic;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg dev_info_t *dip = sc->sc_dip;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg int err;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "ipw2100_cpr_resume(): enter\n"));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Reset the chip
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg err = ipw2100_chip_reset(sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg if (err != DDI_SUCCESS) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg IPW2100_WARN((dip, CE_WARN,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "ipw2100_attach(): reset failed\n"));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return (DDI_FAILURE);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg }
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Get the hw conf, including MAC address, then init all rings.
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /* ipw2100_hwconf_get(sc); */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg err = ipw2100_ring_init(sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg if (err != DDI_SUCCESS) {
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg IPW2100_WARN((dip, CE_WARN,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "ipw2100_attach(): "
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "unable to allocate and initialize rings\n"));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return (DDI_FAILURE);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg }
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Cache firmware, always return true
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg (void) ipw2100_cache_firmware(sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * Notify link is down now
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg mac_link_update(ic->ic_mach, LINK_STATE_DOWN);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * create the mf thread to handle the link status,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * recovery fatal error, etc.
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc->sc_mfthread_switch = 1;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg if (sc->sc_mf_thread == NULL)
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc->sc_mf_thread = thread_create((caddr_t)NULL, 0,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ipw2100_thread, sc, 0, &p0, TS_RUN, minclsyspri);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * enable all interrupts
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc->sc_suspended = 0;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg ipw2100_csr_put32(sc, IPW2100_CSR_INTR_MASK, IPW2100_INTR_MASK_ALL);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg /*
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg * initialize ipw2100 hardware
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg (void) ipw2100_init(sc);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg sc->sc_flags |= IPW2100_FLAG_RUNNING;
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return (DDI_SUCCESS);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg}
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev/*
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * quiesce(9E) entry point.
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * This function is called when the system is single-threaded at high
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * PIL with preemption disabled. Therefore, this function must not be
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * blocked.
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * DDI_FAILURE indicates an error condition and should almost never happen.
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * Contributed by Juergen Keil, <jk@tools.de>.
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev */
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyevstatic int
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyevipw2100_quiesce(dev_info_t *dip)
e9f896cf06d03b269a2e209d54371788c513a7dbeh{
e9f896cf06d03b269a2e209d54371788c513a7dbeh struct ipw2100_softc *sc =
e9f896cf06d03b269a2e209d54371788c513a7dbeh ddi_get_soft_state(ipw2100_ssp, ddi_get_instance(dip));
e9f896cf06d03b269a2e209d54371788c513a7dbeh
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev if (sc == NULL)
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev return (DDI_FAILURE);
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev /*
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * No more blocking is allowed while we are in the
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * quiesce(9E) entry point.
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev */
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev sc->sc_flags |= IPW2100_FLAG_QUIESCED;
e9f896cf06d03b269a2e209d54371788c513a7dbeh
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev /*
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev * Disable and mask all interrupts.
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev */
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev ipw2100_stop(sc);
e9f896cf06d03b269a2e209d54371788c513a7dbeh return (DDI_SUCCESS);
e9f896cf06d03b269a2e209d54371788c513a7dbeh}
e9f896cf06d03b269a2e209d54371788c513a7dbeh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_tables_init(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_table1_base = ipw2100_csr_get32(sc, IPW2100_CSR_TABLE1_BASE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_table2_base = ipw2100_csr_get32(sc, IPW2100_CSR_TABLE2_BASE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_stop(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_master_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RST, IPW2100_RST_SW_RESET);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2100_FLAG_FW_INITED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev if (!(sc->sc_flags & IPW2100_FLAG_QUIESCED))
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_config(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_security sec;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_wep_key wkey;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_scan_options sopt;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_configuration cfg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t data;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * operation mode
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (ic->ic_opmode) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_M_STA:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_M_HOSTAP:
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(IPW2100_MODE_BSS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_M_IBSS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_M_AHDEMO:
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(IPW2100_MODE_IBSS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting mode to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_MODE,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * operation channel if IBSS or MONITOR
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_IBSS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(ieee80211_chan2ieee(ic, ic->ic_ibss_chan));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting channel to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_CHANNEL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set MAC address
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting MAC address to "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "%02x:%02x:%02x:%02x:%02x:%02x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_macaddr[0], ic->ic_macaddr[1], ic->ic_macaddr[2],
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_macaddr[3], ic->ic_macaddr[4], ic->ic_macaddr[5]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_MAC_ADDRESS, ic->ic_macaddr,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_LEN);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * configuration capabilities
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.flags = IPW2100_CFG_BSS_MASK | IPW2100_CFG_IBSS_MASK |
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_CFG_PREAMBLE_AUTO | IPW2100_CFG_802_1x_ENABLE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_IBSS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.flags |= IPW2100_CFG_IBSS_AUTO_START;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->if_flags & IFF_PROMISC)
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.flags |= IPW2100_CFG_PROMISCUOUS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.flags = LE_32(cfg.flags);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.bss_chan = LE_32(sc->sc_chmask >> 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh cfg.ibss_chan = LE_32(sc->sc_chmask >> 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting configuration to 0x%x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(cfg.flags)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_CONFIGURATION,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &cfg, sizeof (cfg));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set 802.11 Tx rates
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(0x3); /* 1, 2 */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting 802.11 Tx rates to 0x%x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_BASIC_TX_RATES,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set 802.11b Tx rates
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(0xf); /* 1, 2, 5.5, 11 */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting 802.11b Tx rates to 0x%x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_TX_RATES, &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set power mode
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(IPW2100_POWER_MODE_CAM);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting power mode to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_POWER_MODE, &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set power index
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_IBSS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(32);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting Tx power index to %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_TX_POWER_INDEX,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set RTS threshold
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_rtsthreshold = 2346;
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(ic->ic_rtsthreshold);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting RTS threshold to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_RTS_THRESHOLD,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set frag threshold
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_fragthreshold = 2346;
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(ic->ic_fragthreshold);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting frag threshold to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_FRAG_THRESHOLD,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set ESSID
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting ESSID to %u, ESSID[0]%c\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_esslen, ic->ic_des_essid[0]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_ESSID,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_essid, ic->ic_des_esslen);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * no mandatory BSSID
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_MANDATORY_BSSID, NULL, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set BSSID, if any
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_flags & IEEE80211_F_DESBSSID) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting BSSID to %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_LEN));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_DESIRED_BSSID,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_des_bssid, IEEE80211_ADDR_LEN);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set security information
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memset(&sec, 0, sizeof (sec));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * use the value set to ic_bss to retrieve current sharedmode
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sec.authmode = (ic->ic_bss->in_authmode == WL_SHAREDKEY) ?
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_AUTH_SHARED : IPW2100_AUTH_OPEN;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sec.ciphers = LE_32(IPW2100_CIPHER_NONE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting authmode to %u\n", sec.authmode));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_SECURITY_INFORMATION,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &sec, sizeof (sec));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set WEP if any
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_flags & IEEE80211_F_PRIVACY) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IEEE80211_WEP_NKID; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_nw_keys[i].wk_keylen == 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh continue;
bb5e3b2f129cc39517b925419c22f69a378ec023eh wkey.idx = (uint8_t)i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh wkey.len = ic->ic_nw_keys[i].wk_keylen;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memset(wkey.key, 0, sizeof (wkey.key));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_nw_keys[i].wk_keylen)
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(wkey.key,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_nw_keys[i].wk_key,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_nw_keys[i].wk_keylen);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_WEP_KEY,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &wkey, sizeof (wkey));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(ic->ic_def_txkey);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_WEP_KEY_INDEX,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * turn on WEP
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32((ic->ic_flags & IEEE80211_F_PRIVACY) ? 0x8 : 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting WEP flags to %u\n", LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_WEP_FLAGS, &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set beacon interval if IBSS or HostAP
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_IBSS ||
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_opmode == IEEE80211_M_HOSTAP) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh data = LE_32(ic->ic_lintval);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Setting beacon interval to %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(data)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_BEACON_INTERVAL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &data, sizeof (data));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * set scan options
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sopt.flags = LE_32(0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sopt.channels = LE_32(sc->sc_chmask >> 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_cmd(sc, IPW2100_CMD_SET_SCAN_OPTIONS,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &sopt, sizeof (sopt));
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehen_adapter:
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_config(): Enabling adapter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ipw2100_cmd(sc, IPW2100_CMD_ENABLE, NULL, 0));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_cmd(struct ipw2100_softc *sc, uint32_t type, void *buf, size_t len)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_bd *txbd;
bb5e3b2f129cc39517b925419c22f69a378ec023eh clock_t clk;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t idx;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * prepare command buffer
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd->type = LE_32(type);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd->subtype = LE_32(0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd->seq = LE_32(0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * copy data if any
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (len && buf)
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(sc->sc_cmd->data, buf, len);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd->len = LE_32(len);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * get host & device descriptor to submit command
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_cmd(): tx-free=%d\n", sc->sc_tx_free));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command need 1 descriptor
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (sc->sc_tx_free < 1) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2100_FLAG_CMD_WAIT;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_wait(&sc->sc_tx_cond, &sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx = sc->sc_tx_cur;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_cmd(): tx-cur=%d\n", idx));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_done = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd = &sc->sc_txbd[idx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd->phyaddr = LE_32(sc->sc_dma_cmd.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd->len = LE_32(sizeof (struct ipw2100_cmd));
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd->flags = IPW2100_BD_FLAG_TX_FRAME_COMMAND
bb5e3b2f129cc39517b925419c22f69a378ec023eh | IPW2100_BD_FLAG_TX_LAST_FRAGMENT;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd->nfrag = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * sync for device
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(sc->sc_dma_cmd.dr_hnd, 0,
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2100_cmd), DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(sc->sc_dma_txbd.dr_hnd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx * sizeof (struct ipw2100_bd),
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2100_bd), DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ring move forward
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_cur = RING_FORWARD(sc->sc_tx_cur, 1, IPW2100_NUM_TXBD);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free--;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_TX_WRITE_INDEX, sc->sc_tx_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * wait for command done
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clk = drv_usectohz(1000000); /* 1 second */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_ilock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (sc->sc_done == 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * pending for the response
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (cv_reltimedwait(&sc->sc_cmd_cond, &sc->sc_ilock,
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni clk, TR_CLOCK_TICK) < 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_ilock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_cmd(): cmd-done=%s\n", sc->sc_done ? "yes" : "no"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_done == 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_init(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "ipw2100_init(): enter\n"));
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * no firmware is available, return fail directly
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!(sc->sc_flags & IPW2100_FLAG_FW_CACHED)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_init(): no firmware is available\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_chip_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_init(): could not reset adapter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * load microcode
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "ipw2100_init(): loading microcode\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_load_uc(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_init(): could not load microcode, try again\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_master_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_ring_hwsetup(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * load firmware
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg IPW2100_DBG(IPW2100_DBG_INIT, (sc->sc_dip, CE_CONT,
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg "ipw2100_init(): loading firmware\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_load_fw(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_init(): could not load firmware, try again\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * initialize tables
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_tables_init(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_table1_put32(sc, IPW2100_INFO_LOCK, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Hardware will be enabled after configuration
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_config(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_init(): device configuration failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh delay(drv_usectohz(delay_config_stable));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * get hardware configurations from EEPROM embedded within chip
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_hwconf_get(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint16_t val;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * MAC address
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh i = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2100_rom_get16(sc, IPW2100_ROM_MAC + 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val >> 8;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val & 0xff;
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2100_rom_get16(sc, IPW2100_ROM_MAC + 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val >> 8;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val & 0xff;
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2100_rom_get16(sc, IPW2100_ROM_MAC + 2);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val >> 8;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_macaddr[i++] = val & 0xff;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * formatted MAC address string
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) snprintf(sc->sc_macstr, sizeof (sc->sc_macstr),
e9f896cf06d03b269a2e209d54371788c513a7dbeh "%02x:%02x:%02x:%02x:%02x:%02x",
e9f896cf06d03b269a2e209d54371788c513a7dbeh sc->sc_macaddr[0], sc->sc_macaddr[1],
e9f896cf06d03b269a2e209d54371788c513a7dbeh sc->sc_macaddr[2], sc->sc_macaddr[3],
e9f896cf06d03b269a2e209d54371788c513a7dbeh sc->sc_macaddr[4], sc->sc_macaddr[5]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * channel mask
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2100_rom_get16(sc, IPW2100_ROM_CHANNEL_LIST);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (val == 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = 0x7ff;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_chmask = val << 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_HWCAP, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_hwconf_get(): channel-mask=0x%08x\n", sc->sc_chmask));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * radio switch
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh val = ipw2100_rom_get16(sc, IPW2100_ROM_RADIO);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (val & 0x08)
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2100_FLAG_HAS_RADIO_SWITCH;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_HWCAP, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_hwconf_get(): has-radio-switch=%s(%u)\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh (sc->sc_flags & IPW2100_FLAG_HAS_RADIO_SWITCH)? "yes" : "no",
bb5e3b2f129cc39517b925419c22f69a378ec023eh val));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * all ipw2100 interrupts will be masked by this routine
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_master_stop(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t tmp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int ntries;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * disable interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_INTR_MASK, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RST, IPW2100_RST_STOP_MASTER);
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (ntries = 0; ntries < 50; ntries++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2100_csr_get32(sc, IPW2100_CSR_RST)
bb5e3b2f129cc39517b925419c22f69a378ec023eh & IPW2100_RST_MASTER_DISABLED)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh drv_usecwait(10);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev if (ntries == 50 && !(sc->sc_flags & IPW2100_FLAG_QUIESCED))
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_master_stop(): timeout when stop master\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp = ipw2100_csr_get32(sc, IPW2100_CSR_RST);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RST,
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp | IPW2100_RST_PRINCETON_RESET);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2100_FLAG_FW_INITED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * all ipw2100 interrupts will be masked by this routine
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_chip_reset(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int ntries;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t tmp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_master_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
0778188f242b11e5d53f771c9e8a069354b3d5d4Hengqing Hu * move adapter to DO state
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp = ipw2100_csr_get32(sc, IPW2100_CSR_CTL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_CTL, tmp | IPW2100_CTL_INIT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * wait for clock stabilization
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (ntries = 0; ntries < 1000; ntries++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2100_csr_get32(sc, IPW2100_CSR_CTL)
bb5e3b2f129cc39517b925419c22f69a378ec023eh & IPW2100_CTL_CLOCK_READY)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh drv_usecwait(200);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ntries == 1000)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_FAILURE);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp = ipw2100_csr_get32(sc, IPW2100_CSR_RST);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RST, tmp | IPW2100_RST_SW_RESET);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh drv_usecwait(10);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh tmp = ipw2100_csr_get32(sc, IPW2100_CSR_CTL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_CTL, tmp | IPW2100_CTL_INIT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * get the radio status from IPW_CSR_IO, invoked by wificonfig/dladm
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_get_radio(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2100_csr_get32(sc, IPW2100_CSR_IO) & IPW2100_IO_RADIO_DISABLED)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * This function is used to get the statistic, invoked by wificonfig/dladm
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehvoid
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_get_statistics(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t addr, size, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t atbl[256], *datatbl;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh datatbl = atbl;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!(sc->sc_flags & IPW2100_FLAG_FW_INITED)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_STATISTIC, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_get_statistic(): fw doesn't download yet."));
bb5e3b2f129cc39517b925419c22f69a378ec023eh return;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_AUTOINC_ADDR, sc->sc_table1_base);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh size = ipw2100_csr_get32(sc, IPW2100_CSR_AUTOINC_DATA);
bb5e3b2f129cc39517b925419c22f69a378ec023eh atbl[0] = size;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 1, ++datatbl; i < size; i++, datatbl++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh addr = ipw2100_csr_get32(sc, IPW2100_CSR_AUTOINC_DATA);
bb5e3b2f129cc39517b925419c22f69a378ec023eh *datatbl = ipw2100_imem_get32(sc, addr);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * To retrieve the statistic information into proper places. There are
bb5e3b2f129cc39517b925419c22f69a378ec023eh * lot of information.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_STATISTIC, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_get_statistic(): \n"
bb5e3b2f129cc39517b925419c22f69a378ec023eh "operating mode = %u\n"
bb5e3b2f129cc39517b925419c22f69a378ec023eh "type of authentification= %u\n"
bb5e3b2f129cc39517b925419c22f69a378ec023eh "average RSSI= %u\n"
bb5e3b2f129cc39517b925419c22f69a378ec023eh "current channel = %d\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh atbl[191], atbl[199], atbl[173], atbl[189]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_TX_FRAGS */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_frags = (uint32_t)atbl[2];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_MCAST_TX = (all frame - unicast frame) */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_mcast = (uint32_t)atbl[2] - (uint32_t)atbl[3];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_TX_RETRANS */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_retries = (uint32_t)atbl[42];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_TX_FAILED */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_failed = (uint32_t)atbl[51];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* MAC_STAT_OBYTES */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_bytes = (uint32_t)atbl[41];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_RX_FRAGS */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_rx_frags = (uint32_t)atbl[61];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_MCAST_RX */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_rx_mcast = (uint32_t)atbl[71];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* MAC_STAT_IBYTES */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_rx_bytes = (uint32_t)atbl[101];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_ACK_FAILURE */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_ack_failure = (uint32_t)atbl[59];
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* WIFI_STAT_RTS_SUCCESS */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_rts_success = (uint32_t)atbl[22];
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * dma region alloc
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_dma_region_alloc(struct ipw2100_softc *sc,
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct dma_region *dr, size_t size, uint_t dir, uint_t flags)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh dev_info_t *dip = sc->sc_dip;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_DMA, (dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_dma_region_alloc() name=%s size=%u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh dr->dr_name, size));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_dma_alloc_handle(dip, &ipw2100_dma_attr, DDI_DMA_SLEEP, NULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &dr->dr_hnd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_DMA, (dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_dma_region_alloc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ddi_dma_alloc_handle() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_dma_mem_alloc(dr->dr_hnd, size, &ipw2100_dma_accattr,
bb5e3b2f129cc39517b925419c22f69a378ec023eh flags, DDI_DMA_SLEEP, NULL, &dr->dr_base,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &dr->dr_size, &dr->dr_acc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_DMA, (dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_dma_region_alloc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ddi_dma_mem_alloc() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ddi_dma_addr_bind_handle(dr->dr_hnd, NULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh dr->dr_base, dr->dr_size, dir | flags, DDI_DMA_SLEEP, NULL,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &dr->dr_cookie, &dr->dr_ccnt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_DMA_MAPPED) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_DMA, (dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_dma_region_alloc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ddi_dma_addr_bind_handle() failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (dr->dr_ccnt != 1) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_FAILURE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail3;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh dr->dr_pbase = dr->dr_cookie.dmac_address;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_DMA, (dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_dma_region_alloc(): get physical-base=0x%08x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh dr->dr_pbase));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail3:
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_unbind_handle(dr->dr_hnd);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail2:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_dma_mem_free(&dr->dr_acc);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail1:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_dma_free_handle(&dr->dr_hnd);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail0:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_dma_region_free(struct dma_region *dr)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_unbind_handle(dr->dr_hnd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_dma_mem_free(&dr->dr_acc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_dma_free_handle(&dr->dr_hnd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_ring_alloc(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_txbd.dr_name = "ipw2100-tx-ring-bd";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_dma_region_alloc(sc, &sc->sc_dma_txbd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_TXBD_SIZE, DDI_DMA_WRITE, DDI_DMA_CONSISTENT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx bufs
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_TXBUF; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_txbufs[i].dr_name = "ipw2100-tx-buf";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_dma_region_alloc(sc, &sc->sc_dma_txbufs[i],
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_TXBUF_SIZE, DDI_DMA_WRITE, DDI_DMA_STREAMING);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
e5a7a30b42c34918b40930de0e02883a37ef0c3dpengcheng chen - Sun Microsystems - Beijing China while (i > 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh i--;
e5a7a30b42c34918b40930de0e02883a37ef0c3dpengcheng chen - Sun Microsystems - Beijing China ipw2100_dma_region_free(&sc->sc_dma_txbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_rxbd.dr_name = "ipw2100-rx-ring-bd";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_dma_region_alloc(sc, &sc->sc_dma_rxbd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_RXBD_SIZE, DDI_DMA_WRITE, DDI_DMA_CONSISTENT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx bufs
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_RXBUF; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_rxbufs[i].dr_name = "ipw2100-rx-buf";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_dma_region_alloc(sc, &sc->sc_dma_rxbufs[i],
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_RXBUF_SIZE, DDI_DMA_READ, DDI_DMA_STREAMING);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
e5a7a30b42c34918b40930de0e02883a37ef0c3dpengcheng chen - Sun Microsystems - Beijing China while (i > 0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh i--;
e5a7a30b42c34918b40930de0e02883a37ef0c3dpengcheng chen - Sun Microsystems - Beijing China ipw2100_dma_region_free(&sc->sc_dma_rxbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail3;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * status
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_status.dr_name = "ipw2100-rx-status";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_dma_region_alloc(sc, &sc->sc_dma_status,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_STATUS_SIZE, DDI_DMA_READ, DDI_DMA_CONSISTENT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail4;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_cmd.dr_name = "ipw2100-cmd";
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_dma_region_alloc(sc, &sc->sc_dma_cmd, IPW2100_CMD_SIZE,
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DMA_WRITE, DDI_DMA_CONSISTENT);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail5;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail5:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_status);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail4:
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_RXBUF; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_rxbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail3:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_rxbd);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail2:
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_TXBUF; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_txbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail1:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_txbd);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail0:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_ring_free(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_txbd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx buf
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_TXBUF; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_txbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_rxbd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx buf
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_RXBUF; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_rxbufs[i]);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * status
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_status);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_dma_region_free(&sc->sc_dma_cmd);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_ring_reset(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_cur = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free = IPW2100_NUM_TXBD;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_txbd = (struct ipw2100_bd *)sc->sc_dma_txbd.dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_TXBUF; i++)
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_txbufs[i] =
bb5e3b2f129cc39517b925419c22f69a378ec023eh (struct ipw2100_txb *)sc->sc_dma_txbufs[i].dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rx_cur = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rx_free = IPW2100_NUM_RXBD;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_status = (struct ipw2100_status *)sc->sc_dma_status.dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rxbd = (struct ipw2100_bd *)sc->sc_dma_rxbd.dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh for (i = 0; i < IPW2100_NUM_RXBUF; i++) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rxbufs[i] =
bb5e3b2f129cc39517b925419c22f69a378ec023eh (struct ipw2100_rxb *)sc->sc_dma_rxbufs[i].dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * initialize Rx buffer descriptors, both host and device
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rxbd[i].phyaddr = LE_32(sc->sc_dma_rxbufs[i].dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rxbd[i].len = LE_32(sc->sc_dma_rxbufs[i].dr_size);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rxbd[i].flags = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rxbd[i].nfrag = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * command
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_cmd = (struct ipw2100_cmd *)sc->sc_dma_cmd.dr_base;
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx, rx rings and command initialization
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_ring_init(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_ring_alloc(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_ring_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_ring_hwsetup(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_ring_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * tx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_TX_BD_BASE, sc->sc_dma_txbd.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_TX_BD_SIZE, IPW2100_NUM_TXBD);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * no new packet to transmit, tx-rd-index == tx-wr-index
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_TX_READ_INDEX, sc->sc_tx_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_TX_WRITE_INDEX, sc->sc_tx_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * rx ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RX_BD_BASE, sc->sc_dma_rxbd.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RX_BD_SIZE, IPW2100_NUM_RXBD);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * all rx buffer are empty, rx-rd-index == 0 && rx-wr-index == N-1
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_ring_hwsetup(): rx-cur=%u, backward=%u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_rx_cur, RING_BACKWARD(sc->sc_rx_cur, 1, IPW2100_NUM_RXBD)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RX_READ_INDEX, sc->sc_rx_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RX_WRITE_INDEX,
bb5e3b2f129cc39517b925419c22f69a378ec023eh RING_BACKWARD(sc->sc_rx_cur, 1, IPW2100_NUM_RXBD));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * status
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_RX_STATUS_BASE,
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_dma_status.dr_pbase);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ieee80211_new_state() is not be used, since the hardware can handle the
bb5e3b2f129cc39517b925419c22f69a378ec023eh * state transfer. Here, we just keep the status of the hardware notification
bb5e3b2f129cc39517b925419c22f69a378ec023eh * result.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* ARGSUSED */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_newstate(struct ieee80211com *ic, enum ieee80211_state state, int arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_node *in;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t macaddr[IEEE80211_ADDR_LEN];
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t len;
bb5e3b2f129cc39517b925419c22f69a378ec023eh wifi_data_t wd = { 0 };
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_newstate(): %s -> %s\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_state_name[ic->ic_state], ieee80211_state_name[state]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (state) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_RUN:
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * we only need to use BSSID as to find the node
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh drv_usecwait(200); /* firmware needs a short delay here */
bb5e3b2f129cc39517b925419c22f69a378ec023eh len = IEEE80211_ADDR_LEN;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2100_table2_getbuf(sc, IPW2100_INFO_CURRENT_BSSID,
bb5e3b2f129cc39517b925419c22f69a378ec023eh macaddr, &len);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh in = ieee80211_find_node(&ic->ic_scan, macaddr);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (in == NULL)
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ieee80211_sta_join(ic, in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_node_authorize(in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * We can send data now; update the fastpath with our
bb5e3b2f129cc39517b925419c22f69a378ec023eh * current associated BSSID.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_flags & IEEE80211_F_PRIVACY)
bb5e3b2f129cc39517b925419c22f69a378ec023eh wd.wd_secalloc = WIFI_SEC_WEP;
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh wd.wd_secalloc = WIFI_SEC_NONE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh wd.wd_opmode = ic->ic_opmode;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(wd.wd_bssid, ic->ic_bss->in_bssid);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) mac_pdata_update(ic->ic_mach, &wd, sizeof (wd));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_INIT:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_SCAN:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_AUTH:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case IEEE80211_S_ASSOC:
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * notify to update the link
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((ic->ic_state != IEEE80211_S_RUN) && (state == IEEE80211_S_RUN)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * previously disconnected and now connected
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_linkstate = LINK_STATE_UP;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2100_FLAG_LINK_CHANGE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else if ((ic->ic_state == IEEE80211_S_RUN) &&
bb5e3b2f129cc39517b925419c22f69a378ec023eh (state != IEEE80211_S_RUN)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * previously connected andd now disconnected
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_linkstate = LINK_STATE_DOWN;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2100_FLAG_LINK_CHANGE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_state = state;
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_SUCCESS);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * GLD operations
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* ARGSUSED */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_stat(void *arg, uint_t stat, uint64_t *val)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211com_t *ic = (ieee80211com_t *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (((struct ipw2100_softc *)arg)->sc_dip,
e9f896cf06d03b269a2e209d54371788c513a7dbeh CE_CONT,
e9f896cf06d03b269a2e209d54371788c513a7dbeh "ipw2100_m_stat(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * some of below statistic data are from hardware, some from net80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (stat) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_RBYTES:
bb5e3b2f129cc39517b925419c22f69a378ec023eh *val = ic->ic_stats.is_rx_bytes;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_IPACKETS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh *val = ic->ic_stats.is_rx_frags;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_OBYTES:
bb5e3b2f129cc39517b925419c22f69a378ec023eh *val = ic->ic_stats.is_tx_bytes;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_OPACKETS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh *val = ic->ic_stats.is_tx_frags;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Get below from hardware statistic, retrieve net80211 value once 1s
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_TX_FRAGS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_MCAST_TX:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_TX_FAILED:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_TX_RETRANS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_RTS_SUCCESS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_ACK_FAILURE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_RX_FRAGS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_MCAST_RX:
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Get blow information from net80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_RTS_FAILURE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_RX_DUPS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_FCS_ERRORS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WIFI_STAT_WEP_ERRORS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ieee80211_stat(ic, stat, val));
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * need be supported in the future
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_IFSPEED:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_NOXMTBUF:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_IERRORS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case MAC_STAT_OERRORS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ENOTSUP);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* ARGSUSED */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh /* not supported */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (((struct ipw2100_softc *)arg)->sc_dip,
e9f896cf06d03b269a2e209d54371788c513a7dbeh CE_CONT,
e9f896cf06d03b269a2e209d54371788c513a7dbeh "ipw2100_m_multicst(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * This thread function is used to handle the fatal error.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_thread(struct ipw2100_softc *sc)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int32_t nlstate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int stat_cnt = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_SOFTINT, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_thread(): into ipw2100 thread--> %d\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_linkstate));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (sc->sc_mfthread_switch) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * notify the link state
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_mach && (sc->sc_flags & IPW2100_FLAG_LINK_CHANGE)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_SOFTINT, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_thread(): link status --> %d\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_linkstate));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2100_FLAG_LINK_CHANGE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh nlstate = sc->sc_linkstate;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_link_update(ic->ic_mach, nlstate);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * recovery interrupt fatal error
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_mach &&
bb5e3b2f129cc39517b925419c22f69a378ec023eh (sc->sc_flags & IPW2100_FLAG_HW_ERR_RECOVER)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_FATAL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "try to recover fatal hw error\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2100_FLAG_HW_ERR_RECOVER;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2100_init(sc); /* Force stat machine */
bb5e3b2f129cc39517b925419c22f69a378ec023eh delay(drv_usectohz(delay_fatal_recover));
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * get statistic, the value will be retrieved by m_stat
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (stat_cnt == 10) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh stat_cnt = 0; /* re-start */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_get_statistics(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else
bb5e3b2f129cc39517b925419c22f69a378ec023eh stat_cnt++; /* until 1s */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh delay(drv_usectohz(delay_aux_thread));
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_mf_thread = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cv_broadcast(&sc->sc_mfthread_cv);
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_start(void *arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_start(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * initialize ipw2100 hardware
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2100_init(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2100_FLAG_RUNNING;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * fix KCF bug. - workaround, need to fix it in net80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) crypto_mech2id(SUN_CKM_RC4);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_stop(void *arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_stop(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags &= ~IPW2100_FLAG_RUNNING;
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_unicst(void *arg, const uint8_t *macaddr)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_unicst(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_unicst(): GLD setting MAC address to "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "%02x:%02x:%02x:%02x:%02x:%02x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh macaddr[0], macaddr[1], macaddr[2],
bb5e3b2f129cc39517b925419c22f69a378ec023eh macaddr[3], macaddr[4], macaddr[5]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!IEEE80211_ADDR_EQ(ic->ic_macaddr, macaddr)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(ic->ic_macaddr, macaddr);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_flags & IPW2100_FLAG_RUNNING) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_config(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_unicst(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "device configuration failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (EIO);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_promisc(void *arg, boolean_t on)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int recfg, err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_promisc(): enter. "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "GLD setting promiscuous mode - %d\n", on));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh recfg = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (on)
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!(sc->if_flags & IFF_PROMISC)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->if_flags |= IFF_PROMISC;
bb5e3b2f129cc39517b925419c22f69a378ec023eh recfg = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->if_flags & IFF_PROMISC) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->if_flags &= ~IFF_PROMISC;
bb5e3b2f129cc39517b925419c22f69a378ec023eh recfg = 1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (recfg && (sc->sc_flags & IPW2100_FLAG_RUNNING)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ipw2100_config(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_promisc(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "device configuration failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh return (EIO);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic mblk_t *
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_tx(void *arg, mblk_t *mp)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * No data frames go out unless we're associated; this
bb5e3b2f129cc39517b925419c22f69a378ec023eh * should not happen as the 802.11 layer does not enable
bb5e3b2f129cc39517b925419c22f69a378ec023eh * the xmit queue until we enter the RUN state.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_state != IEEE80211_S_RUN) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_tx(): discard msg, ic_state = %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_state));
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsgchain(mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (mp != NULL) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh next = mp->b_next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mp->b_next = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2100_send(ic, mp, IEEE80211_FC0_TYPE_DATA) !=
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh mp->b_next = next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh mp = next;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* ARGSUSED */
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_send(ieee80211com_t *ic, mblk_t *mp, uint8_t type)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_node *in;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_frame wh, *wh_tmp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_key *k;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *hdat;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *m0, *m;
bb5e3b2f129cc39517b925419c22f69a378ec023eh size_t cnt, off;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_bd *txbd[2];
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_txb *txbuf;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct dma_region *dr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_hdr *h;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t idx, bidx;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh ASSERT(mp->b_next == NULL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh m = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((type & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_DATA) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * it is impossible to send non-data 802.11 frame in current
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ipw driver. Therefore, drop the package
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * need 2 descriptors: 1 for SEND cmd parameter header,
bb5e3b2f129cc39517b925419c22f69a378ec023eh * and the other for payload, i.e., 802.11 frame including 802.11
bb5e3b2f129cc39517b925419c22f69a378ec023eh * frame header
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_tx_free < 2) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_RING, (sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): no enough descriptors(%d)\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free));
bb5e3b2f129cc39517b925419c22f69a378ec023eh ic->ic_stats.is_tx_nobuf++; /* no enough buffer */
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2100_FLAG_TX_SCHED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_FAILURE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_RING, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): tx-free=%d,tx-curr=%d\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free, sc->sc_tx_cur));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh wh_tmp = (struct ieee80211_frame *)mp->b_rptr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh in = ieee80211_find_txnode(ic, wh_tmp->i_addr1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (in == NULL) { /* can not find tx node, drop the package */
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh in->in_inact = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ieee80211_encap(ic, mp, in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_free_node(in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (wh_tmp->i_fc[1] & IEEE80211_FC1_WEP) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * it is very bad that ieee80211_crypto_encap can only accept a
bb5e3b2f129cc39517b925419c22f69a378ec023eh * single continuous buffer.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * allocate 32 more bytes is to be compatible with further
bb5e3b2f129cc39517b925419c22f69a378ec023eh * ieee802.11i standard.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh m = allocb(msgdsize(mp) + 32, BPRI_MED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (m == NULL) { /* can not alloc buf, drop this package */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): msg allocation failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail1;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh off = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = mp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (m0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt = MBLKL(m0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (cnt) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(m->b_rptr + off, m0->b_rptr, cnt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh off += cnt;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = m0->b_cont;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh m->b_wptr += off;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "Encrypting 802.11 frame started, %d, %d\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh msgdsize(mp), MBLKL(mp)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh k = ieee80211_crypto_encap(ic, m);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (k == NULL) { /* can not get the key, drop packages */
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "Encrypting 802.11 frame failed\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = DDI_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh goto fail2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_WIFI, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "Encrypting 802.11 frame finished, %d, %d, k=0x%08x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh msgdsize(mp), MBLKL(mp), k->wk_flags));
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * header descriptor
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx = sc->sc_tx_cur;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[0] = &sc->sc_txbd[idx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((idx & 1) == 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh bidx = idx / 2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_cur = RING_FORWARD(sc->sc_tx_cur, 1, IPW2100_NUM_TXBD);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free--;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * payload descriptor
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh idx = sc->sc_tx_cur;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[1] = &sc->sc_txbd[idx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((idx & 1) == 0)
bb5e3b2f129cc39517b925419c22f69a378ec023eh bidx = idx / 2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_cur = RING_FORWARD(sc->sc_tx_cur, 1, IPW2100_NUM_TXBD);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_tx_free--;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * one buffer, SEND cmd header and payload buffer
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbuf = sc->sc_txbufs[bidx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh dr = &sc->sc_dma_txbufs[bidx];
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * extract 802.11 header from message, fill wh from m0
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh hdat = (uint8_t *)&wh;
bb5e3b2f129cc39517b925419c22f69a378ec023eh off = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (m)
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = m;
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = mp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (off < sizeof (wh)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt = MBLKL(m0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (cnt > (sizeof (wh) - off))
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt = sizeof (wh) - off;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (cnt) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(hdat + off, m0->b_rptr, cnt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh off += cnt;
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0->b_rptr += cnt;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = m0->b_cont;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * prepare SEND cmd header
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh h = &txbuf->txb_hdr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh h->type = LE_32(IPW2100_CMD_SEND);
bb5e3b2f129cc39517b925419c22f69a378ec023eh h->subtype = LE_32(0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh h->encrypted = ic->ic_flags & IEEE80211_F_PRIVACY ? 1 : 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh h->encrypt = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh h->keyidx = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh h->keysz = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh h->fragsz = LE_16(0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(h->saddr, wh.i_addr2);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_opmode == IEEE80211_M_STA)
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(h->daddr, wh.i_addr3);
bb5e3b2f129cc39517b925419c22f69a378ec023eh else
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_ADDR_COPY(h->daddr, wh.i_addr1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * extract payload from message into tx data buffer
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh off = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (m0) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh cnt = MBLKL(m0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (cnt) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(&txbuf->txb_dat[off], m0->b_rptr, cnt);
bb5e3b2f129cc39517b925419c22f69a378ec023eh off += cnt;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = m0->b_cont;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * fill SEND cmd header descriptor
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[0]->phyaddr = LE_32(dr->dr_pbase +
bb5e3b2f129cc39517b925419c22f69a378ec023eh OFFSETOF(struct ipw2100_txb, txb_hdr));
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[0]->len = LE_32(sizeof (struct ipw2100_hdr));
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[0]->flags = IPW2100_BD_FLAG_TX_FRAME_802_3 |
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_BD_FLAG_TX_NOT_LAST_FRAGMENT;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[0]->nfrag = 2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * fill payload descriptor
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[1]->phyaddr = LE_32(dr->dr_pbase +
bb5e3b2f129cc39517b925419c22f69a378ec023eh OFFSETOF(struct ipw2100_txb, txb_dat[0]));
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[1]->len = LE_32(off);
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[1]->flags = IPW2100_BD_FLAG_TX_FRAME_802_3 |
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_BD_FLAG_TX_LAST_FRAGMENT;
bb5e3b2f129cc39517b925419c22f69a378ec023eh txbd[1]->nfrag = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * dma sync
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(dr->dr_hnd, 0, sizeof (struct ipw2100_txb),
bb5e3b2f129cc39517b925419c22f69a378ec023eh DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(sc->sc_dma_txbd.dr_hnd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (txbd[0] - sc->sc_txbd) * sizeof (struct ipw2100_bd),
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2100_bd), DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * since txbd[1] may not be successive to txbd[0] due to the ring
bb5e3b2f129cc39517b925419c22f69a378ec023eh * organization, another dma_sync is needed to simplify the logic
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ddi_dma_sync(sc->sc_dma_txbd.dr_hnd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (txbd[1] - sc->sc_txbd) * sizeof (struct ipw2100_bd),
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2100_bd), DDI_DMA_SYNC_FORDEV);
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * update txcur
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_TX_WRITE_INDEX, sc->sc_tx_cur);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (mp) /* success, free the original message */
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(mp);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail2:
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (m)
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(m);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail1:
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_tx_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023ehfail0:
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_send(): exit - err=%d\n", err));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (err);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * IOCTL Handler
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IEEE80211_IOCTL_REQUIRED (1)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#define IEEE80211_IOCTL_NOT_REQUIRED (0)
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_m_ioctl(void *arg, queue_t *q, mblk_t *m)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int err;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_GLD, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_m_ioctl(): enter\n"));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * check whether or not need to handle this in net80211
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ipw2100_ioctl(sc, q, m) == IEEE80211_IOCTL_NOT_REQUIRED)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return; /* succes or fail */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh err = ieee80211_ioctl(ic, q, m);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err == ENETRESET) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_flags & IPW2100_FLAG_RUNNING) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2100_m_start(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ieee80211_new_state(ic,
bb5e3b2f129cc39517b925419c22f69a378ec023eh IEEE80211_S_SCAN, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (err == ERESTART) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (sc->sc_flags & IPW2100_FLAG_RUNNING)
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ipw2100_chip_reset(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_ioctl(struct ipw2100_softc *sc, queue_t *q, mblk_t *m)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct iocblk *iocp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t len, ret, cmd;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *m0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh boolean_t need_privilege;
bb5e3b2f129cc39517b925419c22f69a378ec023eh boolean_t need_net80211;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (MBLKL(m) < sizeof (struct iocblk)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_ioctl(): ioctl buffer too short, %u\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh MBLKL(m)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh miocnak(q, m, 0, EINVAL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (IEEE80211_IOCTL_NOT_REQUIRED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Validate the command
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh iocp = (struct iocblk *)(uintptr_t)m->b_rptr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh iocp->ioc_error = 0;
bb5e3b2f129cc39517b925419c22f69a378ec023eh cmd = iocp->ioc_cmd;
bb5e3b2f129cc39517b925419c22f69a378ec023eh need_privilege = B_TRUE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (cmd) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WLAN_SET_PARAM:
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WLAN_COMMAND:
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WLAN_GET_PARAM:
bb5e3b2f129cc39517b925419c22f69a378ec023eh need_privilege = B_FALSE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ieee80211_ioctl(): unknown cmd 0x%x", cmd));
bb5e3b2f129cc39517b925419c22f69a378ec023eh miocnak(q, m, 0, EINVAL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (IEEE80211_IOCTL_NOT_REQUIRED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy if (need_privilege && (ret = secpolicy_dl_config(iocp->ioc_cr)) != 0) {
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy miocnak(q, m, 0, ret);
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy return (IEEE80211_IOCTL_NOT_REQUIRED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
eae72b5b807baa9116e64502cbb278edf15f3146Sebastien Roy
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * sanity check
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 = m->b_cont;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (iocp->ioc_count == 0 || iocp->ioc_count < sizeof (wldp_t) ||
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0 == NULL) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh miocnak(q, m, 0, EINVAL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (IEEE80211_IOCTL_NOT_REQUIRED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * assuming single data block
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (m0->b_cont) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh freemsg(m0->b_cont);
bb5e3b2f129cc39517b925419c22f69a378ec023eh m0->b_cont = NULL;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh need_net80211 = B_FALSE;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = ipw2100_getset(sc, m0, cmd, &need_net80211);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!need_net80211) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh len = msgdsize(m0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_ioctl(): go to call miocack with "
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ret = %d, len = %d\n", ret, len));
bb5e3b2f129cc39517b925419c22f69a378ec023eh miocack(q, m, len, ret);
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (IEEE80211_IOCTL_NOT_REQUIRED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * IEEE80211_IOCTL_REQUIRED - need net80211 handle
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (IEEE80211_IOCTL_REQUIRED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_getset(struct ipw2100_softc *sc, mblk_t *m, uint32_t cmd,
bb5e3b2f129cc39517b925419c22f69a378ec023eh boolean_t *need_net80211)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh wldp_t *infp, *outfp;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t id;
bb5e3b2f129cc39517b925419c22f69a378ec023eh int ret; /* IEEE80211_IOCTL - handled by net80211 */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh infp = (wldp_t *)(uintptr_t)m->b_rptr;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh outfp = (wldp_t *)(uintptr_t)m->b_rptr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_result = WL_NOTSUPPORTED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh id = infp->wldp_id;
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_IOCTL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_getset(): id = 0x%x\n", id));
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (id) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * which is not supported by net80211, so it
bb5e3b2f129cc39517b925419c22f69a378ec023eh * has to be handled from driver side
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WL_RADIO:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = ipw_wificfg_radio(sc, cmd, outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * so far, drier doesn't support fix-rates
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WL_DESIRED_RATES:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = ipw_wificfg_desrates(outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * current net80211 implementation clears the bssid while
bb5e3b2f129cc39517b925419c22f69a378ec023eh * this command received, which will result in the all zero
bb5e3b2f129cc39517b925419c22f69a378ec023eh * mac address for scan'ed AP which is just disconnected.
bb5e3b2f129cc39517b925419c22f69a378ec023eh * This is a workaround solution until net80211 find a
bb5e3b2f129cc39517b925419c22f69a378ec023eh * better method.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WL_DISASSOCIATE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = ipw_wificfg_disassoc(sc, outfp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * The wifi IOCTL net80211 supported:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_ESSID:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_BSSID:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_WEP_KEY_TAB:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_WEP_KEY_ID:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_AUTH_MODE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_ENCRYPTION:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_BSS_TYPE:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_ESS_LIST:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_LINKSTATUS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_RSSI:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_SCAN:
bb5e3b2f129cc39517b925419c22f69a378ec023eh * case WL_LOAD_DEFAULTS:
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh /*
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh * When radio is off, need to ignore all ioctl. What need to
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh * do is to check radio status firstly. If radio is ON, pass
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh * it to net80211, otherwise, return to upper layer directly.
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh *
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh * Considering the WL_SUCCESS also means WL_CONNECTED for
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh * checking linkstatus, one exception for WL_LINKSTATUS is to
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh * let net80211 handle it.
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh */
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh if ((ipw2100_get_radio(sc) == 0) &&
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh (id != WL_LINKSTATUS)) {
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh IPW2100_REPORT((sc->sc_dip, CE_WARN,
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh "ipw: RADIO is OFF\n"));
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh outfp->wldp_length = WIFI_BUF_OFFSET;
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh outfp->wldp_result = WL_SUCCESS;
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh ret = 0;
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh break;
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh }
9e2cd38c103ae52a41b09823a11c9b5c059555f0eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh *need_net80211 = B_TRUE; /* let net80211 do the rest */
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * we will overwrite everything
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh m->b_wptr = m->b_rptr + outfp->wldp_length;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ret);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China/*
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China * Call back functions for get/set proporty
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China */
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinastatic int
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinaipw2100_m_getprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer uint_t wldp_length, void *wldp_buf)
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China{
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China int err = 0;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China switch (wldp_pr_num) {
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China /* mac_prop_id */
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China case MAC_PROP_WL_DESIRED_RATES:
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China IPW2100_DBG(IPW2100_DBG_BRUSSELS, (sc->sc_dip, CE_CONT,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China "ipw2100_m_getprop(): Not Support DESIRED_RATES\n"));
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China break;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China case MAC_PROP_WL_RADIO:
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China *(wl_linkstatus_t *)wldp_buf = ipw2100_get_radio(sc);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China break;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China default:
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China /* go through net80211 */
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer err = ieee80211_getprop(ic, pr_name, wldp_pr_num,
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer wldp_length, wldp_buf);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China break;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China }
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China return (err);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China}
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyerstatic void
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyeripw2100_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 struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer struct ieee80211com *ic = &sc->sc_ic;
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer ieee80211_propinfo(ic, pr_name, wldp_pr_num, prh);
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer}
0dc2366f7b9f9f36e10909b1e95edbf2a261c2acVenugopal Iyer
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinastatic int
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing Chinaipw2100_m_setprop(void *arg, const char *pr_name, mac_prop_id_t wldp_pr_num,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China uint_t wldp_length, const void *wldp_buf)
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China{
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China struct ipw2100_softc *sc = (struct ipw2100_softc *)arg;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China struct ieee80211com *ic = &sc->sc_ic;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China int err;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China switch (wldp_pr_num) {
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China /* mac_prop_id */
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China case MAC_PROP_WL_DESIRED_RATES:
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China IPW2100_DBG(IPW2100_DBG_BRUSSELS, (sc->sc_dip, CE_CONT,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China "ipw2100_m_setprop(): Not Support DESIRED_RATES\n"));
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China err = ENOTSUP;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China break;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China case MAC_PROP_WL_RADIO:
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China IPW2100_DBG(IPW2100_DBG_BRUSSELS, (sc->sc_dip, CE_CONT,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China "ipw2100_m_setprop(): Not Support RADIO\n"));
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China err = ENOTSUP;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China break;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China default:
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China /* go through net80211 */
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China err = ieee80211_setprop(ic, pr_name, wldp_pr_num, wldp_length,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China wldp_buf);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China break;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China }
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China if (err == ENETRESET) {
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China if (sc->sc_flags & IPW2100_FLAG_RUNNING) {
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China (void) ipw2100_m_start(sc);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China (void) ieee80211_new_state(ic,
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China IEEE80211_S_SCAN, -1);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China }
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China err = 0;
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China }
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China return (err);
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China}
7efa17f5f4c3cc113e1b0a1e86f43d4bf2ede8fafei feng - Sun Microsystems - Beijing China
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw_wificfg_radio(struct ipw2100_softc *sc, uint32_t cmd, wldp_t *outfp)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t ret = ENOTSUP;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh switch (cmd) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WLAN_GET_PARAM:
bb5e3b2f129cc39517b925419c22f69a378ec023eh *(wl_linkstatus_t *)(outfp->wldp_buf) = ipw2100_get_radio(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_length = WIFI_BUF_OFFSET + sizeof (wl_linkstatus_t);
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_result = WL_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh ret = 0; /* command sucess */
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh case WLAN_SET_PARAM:
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (ret);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw_wificfg_desrates(wldp_t *outfp)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * return success, but with result NOTSUPPORTED
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_length = WIFI_BUF_OFFSET;
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_result = WL_NOTSUPPORTED;
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic int
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw_wificfg_disassoc(struct ipw2100_softc *sc, wldp_t *outfp)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * init the state
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_state != IEEE80211_S_INIT) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * return success always
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_length = WIFI_BUF_OFFSET;
bb5e3b2f129cc39517b925419c22f69a378ec023eh outfp->wldp_result = WL_SUCCESS;
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh/* End of IOCTL Handler */
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_fix_channel(struct ieee80211com *ic, mblk_t *m)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_frame *wh;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t subtype;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *frm, *efrm;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh wh = (struct ieee80211_frame *)m->b_rptr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_MGT)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (subtype != IEEE80211_FC0_SUBTYPE_BEACON &&
bb5e3b2f129cc39517b925419c22f69a378ec023eh subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * assume the message contains only 1 block
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh frm = (uint8_t *)(wh + 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh efrm = (uint8_t *)m->b_wptr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh frm += 12; /* skip tstamp, bintval and capinfo fields */
bb5e3b2f129cc39517b925419c22f69a378ec023eh while (frm < efrm) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (*frm == IEEE80211_ELEMID_DSPARMS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh#if IEEE80211_CHAN_MAX < 255
e9f896cf06d03b269a2e209d54371788c513a7dbeh if (frm[2] <= IEEE80211_CHAN_MAX)
bb5e3b2f129cc39517b925419c22f69a378ec023eh#endif
e9f896cf06d03b269a2e209d54371788c513a7dbeh {
e9f896cf06d03b269a2e209d54371788c513a7dbeh ic->ic_curchan = &ic->ic_sup_channels[frm[2]];
e9f896cf06d03b269a2e209d54371788c513a7dbeh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh frm += frm[1] + 2;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic void
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_rcvpkt(struct ipw2100_softc *sc, struct ipw2100_status *status,
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *rxbuf)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mblk_t *m;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_frame *wh = (struct ieee80211_frame *)rxbuf;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211_node *in;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t rlen;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh in = ieee80211_find_rxnode(ic, wh);
bb5e3b2f129cc39517b925419c22f69a378ec023eh rlen = LE_32(status->len);
bb5e3b2f129cc39517b925419c22f69a378ec023eh m = allocb(rlen, BPRI_MED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (m) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) memcpy(m->b_wptr, rxbuf, rlen);
bb5e3b2f129cc39517b925419c22f69a378ec023eh m->b_wptr += rlen;
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ic->ic_state == IEEE80211_S_SCAN)
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_fix_channel(ic, m);
bb5e3b2f129cc39517b925419c22f69a378ec023eh (void) ieee80211_input(ic, m, in, status->rssi, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh } else
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_WARN((sc->sc_dip, CE_WARN,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_rcvpkg(): cannot allocate receive message(%u)\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh LE_32(status->len)));
bb5e3b2f129cc39517b925419c22f69a378ec023eh ieee80211_free_node(in);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic uint_t
bb5e3b2f129cc39517b925419c22f69a378ec023ehipw2100_intr(caddr_t arg)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
922d2c76afbee21520ffa2088c4e60dcb80d3945eh struct ipw2100_softc *sc = (struct ipw2100_softc *)(uintptr_t)arg;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t ireg, ridx, len, i;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ieee80211com *ic = &sc->sc_ic;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_status *status;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint8_t *rxbuf;
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct dma_region *dr;
bb5e3b2f129cc39517b925419c22f69a378ec023eh uint32_t state;
bb5e3b2f129cc39517b925419c22f69a378ec023eh#if DEBUG
bb5e3b2f129cc39517b925419c22f69a378ec023eh struct ipw2100_bd *rxbd;
bb5e3b2f129cc39517b925419c22f69a378ec023eh#endif
bb5e3b2f129cc39517b925419c22f69a378ec023eh
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg if (sc->sc_suspended)
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg return (DDI_INTR_UNCLAIMED);
0f1b305ee9e700c825d9e9ad1ea1e4311d212eb2Seth Goldberg
bb5e3b2f129cc39517b925419c22f69a378ec023eh ireg = ipw2100_csr_get32(sc, IPW2100_CSR_INTR);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (!(ireg & IPW2100_INTR_MASK_ALL))
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_INTR_UNCLAIMED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * mask all interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_INTR_MASK, 0);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * acknowledge all fired interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_INTR, ireg);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_INT, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_intr(): interrupt is fired. int=0x%08x\n", ireg));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (ireg & IPW2100_INTR_MASK_ERR) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_FATAL, (sc->sc_dip, CE_CONT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh "ipw2100_intr(): interrupt is fired, MASK = 0x%08x\n",
bb5e3b2f129cc39517b925419c22f69a378ec023eh ireg));
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * inform mfthread to recover hw error
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_enter(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh sc->sc_flags |= IPW2100_FLAG_HW_ERR_RECOVER;
bb5e3b2f129cc39517b925419c22f69a378ec023eh mutex_exit(&sc->sc_mflock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh goto enable_interrupt;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * FW intr
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2100_INTR_FW_INIT_DONE) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_flags |= IPW2100_FLAG_FW_INITED;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh cv_signal(&sc->sc_fw_cond);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * RX intr
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2100_INTR_RX_TRANSFER) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx = ipw2100_csr_get32(sc,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2100_CSR_RX_READ_INDEX);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh for (; sc->sc_rx_cur != ridx;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_rx_cur = RING_FORWARD(
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_rx_cur, 1, IPW2100_NUM_RXBD)) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh i = sc->sc_rx_cur;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh status = &sc->sc_status[i];
922d2c76afbee21520ffa2088c4e60dcb80d3945eh rxbuf = &sc->sc_rxbufs[i]->rxb_dat[0];
922d2c76afbee21520ffa2088c4e60dcb80d3945eh dr = &sc->sc_dma_rxbufs[i];
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * sync
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (void) ddi_dma_sync(sc->sc_dma_status.dr_hnd,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh i * sizeof (struct ipw2100_status),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sizeof (struct ipw2100_status),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh DDI_DMA_SYNC_FORKERNEL);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (void) ddi_dma_sync(sc->sc_dma_rxbd.dr_hnd,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh i * sizeof (struct ipw2100_bd),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sizeof (struct ipw2100_bd),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh DDI_DMA_SYNC_FORKERNEL);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh (void) ddi_dma_sync(dr->dr_hnd, 0,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sizeof (struct ipw2100_rxb),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh DDI_DMA_SYNC_FORKERNEL);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2100_DBG(IPW2100_DBG_INT, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2100_intr(): status code=0x%04x, len=0x%08x, "
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "flags=0x%02x, rssi=%02x\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh LE_16(status->code), LE_32(status->len),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh status->flags, status->rssi));
bb5e3b2f129cc39517b925419c22f69a378ec023eh#if DEBUG
922d2c76afbee21520ffa2088c4e60dcb80d3945eh rxbd = &sc->sc_rxbd[i];
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2100_DBG(IPW2100_DBG_INT, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2100_intr(): rxbd,phyaddr=0x%08x, len=0x%08x, "
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "flags=0x%02x,nfrag=%02x\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh LE_32(rxbd->phyaddr), LE_32(rxbd->len),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh rxbd->flags, rxbd->nfrag));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh#endif
922d2c76afbee21520ffa2088c4e60dcb80d3945eh switch (LE_16(status->code) & 0x0f) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * command complete response
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATUS_CODE_COMMAND:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_done = 1;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh cv_signal(&sc->sc_cmd_cond);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_ilock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * change state
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATUS_CODE_NEWSTATE:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh state = LE_32(* ((uint32_t *)(uintptr_t)rxbuf));
bb5e3b2f129cc39517b925419c22f69a378ec023eh IPW2100_DBG(IPW2100_DBG_INT,
bb5e3b2f129cc39517b925419c22f69a378ec023eh (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2100_intr(): newstate,state=0x%x\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh state));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh switch (state) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATE_ASSOCIATED:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ieee80211_new_state(ic,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IEEE80211_S_RUN, -1);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATE_ASSOCIATION_LOST:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATE_DISABLED:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ieee80211_new_state(ic,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IEEE80211_S_INIT, -1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * When radio is OFF, need a better
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * scan approach to ensure scan
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * result correct.
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATE_RADIO_DISABLED:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2100_REPORT((sc->sc_dip, CE_WARN,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2100_intr(): RADIO is OFF\n"));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2100_stop(sc);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATE_SCAN_COMPLETE:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ieee80211_cancel_scan(ic);
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATE_SCANNING:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ic->ic_state != IEEE80211_S_RUN)
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ieee80211_new_state(ic,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IEEE80211_S_SCAN, -1);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ic->ic_flags |= IEEE80211_F_SCAN;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh default:
bb5e3b2f129cc39517b925419c22f69a378ec023eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATUS_CODE_DATA_802_11:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATUS_CODE_DATA_802_3:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2100_rcvpkt(sc, status, rxbuf);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh case IPW2100_STATUS_CODE_NOTIFICATION:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh default:
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2100_WARN((sc->sc_dip, CE_WARN,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2100_intr(): "
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "unknown status code 0x%04x\n",
922d2c76afbee21520ffa2088c4e60dcb80d3945eh LE_16(status->code)));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh break;
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * write sc_rx_cur backward 1 step to RX_WRITE_INDEX
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ipw2100_csr_put32(sc, IPW2100_CSR_RX_WRITE_INDEX,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh RING_BACKWARD(sc->sc_rx_cur, 1, IPW2100_NUM_RXBD));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh /*
922d2c76afbee21520ffa2088c4e60dcb80d3945eh * TX intr
922d2c76afbee21520ffa2088c4e60dcb80d3945eh */
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (ireg & IPW2100_INTR_TX_TRANSFER) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_tx_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx = ipw2100_csr_get32(sc, IPW2100_CSR_TX_READ_INDEX);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh len = RING_FLEN(RING_FORWARD(sc->sc_tx_cur,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_tx_free, IPW2100_NUM_TXBD),
922d2c76afbee21520ffa2088c4e60dcb80d3945eh ridx, IPW2100_NUM_TXBD);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_tx_free += len;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh IPW2100_DBG(IPW2100_DBG_INT, (sc->sc_dip, CE_CONT,
922d2c76afbee21520ffa2088c4e60dcb80d3945eh "ipw2100_intr(): len=%d\n", len));
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_tx_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_enter(&sc->sc_resched_lock);
922d2c76afbee21520ffa2088c4e60dcb80d3945eh if (len > 1 && (sc->sc_flags & IPW2100_FLAG_TX_SCHED)) {
922d2c76afbee21520ffa2088c4e60dcb80d3945eh sc->sc_flags &= ~IPW2100_FLAG_TX_SCHED;
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mac_tx_update(ic->ic_mach);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
922d2c76afbee21520ffa2088c4e60dcb80d3945eh mutex_exit(&sc->sc_resched_lock);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
922d2c76afbee21520ffa2088c4e60dcb80d3945ehenable_interrupt:
bb5e3b2f129cc39517b925419c22f69a378ec023eh /*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * enable all interrupts
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_csr_put32(sc, IPW2100_CSR_INTR_MASK, IPW2100_INTR_MASK_ALL);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (DDI_INTR_CLAIMED);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh/*
bb5e3b2f129cc39517b925419c22f69a378ec023eh * Module Loading Data & Entry Points
bb5e3b2f129cc39517b925419c22f69a378ec023eh */
bb5e3b2f129cc39517b925419c22f69a378ec023ehDDI_DEFINE_STREAM_OPS(ipw2100_devops, nulldev, nulldev, ipw2100_attach,
799aa485da68fdaa1850eaf833ad108e5af82adbKonstantin Ananyev ipw2100_detach, nodev, NULL, D_MP, NULL, ipw2100_quiesce);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic struct modldrv ipw2100_modldrv = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh &mod_driverops,
bb5e3b2f129cc39517b925419c22f69a378ec023eh ipw2100_ident,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &ipw2100_devops
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehstatic struct modlinkage ipw2100_modlinkage = {
bb5e3b2f129cc39517b925419c22f69a378ec023eh MODREV_1,
bb5e3b2f129cc39517b925419c22f69a378ec023eh &ipw2100_modldrv,
bb5e3b2f129cc39517b925419c22f69a378ec023eh NULL
bb5e3b2f129cc39517b925419c22f69a378ec023eh};
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023eh_init(void)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int status;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh status = ddi_soft_state_init(&ipw2100_ssp,
bb5e3b2f129cc39517b925419c22f69a378ec023eh sizeof (struct ipw2100_softc), 1);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (status != DDI_SUCCESS)
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (status);
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_init_ops(&ipw2100_devops, IPW2100_DRV_NAME);
bb5e3b2f129cc39517b925419c22f69a378ec023eh status = mod_install(&ipw2100_modlinkage);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (status != DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_fini_ops(&ipw2100_devops);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_fini(&ipw2100_ssp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (status);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023eh_fini(void)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh int status;
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh status = mod_remove(&ipw2100_modlinkage);
bb5e3b2f129cc39517b925419c22f69a378ec023eh if (status == DDI_SUCCESS) {
bb5e3b2f129cc39517b925419c22f69a378ec023eh mac_fini_ops(&ipw2100_devops);
bb5e3b2f129cc39517b925419c22f69a378ec023eh ddi_soft_state_fini(&ipw2100_ssp);
bb5e3b2f129cc39517b925419c22f69a378ec023eh }
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (status);
bb5e3b2f129cc39517b925419c22f69a378ec023eh}
bb5e3b2f129cc39517b925419c22f69a378ec023eh
bb5e3b2f129cc39517b925419c22f69a378ec023ehint
bb5e3b2f129cc39517b925419c22f69a378ec023eh_info(struct modinfo *mip)
bb5e3b2f129cc39517b925419c22f69a378ec023eh{
bb5e3b2f129cc39517b925419c22f69a378ec023eh return (mod_info(&ipw2100_modlinkage, mip));
bb5e3b2f129cc39517b925419c22f69a378ec023eh}